Управление данными - данные только для чтения - PullRequest
3 голосов
/ 02 июля 2010

Я работаю над каким-то проектом на C # и столкнулся со следующей проблемой:

У меня есть несколько классов типов данных, например, класс Person, который хранит информацию о человеке.

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

Проблема в том, что я не хочу, чтобы кто-либо, кроме класса DataManager, мог изменятьЧеловек возражает.Например, если кто-то вызывает DataManager.getPerson(int ID), он получит объект Person и сможет использовать функции установки этого объекта Person для изменения его содержимого (имя, фамилия, идентификатор и т. Д.).

Я хочу избежать этого.Я хочу, чтобы только класс DataManager мог изменять объекты Person (с помощью таких методов, как DataManager.changeFirstNameForPerson(int ID, string name)).

Какова лучшая структура класса, которая может достичь этого?

Ответы [ 5 ]

2 голосов
/ 02 июля 2010

Ну, вы никогда не сможете остановить людей от изменения значений на 100%.Они всегда могут просто пройти через рефлексию.

Но с точки зрения API вы можете сделать все методы получения вашего класса Person общедоступными, а также все методы установки внутренними.Пока классы Person и DataManager находятся в одной сборке, DataManager сможет нормально обращаться к установщикам, но другие приложения, которые ссылаются на сборку, не могут.

public class Person
{
    public string Fname { get; internal set; }
}


public class DataManager
{
    public void ChangeNameForPerson(int id, string fname)
    {
        Person p = Person.GetById(id);
        // Inside the same assembly.  Setter is accessible
        p.Fname = fname;
    }
}

За пределами сборки вы 'иметь это:

Person p = DataManager.GetPerson(1);
p.Fname = "asdf"; // Compile time error
DataManager.ChangeNameForPerson(1, "asdf"); // Works fine
1 голос
/ 02 июля 2010

Если вы объявите свои методы доступа get / set в классе Person с ключевым словом internal , то только объекты в той же сборке смогут получить к ним доступ.Пока вы включаете класс DataManager в ту же сборку, он будет иметь доступ, а любой код вне сборки не будет.

1 голос
/ 02 июля 2010

Первые две вещи, которые на ум приходят:Персона и DataManager в собственной сборке

0 голосов
/ 02 июля 2010

Один из вариантов заключается в том, чтобы реорганизовать существующий класс Person во внутренний класс DataManager (т.е. DataManager.Person), а затем создать новый класс Person в соответствии с:

public class Person
{
    private DataManager.Person person;

    public Person(Datamanager.Person person)
    {
        this.person = person
    }

    public int ID
    {
        get { return person.ID; }
    }

    ...
}

Затем в вашем классе DataManager вы сделаете что-то вроде:

public Person GetPerson(int id)
{
    DataManager.Person person = // get the person by ID
    return new Person(person);
}

Теперь внешний код имеет доступ к классу Person только для чтения, но не может получить ссылку на DataManager.Person для чтения / записи.

0 голосов
/ 02 июля 2010

Сделать класс Person неизменным;то есть, сделайте все поля на нем readonly и предоставьте только получатели свойства, а не установщики.Передайте значения для всех полей в конструктор.

...