Only allow setting a property from a specific class / instance - c#

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 by 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.

Related

How can I make a polymorphic method with different signatures

Consider I have some abstract Vehicle class and car, truck, motorcycle abstract classes which derive from Vehicle. Also imagine that I have to be able to create a fueled based car or electric based car and so on for truck and motorcycle as well. (concrete classes)
Two questions:
1.Consider that I want to fill up energy in a vehicle without knowing what it is, in a polymorphic way. For example if the vehicle is fuel based I want to fill it with fuel and the method should be with 3 parameters:
void FillUpEnergy(EfuelType i_fuelType,int amounOfEnergy, int maxAmountOfEnergy)
but for electricy based vehicle I need almost the same function signture but this time without fuel type of course, for example (2 parameters):
void FillUpEnergy(int amounOfEnergy, int maxAmountOfEnergy)
Can I do a polymorhic FillUpEnergy method with the above constraints? (different method's signatures)
2.In my implementation all the concrete classes hold a reference for Engine(another abstract class) which represent a FuelEngine or ElectricEngine (other concrete classes I have which derive from Engine). For example I have a concrete class named ElectricCar which holds a reference for ElectricEngine.
Is this architecture good enough or are there better ways to implement a garage system?
(In terms of Object oriented design etc..)
You cannot make a polymorphic "push-style" method with different signatures, but you can make a polymorphic "pull-style" method using the well-publicized Visitor Pattern.
The idea is to invert the sequence of interaction, and let the car object decide what to do: Instead of calling FillUpEnergy and giving the car what you think it needs, call FillUpEnergy and let the car take what it knows it needs, like this:
interface IEnergyProvider {
void TakeFuel(EfuelType i_fuelType, int amounOfEnergy);
void TakeElectricity(int amounOfEnergy);
}
interface ICar {
void FillUpEnergy(IEnergyProvider provider);
}
Now the signature of your polymorphic method is fixed, but the dispatch of the method takes two legs instead of one:
You call myCar.FillUpEnergy(myProvider)
The car calls myProvider.TakeFuel or myProvider.TakeElectricity
Regarding question 1)
You could make electric/gasoline part of the fueltype and handle this in your domain logic.
C# does not offer polymorphism with different signatures.
2) is called Composition
What distinguishes the ElectricCar from the FueledCar? Nothing but the engine (conceptually):
interface IEngine
{
void FillUpFuel(int amountOfFuel, int maxAmountOfFuel);
}
class ElectricEngine : IEngine
{
public void FillUpFuel(int amountOfFuel, int maxAmountOfFuel) { ... }
}
abstract class Vehicle
{
public abstract IEngine Engine { get; }
}
class Car : Vehicle
{
public IEngine _engine;
public override IEngine Engine { get { return _engine; } }
public Car(IEngine engine)
{
_engine = engine;
}
}
...
var electricCar = new Car(new ElectricEngine());
electricCar.Engine.FillUpFuel(40, 70);
Typical composition vs inheritance example. Naming is a bit odd with ElectricEngine filling up fuel... but that's not the point.
About 1)
The point of having FillUpEnergy polymorphic (subtype polymorphism) is to be able to call this method when the only thing you know is that the object is a Vehicle.
If you need to know the exact type in order to choose the correct set of argument, then their is no need for this function to be polymorphic.
About 2)
Nothing's shocking
You can't do that, because it would be exactly a violation of encapsulation.
I don't understand your question regarding engines, but I can surely say that there could be a lot of better ways to implement "garage system" just because there are so many different "garage systems". Which in fact means that you should not try to model your system (in terms of OOP or any other terms) until you get a good grasp of your requirements.

