Anon
Anon

Reputation: 123

Is there a way to restrict access to a public method to only a specific class in C#?

I have a class A with a public method in C#. I want to allow access to this method to only class B. Is this possible?

UPDATE:

This is what i'd like to do:

public class Category
{
    public int NumberOfInactiveProducts {get;}
    public IList<Product> Products {get;set;}

    public void ProcessInactiveProduct()
    {
        // do things...

        NumberOfInactiveProducts++;
    }
}

public class Product
{
    public bool Inactive {get;}
    public Category Category {get;set;}

    public void SetInactive()
    {
        this.Inactive= true;
        Category.ProcessInactiveProduct();
    }
}

I'd like other programmers to do:

var prod = Repository.Get<Product>(id);
prod.SetInactive();

I'd like to make sure they don't call ProcessInactiveProduct manually:

var prod = Repository.Get<Product>(id);
prod.SetInactive();
prod.Category.ProcessInactiveProduct();

I want to allow access of Category.ProcessInactiveProduct to only class Product. Other classes shouldn't be able to call Category.ProcessInactiveProduct.

Upvotes: 12

Views: 4840

Answers (5)

theb1uro
theb1uro

Reputation: 546

You can restrict method/class access in this way:

[StrongNameIdentityPermissionAttribute(SecurityAction.Demand, PublicKey="…hex…", Name="App1", Version="0.0.0.0")]
public class Class1 { } 

Take a look here http://msdn.microsoft.com/en-us/library/c09d4x9t.aspx for more info.

Managed code offers several ways to restrict method access:
...

  • Limit the method access to callers of a specified identity--essentially, any particular evidence (strong name, publisher, zone, and so on) you choose.

Upvotes: 2

Dan Bryant
Dan Bryant

Reputation: 27515

You could use an Observer type of pattern, where the Category registers an interest in particular events on the Product (perhaps a ProductInactivated event?) and then handles the logic appropriately. This event-based pattern is very common and greatly reduces coupling. The Category is ultimately responsible for its own state and doesn't rely on the Product knowing something about what's containing it in order to keep the Category's state intact. The Product just tells interested clients when things have happened to it.

Another option is to refactor your Category class so that it contains or is contained by some CategoryProductServices object that encapsulates the methods that a Product would need to perform on its containing Category. In the context that creates the Categories and Products, pass the instance of this CategoryProductServices object to the Product rather than the full Category. This design keeps the interface public, but prevents your client from getting access to the services, as they can't retrieve an instance. It also loosens the tight coupling of Products to the Category class, limiting it to only those services that Products must be aware of. This leaves the Product in charge of the state, but at least limits what it needs to know/do.

Upvotes: 0

Jennifer Zouak
Jennifer Zouak

Reputation: 1348

There is no out-of-the-box answer for your question.

If they are already in the same assembly, why not make the method internal scoped instead?

If they are in different assemblies, you can use the "friend" syntax which covers all internal methods.

Probably your best solution is to limit access to the public methods to specific assembly(ies). Which means that someone cannot just write a new assembly and go ahead an call your public methods. Given that you seem to have a domain model, it looks like you should allow this method to be called from other domain objects, but perhaps not from the business logic. This can be achieved by assigning a unique strong name to domain model DLL's.

You can restrict access to a public method to only allow it to be called by methods in assemblies satisfying a given public key. see msdn StrongNameIdentityPermission

Upvotes: 0

Henrik
Henrik

Reputation: 23324

Place both classes in a separate assembly and make the method internal.

Upvotes: 19

Andrew Hare
Andrew Hare

Reputation: 351698

You can if you make class A a private, nested class inside class B:

class B
{
    class A
    {
        public Int32 Foo { get; set; }
    }
}

Only B will be able to see A and it's members in this example.

Alternatively you could nest B inside A:

class A
{
    Int32 Foo { get; set; }

    public class B { }
}

In this case everyone can see both A and B but only B can see A.Foo.

Upvotes: 4

Related Questions