Note that there are some explanatory texts on larger screens.

plurals
  1. PORestricting class method access to one other class
    primarykey
    data
    text
    <p>Greetings.</p> <p>I have two classes, 'Database' and 'Group.' I want to be able to create instances of 'Group' and call methods on those instances from within 'Database' and to be able to distribute 'Group' instance references publicly. However, I do not want to provide public access to the constructor or other methods in 'Group.'</p> <p>I originally thought that I could achieve this access restriction by making 'Group' a private inner class of 'Database,' but I discovered that I couldn't publicly distribute references to 'Group' if it was private. Also, my attempts at making 'Group' a public inner class failed, because if its methods were all private, 'Database' couldn't access them, and if they were public, access was possible beyond 'Database.'</p> <p><strong>I am looking for a best-practice technique for solving or circumventing this problem.</strong> Maybe I missed a necessary keyword somewhere? Nothing I have found thus far in my research has indicated that C# permits this granularity of control. I found a messy way to get around the problem, as I've provided below in code. Its essence is this: before every call in 'Database' to a method in 'Group,' set a field in 'Database,' publicly readable but only privately settable, that 'Group''s methods all check in their creating instances of 'Database' before performing their intended operations. When reading the field (via a public method in 'Database,') the field is reset, preventing any further method calls on 'Group' until 'Database' sets the field again.</p> <pre><code>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... } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload