Свойства частного набора; - PullRequest
45 голосов
/ 02 марта 2010

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

Как мне решить проблему с идентификаторами 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, но не в графическом интерфейсе?

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


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


Ответы [ 9 ]

37 голосов
/ 02 марта 2010

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

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

18 голосов
/ 02 марта 2010

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

12 голосов
/ 02 марта 2010

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

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; }
}
9 голосов
/ 02 марта 2010

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

7 голосов
/ 02 марта 2010

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

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; }
}
2 голосов
/ 02 марта 2010

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

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

2 голосов
/ 02 марта 2010
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;
    }
}
1 голос
/ 02 марта 2010

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

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

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

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

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

private int Id = 0;
public Person (int id)
{
  this.Id = id;
}
0 голосов
/ 02 марта 2010

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

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

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

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...