0

SetValue我正在尝试使用 LINQ 表达式加速反射-> 。

我的问题是这种方法:

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)发表声明,并为每种可能的类型放置一个通用方法,这会浪费很多时间?

4

2 回答 2

1

也许是这样的

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

当然需要在字典中缓存动作。

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();
}
于 2012-06-18T14:00:29.683 回答
0

使参数 ob 类型对象,并使 lambda 在内部转换为正确的字段类型。

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

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

SetValue<TObject, TProperty>

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

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

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

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

于 2012-06-18T13:36:52.227 回答