代码之家  ›  专栏  ›  技术社区  ›  Eric

私有集属性;

  •  45
  • Eric  · 技术社区  · 16 年前

    我知道它只允许类设置它,但是有什么意义呢?

    如何解决具有只读ID的问题?

    假设我有个人课:

    public class Person
        {
            public string Name { get;  set; }
            public int Id { get; private set; }
            public int Age { get; set; }
        }
    

    这是在一个 Entities.dll ,由GUI、BL和DAL使用。

    GUI调用BL:

       List<Person> p =  BL.PeopleBL.GetPeople();
    

    为了这个例子,我们称之为DAL:

    ...
    while(dr.read())
    {
        returnPersonList.add( new Person{ Age=dr.GetInt32(1), Id=dr.GetInt32(0), Name=dr.GetString(2)})
    }
    ...
    

    当然,我不能这样做,因为ID是一个私有集; 正确的方法是什么?

    如何让BL/DAL设置ID,而不是在GUI上?

    或者这甚至不是一个私有集的正确使用?


    我只是想补充一下,这是您典型的数据库应用程序,其中pk是ID,不应该更改(仅由bl/dal)


    9 回复  |  直到 10 年前
        1
  •  36
  •   Danny Beckett    12 年前

    这是一个可能的解决方案,尽管不是很干净:

    1. 使您需要暴露在BAL&DAL中的属性 internal
    2. 作记号 BAL.dll 和; DAL.dll 内部可见 在里面 assemblyinfo.cs

    public class Person
    {
        public Person(int id)
        {
             this.Id=id;
        }
    
        public string Name { get;  set; }
        public int Id { get; internal set; }
        public int Age { get; set; }
    }
    

    AssemblyInfo.cs 对于 Entities.dll

    [assembly: InternalsVisibleTo("DAL"), InternalsVisibleTo("BAL")]
    

    这样,DAL&BAL就能看到您的所有内部结构。这可能不可取,但我只是建议一个可能的解决方案。

        2
  •  18
  •   Rex M    16 年前

    两种常见的方法要么是类应该有一个用于DAL的构造函数,要么是DAL应该使用反射来水合物。

        3
  •  12
  •   Gregoire    16 年前

    或者你可以

    public class Person
    {
        public Person(int id)
        {
             this.Id=id;
        }
    
        public string Name { get;  set; }
        public int Id { get; private set; }
        public int Age { get; set; }
    }
    
        4
  •  9
  •   Robert Davis    16 年前

    也许我误解了,但是如果你想要真正的只读ID,为什么不使用实际的只读字段呢?

    public class Person
    {
       public Person(int id)
       {
          m_id = id;
       }
    
       readonly int m_id;
       public int Id { get { return m_id; } }
    }
    
        5
  •  7
  •   Mark Seemann    16 年前

    您可以让用户通过构造函数设置只读属性:

    public class Person
    {
        public Person(int id)
        {
            this.Id = id;
        }
    
        public string Name { get;  set; }
        public int Id { get; private set; }
        public int Age { get; set; }
    }
    
        6
  •  2
  •   Big Endian    16 年前

    也许,您可以将它们标记为内部的,在这种情况下,只有DAL或BL中的类(假设它们是单独的DLL)才能设置它。

    您还可以提供一个构造函数,它获取字段,然后只将它们作为属性公开。

        7
  •  2
  •   John Saunders    16 年前
    while(dr.read())
    {
        returnPersonList.add( 
            new Person(dr.GetInt32(1), dr.GetInt32(0), dr.GetString(2)));
    }
    

    在哪里?

    public class Person
    {
        public Person(int age, int id, string name) 
        {
            Age = age;
            Id = id;
            Name = name;
        }
    }
    
        8
  •  1
  •   Oded    16 年前

    通常情况下,ID不是实体的自然组成部分,而是需要抽象掉的数据库工件。

    这是一个设计决策——只允许在构造期间或通过方法调用设置ID,因此它由类内部管理。

    您可以自己编写一个setter,假设您有一个支持字段:

    private int Id = 0;
    public void SetId (int id)
    {
      this.Id = id;
    }
    

    或通过建造商:

    private int Id = 0;
    public Person (int id)
    {
      this.Id = id;
    }
    
        9
  •  0
  •   Jacob G    16 年前

    根据我的应用范围,我喜欢将对象的水合机制放在对象本身中。我将用一个自定义对象包装数据读取器,并向它传递一个委托,该委托在查询返回时执行。委托将传递给DataReader。然后,因为我在我的智能商务对象,我可以水合物远离我的私人设置。

    编辑伪代码

    “dataaccesswrapper”为我包装了所有的连接和对象生命周期管理。所以,当我调用“executedatareader”时,它会创建连接,通过传递的proc(参数有一个重载)来执行它,执行委托,然后在它自身之后进行清理。

    public class User
    {
        public static List<User> GetAllUsers()
        {
            DataAccessWrapper daw = new DataAccessWrapper();
            return (List<User>)(daw.ExecuteDataReader("MyProc", new ReaderDelegate(ReadList)));
        }
    
        protected static object ReadList(SQLDataReader dr)
        {
            List<User> retVal = new List<User>();
            while(dr.Read())
            {
                User temp = new User();
                temp.Prop1 = dr.GetString("Prop1");
                temp.Prop2 = dr.GetInt("Prop2");
                retVal.Add(temp);
            }
            return retVal;
        }
    }