I looked up for something similar, but I couldn't find anything that I am able to comprehend at the moment. I never needed to use Expressions so I don't really understand how they work, although they do look interesting. I can spend time studying them, but currently I am using them just for one single purpose, which is not really what they have been designed for, although I may be wrong here. It's to generate a run time function to set a value in to a FieldInfo of a class instance.
I would have done it with opcodes, which I understand better, but opcodes are not available on all the platforms I need to work with (i.e.: UWP). With NetStandard 2.0 I may actually use them, but before I try it, I wonder if you can tell me if this is possible. Currently I am using this code:
public static CastedAction<T> MakeSetter(FieldInfo field)
{
if (field.FieldType.IsInterfaceEx() == true && field.FieldType.IsValueTypeEx() == false)
{
ParameterExpression targetExp = Expression.Parameter(typeof(T), "target");
ParameterExpression valueExp = Expression.Parameter(typeof(object), "value");
MemberExpression fieldExp = Expression.Field(targetExp, field);
UnaryExpression convertedExp = Expression.TypeAs(valueExp, field.FieldType);
BinaryExpression assignExp = Expression.Assign(fieldExp, convertedExp);
Type type = typeof(Action<,>).MakeGenericType(typeof(T), typeof(object));
var setter = Expression.Lambda(type, assignExp, targetExp, valueExp).Compile();
return new CastedAction<T>(setter);
}
throw new ArgumentException();
}
}
public class CastedAction<T>
{
readonly Action<T, object> setter;
public CastedAction(Delegate setter)
{
this.setter = (Action<T, object>)setter;
}
public CastedAction(Action<T, object> setter)
{
this.setter = setter;
}
public void Call(ref T target, object value)
{
setter(target, value); //I want to pass ref target here
//target = setter(target, value); may be an alternative
}
However nowe I want to support structs as well and what I would like to have is to pass the first parameter in the setter Action by ref. As far as I understood this is not possible.
Therefore I was thinking to generate a Func returning the modified object passed by parameter. Here I got totally lost, too hard for me.
Even tho you may find a solution for this, I may still think to switch 100% op code as returning and passing by value could affect the performance of my application.
Action<ref T>, though... not sure ifExpressionis going to work with a custom delegate with arefarg