ご挨拶。
「データベース」と「グループ」の 2 つのクラスがあります。「グループ」のインスタンスを作成し、「データベース」内からそれらのインスタンスのメソッドを呼び出し、「グループ」インスタンスの参照をパブリックに配布できるようにしたいと考えています。ただし、コンストラクターまたは「グループ」内の他のメソッドへのパブリック アクセスを提供したくありません。
当初は、「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...
}
}