I follow to explain my problem in a much bigger class with an smaller easy to follow exact example. I got quite a big class, with a lot of properties of different types, getting and setting their respective class variable.
public class Foo() {
int property1 { get => _property1 ; set => _property1 = value;}
string property2 { get => _property2 ; set => _property2 = value;}
Vector3 property3 { get => _property3 ; set => _property3 = value;}
bool property4 { get => _property3 ; set => _property4 = value;}
}
I put 4 properties in the example, but in the real example there are a lot. I need to apply a logic in the set of all the properties, depending on property4 boolean, so instead of writting the same code in all the setters of my properties, I tried to make a generic method to be called in all of them.
So, I made a an enum:
public enum properties {
property1,
property2,
property3,
property4
}
So that I can set my properties with a method that involves reflection, taking the property type as an argument:
public void setLogic<T>(properties property, T value) {
//irrelevant code
}
So my setters turn to be:
public class Foo() {
int property1 { get => _property1 ; set { setLogic(properties.property1 , value) };}
string property2 { get => _property2 ; set { setLogic(properties.property2 , value) };}
Vector3 property3 { get => _property3 ; set { setLogic(properties.property3 , value) };}
bool property4 { get => _property4 ; set{ _property4 = value) };}
}
My problem comes when in my setLogic() the property setter is called recursively producing a stack overflow. So I solved the topic with a boolean controlled from setLogic() that controlls where the setter is being called from. So now my properties turn to be:
public class Foo() {
int property1 {
get => _property1;
set {
if (!_calledFromSetLogic)
setLogic(properties.property1 , value);
else {
_property1 = value;
_calledFromSetLogic = false;
}
}
}
string property2 {
get => _property2;
set {
if (!_calledFromSetLogic)
setLogic(properties.property2 , value);
else {
_property2 = value;
_calledFromSetLogic = false;
}
}
}
Vector3 property3 {
get => _property3;
set {
if (!_calledFromSetLogic)
setLogic(properties.property3 , value);
else {
_property3 = value;
_calledFromSetLogic = false;
}
}
}
bool property4 { get => property4; set{ _property4 = value) };}
}
The code works fine, but the setter bool control to avoid recursivity throws away all the possible cleannes brought by the SetLogic() generic method. On the other hand I cannot set the class variables in the setLogic method because I access the properties with reflection, so to set the new value in the logic I cannot avoid the recursive set without the boolean (property.SetValue() from the reflection class sets the new value calling the set once again, so infinite loop).
If I dont do this, I have to paste the setLogic() method, instead of been generic, copy pasted for each of the properties in the set, which is not very clean code neither.
Is there not a clean solution for this, where the setter can be passed as an argument, or a generic method that avoids infinite recursive set?
I was thinking of something like
private setLogic<T>(Action<> setterMethod, T value) {
//so that the property involved might be already in the setter?
}
or other kind of setLogic with the generic class properties that avoids the infinite loop, of whom a cannot think of.
Hope I made myself understood.