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

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

Как я решаю проблему наличия идентификаторов только для чтения?

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

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)})
}
...

конечно, я не могу сделать, тот идентификатор причины является частным набором; Что надлежащий путь состоит в том, чтобы сделать это?

Как я могу позволить BL/Dal установить идентификатор, но не на GUI?

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


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


46
задан Răzvan Flavius Panda 14 February 2013 в 11:43
поделиться

9 ответов

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

  1. Сделайте свойство, которое вам нужно раскрыть для BAL и DAL internal
  2. Mark BAL.dll & DAL. dll Internal Visible в 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. Это может быть нежелательно, но я просто предлагаю одно из возможных решений.

38
ответ дан 26 November 2019 в 20:25
поделиться

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

18
ответ дан 26 November 2019 в 20:25
поделиться

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

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; }
}
12
ответ дан 26 November 2019 в 20:25
поделиться

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

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

   readonly int m_id;
   public int Id { get { return m_id; } }
}
9
ответ дан 26 November 2019 в 20:25
поделиться

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

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; }
}
7
ответ дан 26 November 2019 в 20:25
поделиться

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

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

2
ответ дан 26 November 2019 в 20:25
поделиться
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;
    }
}
2
ответ дан 26 November 2019 в 20:25
поделиться

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

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

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

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

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

private int Id = 0;
public Person (int id)
{
  this.Id = id;
}
1
ответ дан 26 November 2019 в 20:25
поделиться

В зависимости от сферы применения, мне нравится размещать механизмы увлажнения объекта в самом объекте. Я оберну читателя данных пользовательским объектом и передам ему делегат, который будет выполнен после возврата запроса. Делегату передается 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;
    }
}
0
ответ дан 26 November 2019 в 20:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: