Подтвердить что ты не робот

Свойства частного набора;

Я знаю, что это только позволяет классу установить его, но что такое точка?

Как решить проблему с идентификаторами readonly?

Скажем, у меня есть класс человека:

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?

Или это даже не правильное использование частного набора?


Я просто хотел добавить, что это ваше типичное приложение DB, где pk - это идентификатор и его не следует изменять (только BL/DAL)


4b9b3361

Ответ 1

Это одно возможное решение, хотя и не очень чистое:

  • Сделайте свойство, которое вам нужно открыть для BAL и DAL internal
  • Отметить 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

Два общих подхода заключаются в том, что класс должен иметь конструктор для использования DAL, или DAL должен использовать отражение для гидратации объектов.

Ответ 3

Или вы можете сделать

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

Может быть, я недопонимаю, но если вы хотите действительно прочитать только для чтения, почему бы не использовать фактическое поле readonly?

public class Person
{
   public Person(int id)
   {
      m_id = id;
   }

   readonly int m_id;
   public int Id { get { return m_id; } }
}

Ответ 5

Вы можете позволить пользователю установить свойство только для чтения, предоставив его через конструктор:

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

Возможно, они могут быть помечены как внутренние, и в этом случае только классы в вашем DAL или BL (при условии, что они являются отдельными dll) могли бы установить его.

Вы также можете предоставить конструктор, который принимает поля, а затем предоставляет только их свойства.

Ответ 7

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

Обычно это так, то идентификатор не является естественной частью сущности, а артефактом базы данных, который нужно абстрагировать.

Это дизайнерское решение - разрешить установку идентификатора во время построения или путем вызова метода, поэтому он управляется внутри класса.

Вы можете написать сеттер самостоятельно, если у вас есть поле поддержки:

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

Или через конструктор:

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

Ответ 9

В зависимости от области моего приложения, я хотел бы поместить механизмы гидратации объекта в самом объекте. Я завершу считыватель данных специальным объектом и передам ему делегат, который будет выполнен после запроса. Делегат получает данные DataReader. Затем, поскольку я нахожусь в своем умном бизнес-объекте, я могу уйти со своими частными сеттерами.

Изменить для псевдокода

"DataAccessWrapper" переносит все управление жизненным циклом соединения и объекта для меня. Поэтому, когда я вызываю "ExecuteDataReader", он создает соединение, с переданным proc (там перегрузка для params) выполняет его, выполняет делегат, а затем очищается после себя.

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;
    }
}