Ограничение доступа метода класса к одному другому классу - PullRequest
3 голосов
/ 13 ноября 2010

Привет.

У меня есть два класса, «База данных» и «Группа».Я хочу иметь возможность создавать экземпляры «Group» и вызывать методы для этих экземпляров из «Database» и публично распространять ссылки на «Group».Однако я не хочу предоставлять публичный доступ к конструктору или другим методам в «Группе».

Первоначально я думал, что смогу достичь этого ограничения доступа, сделав «Группу» частным внутренним классом «Базы данных».Но я обнаружил, что не могу публично распространять ссылки на «Группу», если она была частной.Кроме того, мои попытки сделать «Группу» общедоступным внутренним классом не увенчались успехом, потому что, если все его методы были частными, «База данных» не могла бы получить к ним доступ, и если они были общедоступными, доступ был бы возможен за пределами «Базы данных».

Я ищу метод передовой практики для решения или обхода этой проблемы. Может быть, я где-то пропустил необходимое ключевое слово?Ничто из того, что я обнаружил в своих исследованиях, не указывает на то, что C # допускает такую ​​гранулярность контроля.Я нашел грязный способ обойти проблему, как я указал ниже в коде.Его суть заключается в следующем: перед каждым вызовом в «Базе данных» метода в «Группе» установите поле в «Базе данных», доступное для чтения, но только для частной установки, чтобы все методы «Группы» проверяли в своих созданных экземплярах »База данных »перед выполнением запланированных операций.При чтении поля (через открытый метод в «Базе данных») поле сбрасывается, предотвращая любые дальнейшие вызовы метода для «Группы», пока «База данных» не установит поле снова.

public class Database {

    // Field; true if Database has just authorized a method call to a %Group.
    private bool group_isNextCallAuthorized = false;

    // Invoked before every method call to a %Group.
    private void Group_AuthorizeNextCall() {
        group_isNextCallAuthorized = true;
 }

    // Method, ordinarily called from %Group, that checks its creating %Database
    //  that the %Database itself authorized the method call on the %Group. It
    //  automatically resets the authorization to false to prepare for the next,
    //  perhaps unauthorized, method call.
    public bool Group_IsNextCallAuthorized() {
        bool previousValue = group_isNextCallAuthorized;
        group_isNextCallAuthorized = false;
        return previousValue;
    }

    // Constructor; creates a demo %Group.
    public Database() {

        // Create a %Group, first authorizing the action.
        Group_AuthorizeNextCall();
        Group group = Group.Create(this);

        // Call some method on the group
        Group_AuthorizeNextCall();
        group.SomeGroupMethod();

    }

}

public class Group {

    // Field; refers to the %Database that created this %Group instance.
    private Database db;

    // Generates an instance of %Group, requiring the creating %Database as an
    //  argument. After checking that the %Database %db isn't null, it verifies
    //  that %db actually requests and authorized this %Group's creation via the
    //  %Group_IsNextCallAuthorized(.) method provided by %Database.
    public static Group Create(Database db) {

        // It will not create a dud instance of %Group; it will throw an exception
        //  instead.
        if ((db == null) || !db.Group_IsNextCallAuthorized())
            throw new System.Exception("Unauthorized access.");

        return new Group(db);
    }

    // This constructor is referenced internally by static %Create(.) as above.
    private Group(Database db) {
        this.db = db;
    }

    // This is an arbitrary method showing that it must check that the %Database
    //  that created this %Group authorized this method call before it will
    //  perform its intended function.
    public void SomeGroupMethod() {
        if (!db.Group_IsNextCallAuthorized())
            throw new System.Exception("Unauthorized access.");

        // intended functionality...
    }

}

Ответы [ 3 ]

5 голосов
/ 13 ноября 2010

Один из вариантов - открыть интерфейс IGroup для внешних частей вашего кода.У этого интерфейса будут только методы получения свойств, доступные методы и т. Д. Затем база данных будет работать с классом Group, имея полный доступ ко всем свойствам / методам и возвращая IGroup

3 голосов
/ 13 ноября 2010

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

 public class DataBase 
 {
      private class Group 
      {
            private Group() {} 

      }

      private Group group = null;

      public DataBase() 
      {
         this.group = new Group();
      }

      public Group 
      {
         get 
         {
            return this.group;

         }   
 }
0 голосов
/ 13 ноября 2010

Чтобы выразить эту видимость с помощью правил доступа C #, необходимо изменить вложение классов: сделать базу данных вложенным классом внутри группы, чтобы он мог обращаться к частным битам группы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...