Anne-Christine
Anne-Christine

Reputation: 55

Is it possible to customize access modifiers behaviour?

I have a winform application made up of two assemblies : a business layer and a front-end layer. Each usercontrol (front-end layer) relates to a class of the business layer, i.e. CustomerUserControl uses the Customer class.

Editable properties, i.e. Customer.Name, have public setters so that their values can be modified through front-end controls.

My question is : is it possible to change the setter accessibility of a property to make it more or less restrictive only for specific classes. In my example, the Customer.Name setter would be internal, that is not accessible by front-end controls but accessible for its corresponding control CustomerUserControl. Or else, the setter would be public but not accessible to controls other than CustomerUserControl.

Is it possible to achieve such customized access rights ?

Upvotes: 1

Views: 850

Answers (3)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112269

I would use the internal modifier for the setter. This makes it only accessible inside the assembly. If the CustomerUserControl is in another assembly then you can use the InternalsVisibleToAttribute

[assembly: InternalsVisibleTo("assembly name")] 

EDIT: You are right. Here is another possibility: Declare an interface that would be implemented by controls that are allowed to set names:

public interface ICustomerNameProvider
{
    string CustomerName { get; }
}

In Customer add a method:

public void SetName(ICustomerNameProvider customerNameProvider)
{
    this.Name = customerNameProvider.CustomerName;
}

The CustomerUserControl would call it like this:

cust.SetName(this);

Of cause this is not absolutely fool proof, but accidentally passing the wrong control would become impossible.

Upvotes: 3

Esoteric Screen Name
Esoteric Screen Name

Reputation: 6112

As far as I know, there's no way to apply what you're asking for directly to a property setter, since it doesn't know where the call initiated from. However, you could cobble something together using mutator methods:

public class Customer
{
   ...
   public string Name
   {
      get;
      private set;
   }

   public void SetName(string callingControlName, string newName)
   {
      // you'd use TypeOf the same way to pass in callingControlName
      if(TypeOf(this).Name + "UserControl" == callingControlName)
         this.Name = newName;
   }
   ...
}

Note that this is ridiculously tightly coupled and poor design practice, but it ought to do what you want, provided you strictly adhere to the naming conventions outlined in the question (Customer matches 1:1 with CustomerUserControl). As an aside, I didn't just statically compare callingControlName to "CustomerUserControl" in order to gain a slight improvement in maintainability, in case you wanted to do something like rename the CustomerUserControl class. Also important to note is the fact that this is easily defeasible by calling Customer.SetName("CustomerUserControl","badName"). Hopefully you aren't exposing this to coders who would do things like that, but it is entirely possible.

The real issue here is that your business layer shouldn't be dependent on your presentation layer. Why would you need to restrict set access to a specific UserControl? If you have a genuine need (and I can't think of one) that a business property's set only be accessible from a certain UI class, then some significant redesigning of your application is called for.

Upvotes: 1

James Johnson
James Johnson

Reputation: 46047

You can limit the scope of get or set accessors like this:

//private set accessor - this is what you're looking for
public int SomeProperty { get; private set; } 

//private get accessor
public int SomeOtherProperty { private get; set; }

Upvotes: -2

Related Questions