我试图加快反思 - >带有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)
语句的情况下执行此操作,并为每种可能的类型设置通用方法,这会占用大量时间?
答案 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>
作为委托类型。