如何使用LINQ从类型对象创建lambda表达式?

时间:2012-06-18 13:31:31

标签: c# .net linq generics linq-expressions

我试图加快反思 - >带有LINQ表达式的SetValue

我的问题是这个方法:

public void SetValue<T>(T obj)
{
    FieldInfo field = typeof(T).GetField("Title", BindingFlags.Instance |
                                                  BindingFlags.Public |
                                                  BindingFlags.IgnoreCase);

    ParameterExpression targetExp = Expression.Parameter(typeof(T), "target");
    ParameterExpression valueExp = Expression.Parameter(field.FieldType, "value");

    // Expression.Property can be used here as well
    MemberExpression fieldExp = Expression.Field(targetExp, field);
    BinaryExpression assignExp = Expression.Assign(fieldExp, valueExp);

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

    setter(obj, "Hello World");

    //Console.WriteLine(obj.title);
}

我称之为:

var ii = new Controllers.SearchController.InstantItem();

SetValue<Controllers.SearchController.InstantItem>(ii);

问题在于这一行:

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

由于Action使用泛型,我无法用field.FieldType ...

替换字符串

我是否有可能在不必编写switch(field.FieldType)语句的情况下执行此操作,并为每种可能的类型设置通用方法,这会占用大量时间?

2 个答案:

答案 0 :(得分:1)

也许是这样的

action = FormAction(fieldInfo);
action(obj,valueToSet);

当然,需要在字典中缓存Actions。

static Action<object, object> FormAction(FieldInfo fieldInfo)
{
    ParameterExpression obj = Expression.Parameter(typeof(object), fieldInfo.Name);
    ParameterExpression value = Expression.Parameter(typeof(object));

    MemberExpression fieldExp = Expression.Field(Expression.Convert(obj, fieldInfo.DeclaringType), fieldInfo.Name);
    BinaryExpression assignExp = Expression.Assign(fieldExp, Expression.Convert(value, fieldInfo.FieldType));

    return Expression.Lambda<Action<object, object>>(assignExp, obj, value).Compile();
}

答案 1 :(得分:0)

创建参数ob类型对象,并在内部将lambda强制转换为正确的字段类型。

或者,在运行时动态构造委托类型(Action)。

或者,您可以按如下方式定义SetValue:

SetValue<TObject, TProperty>

这将使该方法在属性类型上具有通用性。

编辑:听起来选项1最适合您。您需要将参数类型更改为typeof(object)并添加强制转换:

valueExp = Expression.Convert(valueExp, field.FieldType)

您需要使用Action<T, object>作为委托类型。