Hierarchical structuring of Functions inside a Class (C#)

is it possible to structure functions inside a class, to make some functions only accessable through a prewritten identifier?
I'll try to make my question a litte more clear with a (poor) example ;-) My class car got the functions drive, openDoor, closeDoor, startEngine, etc. But, to keep it clear, i would like to acces these functions like this:
car.drive()
car.door.open()
car.door.close()
car.engine.start()
I tried with structs and nested classes, but i don't think those were the right ways, because i don't like to have to create an object for every "identifier" i use.
Are there any "clean" ways to do this?
Thanks!
Edit:
I'm not sure if it matters but heres some additional information:
the "Car"-Class is Singelton
apart from the functions neither the engine nor the doors or any other part of my car do have any other properties (Yay. Really poor example!)
Nested classes would be the correct approach.
Consider that all Door objects would have Open and Close methods, and a Car object would have several instances of the Door object (2, maybe 4, or even more).
Likewise, each Car object would have an instance of the Engine object, which can be Started, Stopped, and have the oil changed (ChangeOil).
Then, each of these classes would be extensible beyond the Car class. If you wanted to change some of the code inside of your Door class, all of your Car objects that have Doors would automatically inherit those changes. If you wanted to swap out the engine of a car with a more powerful one, you could do that easily by passing in a new instance of the Engine object to your Car object.
You could use structs the same way that you would use classes, but generally you should choose to use a class rather than a struct. Structs should be reserved for types that should have value type semantics, i.e., are small, immutable, etc. For more information on the difference and how to make an informed decision, see this question.
And just in case I failed to convince you that nested classes are the correct approach, I'll conclude by noting that they're also the only way of achieving what you want. That is, beyond hacky solutions like appending a pseudo-namespace to the beginning of each function name (i.e., Car.DoorOpen), which is ugly and doesn't really gain you anything at all.
No - you would need to have a nested class door with its own methods. You could add your descriptor to the method name. So you would have
car.DoorOpen();
car.DoorClose();
I'd go for classes, since you may have properties that would apply more to the class door than to car. And add properties of the class door to car.
car.Door.Open();
Nested classes are not necessary here, for anyone having trouble understanding, the following is a nested class approach:
public class Car
{
public static Car Instance { get; private set; }
static Car() { Car.Instance = new Car(); }
private Car() { }
public static class Door
{
public static void Close()
{
/* do something with Car.Instance */
}
}
}
The use of static classes yields the following syntax:
Car.Door.Close();
C# allows you to nest class definitions it does not have a formal concept of 'inner types' or 'inner classes' as other languages do.
This is an excellent example of poor component modeling/design.
Consider the following, which is a more acceptable and more elegant solution:
public interface ICar
{
IDoor Door { get; set; }
}
public class Car : ICar
{
public IDoor Door { get; set; }
}
public interface IDoor
{
void Open();
void Close();
}
public class Door : IDoor
{
public override void Open() { /* do something */ }
public override void Close() { /* do something */ }
}
With the above could use C#'s initializer syntax:
var car = new Car
{
Door = new Door()
};
car.Door.Open();
If your gripe is with constantly needing to type "new XYZ" you can also bake initialization into the constructor. Done properly with a 'poor man' DI pattern it should look like this:
public class Car : ICar
{
public IDoor Door { get; set; }
public Car()
: this(new Door())
{
}
public Car(IDoor door)
{
this.Door = door;
}
}
This avoids the need to perform initialization as part of creation, and allows you to inject new/different Door types into the stack.
var common = new Car();
var lambo = new Car(new LamboDoor());
In either case, calling code looks the same:
common.Door.Open();
lambo.Door.Open();
Lastly, you could consider a Composition or DI framework rather than bake new() operators into your implementation code. In any case, the most appropriate approach is to use properties and construct a legitimate object model which expresses your intent. Nested types do not yield the syntax you're looking for unless static members are used and taking that approach is very rarely a good idea, I've only seen it for simplistic singleton implementations, certainly never for API/Framework/Model definition.
Just my 2 sense.
I like #Code Gray idea of nested classes. But to achieve the correct order of calling the methods, I think you need to nest car under Driver. The Driver would do something like this.
public class Driver
{
public void Drive(Car car)
{
car.drive();
car.door.open();
car.door.close();
car.engine.start();
}
}

Permanent casting to a superclass

If:
class Car : Automobile
{}
I can do:
Car toyota = new Car();
Automobile tauto = (Automobile)toyota;
but if I do tauto.GetType().Name it will still be Car.
Is it possible to perform a cast, so that the type is permanently changed to Automobile (without having to clone the object) ?
The problem i am trying to overcome is that there is no multiple inheritance in c#, and i need to merge objects (with the same signature) from 2 services, in one method, and return one type.
No. There is no way to do this without constructing a new Automobile object.
However, there is also no reason to do this. The Liskov substitution principle says that any Car should, always, be treatable exactly like an Automobile, and the user should have no change in expected behavior.
As long as you design your class hierarchy correctly, using Car as an Automobile should always be perfectly acceptable.
On a side note: This is part of why using Type.GetType() is not the preferred way to check for type. It's much safer, and better, to use the is and as keywords in C#. They will return true if you check that tauto is Car.
According to MSDN, you're just casting the reference to the object, and not the underlying object.
Your question and what you're trying to do seem like two different things. No you can't change the underlying type of a object. But what you seem to want to do is create a type of automobile with set of properties and not actually use the subclass. What you could do is use a Automobile factory instead.
public static class AutomobileFactory()
{
public static Automobile CreateAutomobile(AutomobileType type)
{
...
}
}
Where AutomobileType is a enum. For more information google C# Factory pattern.
I'm not sure exactly what it is you're trying to do, but maybe you could consider a different approach? Instead of trying to merge the functionality of two different classes using inheritance, maybe you could use composition?
http://tiedyedfreaks.org/eric/CompositionVsInheritance.html
public class Service
{
public virtual void DoSomething()
{
}
}
public class ServiceA : Service
{
public override void DoSomething()
{
}
}
public class ServiceB : Service
{
public override void DoSomething()
{
}
}
public class ServiceA_B : Service
{
ServiceA serviceA = new ServiceA();
ServiceB serviceB = new ServiceB();
public override void DoSomething()
{
serviceA.DoSomething();
serviceB.DoSomething();
}
}
In some cases, generics may help. If a method includes a generic parameter, the generic type will be evaluated as the declared type of the passed-in reference, rather than the type of the passed-in object. For example:
void Foo(T bar)
If foo() is called with (Control)someButton, the type of 'bar' will be Button, but the type of T will be Control.

Nested class with hidden constructor impossible in c#?

I' ve been doing some programming lately and faced an issue which i found weird in c#. (at least for me)
public class Foo
{
//whatever
public class FooSpecificCollection : IList<Bar>
{
//implementation details
}
public FooSpecificCollection GetFoosStuff()
{
//return the collection
}
}
I want the consumer of Foo to be able to obtain a reference to FooSpecificCollection, even perform some operations on it. Maybe even set it to some other property of Foo or smth like that, but not To be able to CREATE an instance of this class. (the only class that should be able to instatiate this collection should be Foo.
Is my request really that far-fetched? I know that people way smarter defined c# but shouldn't there be such an option that a parent class can create a nested class instance but nobody else can't.
So far I created a solution to make an abstract class, or interface available through the property and implement a concrete private class that is not available anywhere else.
Is this a correct way to handle such a situation.?
The way embedded classes work is that they, as members of the outer class, get access to private members of that outer class. But not the other way around (what is what you want).
You can shield the constructor of FooSpecificCollection, but then the Factory has to be part of FooSpecificCollection itself. It could enlist the outer class:
public class Foo
{
public class FooSpecificCollection : List<Bar>
{
private FooSpecificCollection () { }
public static FooSpecificCollection GetFoosStuff()
{
var collection = new FooSpecificCollection ();
PrepareFooSpecificCollection(collection);
return collection;
}
}
private static void PrepareFooSpecificCollection(FooSpecificCollection collection)
{
//prepare the collection
}
}
Make your nested class private and make the return value of GetFoosStuff IList<Bar> instead of FooSpecificCollection.
Also, there's a good chance that deriving from List<Bar> is a bug.
If you are creating a library for others to use, you could make the constructor internal. Anyone outside the library will not be able to access it. If you are concerned about calling the constructor in your own project, just don't call it outside the parent class.
We create classes all the time which are not directly related to other classes, but the constructors don't have to be hidden from non-related classes. We (the programmers) know the the objects are not related so we don't ever create an instance of one in the other.
There is a solution but I don't think I would use it in my App :)
The idea is to have derived class from FooSpecific which is private and can be used only inside Foo but has public constructor, so Foo can create its instances.
public class Foo
{
//whatever
public class FooSpecific
{
// Protected contructor.
protected FooSpecific()
{
}
// All other code in here.
}
// Private helper class used for initialization.
private class FooSpecificInitHelper : FooSpecific
{
public FooSpecificInitHelper()
{
}
}
// Method in foo to create instaces of FooSpecific.
private FooSpecific CreateFooSpecific()
{
return new FooSpecificInitHelper();
}
}
No, and it doesn't really make sense.
I mean the whole point is so that you could potentially return other instances; but who will be deriving from that class anyway? Certainly not any other classes (Because that would be wrong, and imply it shouldn't be hidden inside the main class), so ...

.NET inheritance: suppress a property from the base class

Consider the Employee, Manager, and Assistant classes:
public class Emp
{
public string Name { get; set; }
public Manager Manager { get; set; }
public Assistant Assistant { get; set; }
}
public class Manager : Emp
{
}
public class Assistant : Emp
{
}
The goal is to DISALLOW a piece of code to access a property like this:
var foo = new Manager();
var elmo = new Emp();
elmo.Manager = foo;
elmo.Manager.Manager = new Manager();
//how to disallow access to Manager.Manager ?
Because Manager inherits from Emp, it has a .Manager and .Assistant property.
Question
Are there any modifiers in .NET's inheritance implementation to remove the .Manager and .Assistant properties?
Update
Thank you for your great answers, everyone. I was hoping the simplification and contrivance of Emp/Mgr would show through in this question. It's clear that the inheritance, in this example, should be taken to another commonality (something like Person, where the classes would share names, birthdates, etc.) Your input is much appreciated!
Doing this would violate the Liskov substitution principle, and is usually a sign of a questionable design. In general, any subclass should be able to be used in any context that a base class would be. If Managers don't have .Managers, then they aren't Emps, and shouldn't inherit from them.
No - because it would break Liskov's Subsitution Principle. Basically, you can add things, but you can't take them away.
You could potentially override the property to throw an exception at execution time, but you can't do it at compile time.
Generally if you want to disallow this sort of thing, you should consider composition rather than inheritance, as you don't have a genuine inheritance relationship.
No, there isn't.
You can make the base class property virtual, then override it to throw an exception in the setter, but there's no way to give a compile-time error. After all, there is nothing you do at compile time to prevent
(elmo.Manager as Employee).Manager = new Manager();
However, you can write
public class ManagerEmployee : Emp {
public new ManagerEmployee Manager {
get { return base.Manager; }
}
}
Note that this won't prevent casting.
Like most things, it depends. Given the following classes:
public class foo
{
public string Test { get { return "foo"; } }
}
public class bar : foo
{
public new string Test { get { return "bar"; } }
}
And the following code:
bar a = new bar();
// returns bar
literalTest1.Text = a.Test;
foo b = new foo();
// returns "foo"
literalTest2.Text = b.Test;
foo c = new bar();
// returns "foo"
literalTest3.Text = c.Test;
You can see, based on the comments above, that you can override a property that is not declared as virtual. However, the overridden property will only be used when the object variable is declared as the type that overrides the property - not as any of its ancestors. This effectively breaks polymorphism.
Fix your ancestor class instead.
As others have said. No. I'll add that if not every employee has a manager and an assistant, then your inheritance hierarchy is wrong. It would seem that the only thing an employee and manager share is a name. You can add via inheritance, but you cannot take away via inheritance.
No you can't do this, and you wouldn't want to - either Manager is an Employee and has a Manager and an Assistant, or it doesn't and hence should have a different base class i.e. this situation indicates a design flaw. One possibility could be to return null for these properties though if that makes sense for the domain.

Categories

Resources