【问题标题】:How to create a collection that is "owned" by an object?如何创建一个对象“拥有”的集合?
【发布时间】:2011-05-26 16:17:52
【问题描述】:

从这个问题开始Good class design by example我有一个后续问题。

我想创建一些属于其他对象的集合。回顾一下,我有一个Person 课程,我希望Person 能够拥有一个或多个Addresses。所以我想我会创建一个Address 类和一个Addresses 集合。说得通?到目前为止,这是我的代码

class Person
{
    public Person(int SSN, string firstName, string lastName)
    {
        this.SSN = SSN;
        FirstName = firstName;
        LastName = lastName;
    }

    public int SSN { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Address
{
    public Address(string line1, string postCode)
    {
        Line1 = line1;
        PostCode = postCode;
    }

    public int ID { get; set; }
    public string Line1 { get; set; }
    public string PostCode { get; set; }
}

class Addresses : System.Collections.CollectionBase
{
    public int Person { get; set; } // should this be of type Person?

    public void Add(Address addy)
    {
        List.Add(addy);
    }

    public Address Item(int Index)
    {
        return (Address)List[Index];
    }

    public void Remove(int index)
    {
        List.RemoveAt(index);            
    }
}

如何将多个地址与一个人相关联?我想在Main做这样的事情:

Person p = new Person(123,"Marilyn","Manson");
Address a = new Address("Somewhere", "blahblah");
p.Addresses.Add(a);

然后我希望能够将地址保存到数据库中。我应该使用Address.Save() 还是Addresses.Save()(或其他方式)?

我将如何更改我的代码来实现它?感谢观看。

【问题讨论】:

  • 一个人有一个地址。我不知道一个地址应该有一个人。
  • 使用泛型来避免痛苦

标签: c# c#-4.0


【解决方案1】:

如果你想要一个人拥有的地址,这个人应该包括一个地址集合

class Person 
{     
     <all the stuff you have>
     List<Address> Addresses;
}

不要忘记在构造函数中新建它,

然后添加一个你刚才的地址

Address addressInstance = new Address(){...};
PersonInstance.Addresses.Add( addressInstance );

卡尔-

【讨论】:

    【解决方案2】:

    如果 Person “拥有”地址,它应该公开一个 Addresses 属性。这可以是 ReadonlyCollection&lt;Address&gt; 类型 - 无需创建您自己的集合类型。

    public Person  {
      private List<Address> _addresses;
      public ReadonlyCollection<Address> Addresses {
        get { return _addresses.AsReadOnly(); }
      }
      public void AddAddress(Address address) {
        _addresses.Add(address);
      }
    }
    

    如果您正在考虑良好的类设计,请三思而后行是否每个属性都需要一个 setter。也许您希望您的对象是不可变的,在这种情况下您需要私有设置器。

    “保存”将遵循“ActiveRecord”模式。更常见的,例如当使用像 NHibernate 这样的 ORM 时,您的对象会跨越一些边界,表明它已被存储。在 NHibernate 中,这称为 Session,它负责根据可用信息保存对象。

    【讨论】:

      【解决方案3】:

      每个地址都应该保存()。您的地址可以保存,这将调用它的每个孩子的保存。

      您可能希望拥有一个具有可枚举状态的基类,这样您就可以拥有 New、Modified、UnModified 和 Deleted,以便您可以选择调用 CRUD 的哪一部分。有些人将其拆分为布尔值、isNew、isModified、isDeleted。

      【讨论】:

      • 好的,谢谢,是的。关于一个人对地址的“所有权”有什么想法吗?
      • 如果两个人的地址相同怎么办?您将有一个指向同一实例的引用对象...如果您注意到 ZIP 发生了变化,那么与该地址关联的所有人员都会发生变化。你不希望父母拥有孩子。孩子是他们自己的对象,最终可能会有自己的孩子(也许我做了一个比喻)。
      • 对不起,我不明白你在问什么。正如 Eric 所提到的,Person 将有一组地址。我没有注意到您的对象中缺少它。
      • 我同意上述 Dan H 的观点,因为地址应该对保存数据一无所知。当您将地址提供给银行时,他们会要求您在他们的系统上获取地址吗?
      【解决方案4】:

      这取决于您的架构...但是,为了保存地址,我不会使用 Address 对象来执行此操作。这是您的 POCO(普通旧 CLR 对象),它不应该知道 DAL。另一个类应该处理 CRUD(创建读取更新删除)操作,它应该是与 DAL 交互的业务层的一部分。也许称它为 AddressComponent.cs?这是一种领域模型模式方法。

      对于地址集合,您可以按照 flq 的说明进行操作,并将其作为属性...除非您需要额外的逻辑,否则实际上不需要另一个名为 Addresses.cs 的对象。

      【讨论】:

        【解决方案5】:

        我会使用泛型来派生 List(或任何其他集合类)

        // This class add just an Owner (parent) to the list
        public class OwnedList<T> : List<T>
        {
            public Object Owner { set; get; }
        
            public OwnedList(Object owner)
            {
                Owner = owner;
            }
        }
        

        然后在你的类中传递对象本身:

        class Contact
        {
            public int Person { get; set; }
        
            private OwnedList<Address> _Addresses;
            public OwnedList<Address> Addresses
            {
                get
                {
                    if (_Addresses == null)
                    {
                        _Addresses = new OwnedList<Address>(this);
                    }
                    return _Addresses;
                }
        
                set
                {
                    _Addresses = value;
                    _Addresses.Owner = this;
                }
            }       
        }
        

        【讨论】:

          猜你喜欢
          • 2011-12-22
          • 1970-01-01
          • 2020-09-10
          • 2017-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-18
          相关资源
          最近更新 更多