Reputation: 55
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
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
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
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