Only allow setting a property from a specific class / instance
imagine I have two classes A and B where B has the properties BProperty1 and BProperty2.
- The property BProperty1 shall only be settable by class A (no matter which instance)
- The property BProperty2 shall only be settable by a concrete instance of class A (the reference to this instance could e.g. be stored on BProperty1).
Is it possible to realize something like that, is there maybe a pattern for it? Please note that A and B are independent, none of them derives from the other one! I'm using C# and WPF. Thanks for any hint!
EDIT An example:
Imagine a class Car and a class CarDoor. Whenever a CarDoor is added to a Car, the CarDoors property AssociatedCar is set to the Car it's assigned to, because this reference is needed later. But how to make sure the AssociatedCar property is not set 开发者_如何学JAVAby the user, but by the Car class when AddCarDoor(door) is called?
class Car
{
private List<CarDoor> _carDoors = new List<CarDoor>();
public Car()
{
}
public void AddCarDoor(CarDoor door)
{
// Add the door to the car
_carDoors.Add(door);
// Save a reference to the car assigned to the door
door.AssociatedCar = this;
}
}
class CarDoor
{
public Car AssociatedCar;
public CarDoor()
{
}
}
You could lock the setter, then make the object required to unlock it private to class A.
Edit: After seeing your edit, I would suggest that you make a car door a member of class car, seeing as how a car is composed of some x doors. Or perhaps a collection of car doors. Make that member variable private. Then nothing outside of the car class will be able to edit that property of the car door.
Edit2: Also, having a two way association between car and car door (i.e. car door has an associated car, and car has associated car doors) is a bit redundant. I do not see why you would need it - simply set a public get property for the car door, so that you can use that data outside of the car class.
Example...
Class Car
{
private List<CarDoor> carDoors;
Car()
{
this.carDoors = new List<CarDoor>();
}
public List<CarDoor> getCarDoors
{
return this.carDoors;
}
}
Here's one design that shifts responsibilities slightly to create the two-way dependency:
class CarFactory
{
public Car BuildCar()
{
return new Car(BuildDoor);
}
public CarDoor BuildDoor(Car car)
{
return new CarDoor(car);
}
}
class Car
{
private List<CarDoor> _carDoors = new List<CarDoor>();
public Car(Func<Car, CarDoor> buildDoor)
{
for (int i=0; i<4; i++)
_carDoors.Add(buildDoor(this));
}
}
class CarDoor
{
private Car _associatedCar;
public CarDoor(Car associatedCar)
{
_associatedCar = associatedCar;
}
}
Note, however, that this sort of two-way dependency is a sign of other problems. It could be that CarDoor is doing things that it shouldn't be responsible for doing. Perhaps Car should be doing these things or perhaps you've included responsibilities that really belong in another class entirely, like Mechanic.
You can put the two together in a separate project/assembly/dll and use the internal keyword on the property set. That way any class inside the assembly can change the property, but since you're in control of the entire thing you can make sure only Car does so.
If it is a property, you may want to use System.Diagnostics.StackTrace class) inside the property setter. You just need to check the assembly and the class which called the setter, and throw an exception if it is a class other than the class A.
Notes:
- Be aware of performance issues.
- I'm pretty sure that somebody will say that if you need to do this sort of things, it means that there is a flaw in your object-oriented approach. At least, I used this once, and I completely agree that my approach was wrong.
精彩评论