Приветствия.Ограничение доступа метода класса к одному другому классу
У меня есть два класса: «База данных» и «Группа». Я хочу иметь возможность создавать экземпляры «Групп» и методы вызова для этих экземпляров из «базы данных» и иметь возможность публично распространять ссылки на экземпляры «Группы». Однако я не хочу предоставлять публичный доступ к конструктору или другим методам в «Группе».
Первоначально предполагалось, что я могу достичь этого ограничения доступа, сделав «Группу» частным внутренним классом «База данных», но я обнаружил, что я не мог публично распространять ссылки на «Группу», если он был закрытым. Кроме того, мои попытки сделать «Группу» публичным внутренним классом не удались, потому что, если его методы были частными, «База данных» не могла получить к ним доступ, и если они были общедоступными, доступ был возможен за пределами «Базы данных».
Я ищу оптимальную технику для решения или обхода этой проблемы. Возможно, я где-то пропустил необходимое ключевое слово? Ничто из того, что я нашел до сих пор в моих исследованиях, не показало, что C# допускает эту гранулярность контроля. Я нашел грязный способ обойти проблему, как я уже приводил ниже в коде. Суть его заключается в следующем: перед каждым вызовом в «базе данных» методу в «Группе» задано поле в «База данных», общедоступное, но доступное только в частном порядке, что методы «Группы» проверяют в своих экземплярах создания ' Database 'перед выполнением намеченных операций. При чтении поля (через открытый метод в «База данных») поле сбрасывается, что предотвращает дальнейшие вызовы методов в «Группе» до тех пор, пока «База данных» снова не установит это поле.
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...
}
}
хорошая идея, +1 (вы должны добавить образец кода, хотя) – Jan
Это выглядит для меня хорошей идеей. Кажется, он калечит автоматическую проверку типов, когда я хочу использовать «Группу» в качестве аргумента для метода «База данных» из-за пределов «Базы данных», хотя я бы вместо этого должен был передать «Группу», которая может быть реализована любым классом. Тем не менее, поскольку я могу проверять типы вручную в «базе данных» в любом случае, этот метод выглядит так, что он может существенно усложнить мой код. –