Свойства частного набора;
Я знаю, что это только позволяет классу установить его, но что такое точка?
Как решить проблему с идентификаторами 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)
Ответы
Ответ 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;
}
}