I need one class to modify the property of several other classes. So i need to somehow delegate or bind the property to the modifying class. This is a mockup of how the classes are organised.
MainClassA IHasAmount
int Amount
Price
Goodstype
MainClassB IHasAmount
int Amount
Quality
Weight
IHasAmount
int Amount get; set;
AmountModifierClass
IHasAmount HasAmount
This way Amount would be modified like this:
HasAmount.Amount -= AmountModifier();
Its just a tiny detail annoying me that the name gets redundant. I would like to be able to type it just as a property or field. So i try with this:
A)
int Amount=> HasAmount.Amount
But that doesnt work because it becomes read only. So i assume that its not pointing too the original Amount property but its a getter, without a setter. So i try the following:
B)
int Amount { get { return HasAmount.Amount; } set { HasAmount.Amount = value; }}
And this works! I can now use a private property of the AmountModifier class that is bound to the Amount property of the MainClass like so Health = HealthModifer
My question is if this is an efficient and not to complex of solving this situation? I guess what i need is to be able to bind one property to another in another class.
There is no way to have a property automatically delegate to another property using C# language only features.
The way I have accomplished this is by creating an object behind each property, so the property ends up looking roughly like this:
int Amount { get => GetPropertyValue(); set => SetPropertyValue( value ); }
The GetPropertyValue() and SetPropertyValue() methods receive the name of the property ("Amount") by using the CallerMemberName attribute. Internally, they look-up a property object by name in a dictionary mapping names to property objects, and they get or set the value of that property object.
Then, delegation can be achieved as follows:
int AmountOfOtherObject
{
get => GetDelegatingPropertyValue( otherObject, nameof( otherObject.Amount ) );
set => SetDelegatingPropertyValue( otherObject, nameof( otherObject.Amount ), value );
}
The GetDelegatingPropertyValue() and SetDelegatingPropertyValue() methods lookup a special kind of property in the same dictionary, which is a delegating property which delegates to the corresponding property of the "other" object.
It ends up being quite a bit more verbose than I wish it was, and it also requires substantial infrastructural support. If you try implementing this, be prepared for a deep dive down a long rabbit hole.
See properties
// This one indeed is a getter-only
int Amount => HasAmount.Amount;
and
int Amount { get => HasAmount.Amount; }
and
int Amount { get { return HasAmount.Amount; } }
Are just different ways to write the exact same thing.
So in your case your working solution
int Amount
{
get { return HasAmount.Amount; }
set { HasAmount.Amount = value; }
}
can also be written as
int Amount
{
get => HasAmount.Amount;
set => HasAmount.Amount = value;
}
So if you don't want to expose the HasAmount reference this is a totally valid way of implementing such property and I don't see an issue with efficiency.