3

I need to create an expression for all fields in a class. So I've adopted this post to my needs:

public static void Sample()
{
    var setters = GetFieldSetterExpressions<Account>();
    var myAccount = new Account();
    setters["AccounHolder"](myAccount, "Giovanni");
    setters["Pin"](myAccount, 123);
}

public static Dictionary<string, Action<T, object>> GetFieldSetterExpressions<T>() where T: class 
{

    var dic = new Dictionary<string,Action<T,object>>();

    var type = typeof(T);
    var fields = type.GetFields();
    foreach (var fieldInfo in fields)
    {
        Type fieldType;

        if (IsNullableType(fieldInfo.FieldType))
            fieldType = Nullable.GetUnderlyingType(fieldInfo.FieldType);
        else
            fieldType = fieldInfo.FieldType;


        ParameterExpression targetExp = Expression.Parameter(type, "target");
        ParameterExpression valueExp = Expression.Parameter(fieldType, "value");

        MemberExpression fieldExp = Expression.Field(targetExp, fieldInfo);
        BinaryExpression assingExp = Expression.Assign(fieldExp, valueExp);

        var setter = Expression.Lambda<Action<T, object>>(assingExp, targetExp, valueExp).Compile();

        dic.Add(fieldInfo.Name, setter);
    }

    return dic;
}

My problem is Expression.Lambda<Action<T,object>>(..) since the field can be for example string, I get an exeption. I've tried to intregrate Expression.Convert in my snippet, but couldn't figure out how to implement it.

How do I need to integrate the conversion part in my code?

Community
  • 1
  • 1
gsharp
  • 27,557
  • 22
  • 88
  • 134

1 Answers1

3

Expression<Action<T, object>> means that the second parameter is expected to be of type object, while your code is using propertyType. Here is how it should be:

var type = typeof(T);
var fields = type.GetFields();
foreach (var fieldInfo in fields)
{
    var targetExp = Expression.Parameter(type, "target");
    var valueExp = Expression.Parameter(typeof(object), "value");

    var fieldExp = Expression.Field(targetExp, fieldInfo);
    var assignExp = Expression.Assign(fieldExp, Expression.Convert(valueExp, fieldExp.Type));

    var setter = Expression.Lambda<Action<T, object>>(assignExp, targetExp, valueExp).Compile();

}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343