Привет.
У меня есть два класса, «База данных» и «Группа».Я хочу иметь возможность создавать экземпляры «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...
}
}