I am writing a settings system which relies on adding attributes to properties, and then using reflection.
For example, I create sliders by adding a SliderAttribute to float properties, then finding all those attributes and creating delegates to modify the associated property like so:
Func<float> getterDelegate = Delegate.CreateDelegate(typeof(Func<float>), arg, property.GetGetMethod()) as Func<float>;
Action<float> setterDelegate = Delegate.CreateDelegate(typeof(Action<float>), arg, property.GetSetMethod()) as Action<float>;
settingObj = new Slider(sliderAttribute, getterDelegate, setterDelegate);
Now, I'd like to create multiple choice objects by applying the same logic to enum values. That is I want to generate getter/setter delegates which modify the enum property via the underlying type (which we can assume is always int.)
The ideal would be the following, which returns the error ArgumentException: method return type is incompatible
. Same result if I use the 'Enum' type.
Func<int> getterDelegate = Delegate.CreateDelegate(typeof(Func<int>), arg, property.GetGetMethod()) as Func<int>;
Action<int> setterDelegate = Delegate.CreateDelegate(typeof(Action<int>), arg, property.GetSetMethod()) as Action<int>;
settingObj = new MultipleChoice(multipleChoiceAttribute, getterDelegate, setterDelegate, property.PropertyType);
You can create delegates that return and take the actual enum type, like this:
Delegate getterEnumDelegate = Delegate.CreateDelegate(
typeof(Func<>).MakeGenericType(property.PropertyType), arg, property.GetGetMethod()
);
Delegate setterEnumDelegate = Delegate.CreateDelegate(
typeof(Action<>).MakeGenericType(property.PropertyType), arg, property.GetSetMethod()
);
To convert these into Action<int>
and Func<int>
, you just need to do:
Func<int> getterDelegate = () => (int)getterEnumDelegate.DynamicInvoke();
Action<int> setterDelegate = x => setterEnumDelegate.DynamicInvoke(x);