我试图创建一个表达式lambda来传递一个对象,然后获取命名属性return的值。但是,该类型仅在运行时已知。
我开始使用以下方法来处理编译时已知的类型:
private static Func<T, object> CreateExpression(string propertyName)
{
var arg = Expression.Parameter(typeof(T));
var expr = Expression.Property(arg, propertyName);
return Expression.Lambda<Func<T, object>>(expr, arg).Compile();
}
哪个工作完美。但是,我需要将其更改为处理仅在运行时已知的类型。
我应该可以这样调用代理:
public object GetPropertyValue(object obj)
{
var propertyDelegate = GetDelegate(typeof(obj));
var propertyValue = propertyDelegate (obj);
return propertyValue;
}
private Func<object, object> GetDelegate(Type type)
{
// Lookup delegate in dictionary, or create if not existing
return CreateDelegate("MyProperty", type);
}
我尝试过更改之前的CreateDelegate,但它不适用于Func<object, object>
:
Func<object,object> CreateDelegate(string propertyName, Type targetType)
{
var arg = Expression.Parameter(type);
var body = Expression.Property(arg, name);
var lambda = Expression.Lambda<Func<object,object>>(body, arg); //ArgumentException
return lambda.Compile();
}
它不接受Expresion.Parameter,因为它的类型为&#39; targetType&#39;,而不是&#39; object&#39;。
我需要Expression.Convert还是什么?
注意:委托将被多次调用(过滤方法),因此需要进行编译,以确保性能。
编辑:解决方案(由Marc Gravell提供)
变量&#39; body&#39;应更改为以下内容:
var body = Expression.Convert(
Expression.Property(
Expression.Convert(arg, type),
name),
typeof(object));
内部Convert
将输入参数转换为对象,外部Convert
转换返回值。
答案 0 :(得分:3)
是:
var arg = Expression.Parameter(typeof(object));
var expr = Expression.Property(Expression.Convert(arg, type), propertyName);
注意:返回类型(object
)表示需要装箱很多类型。既然你提到过你这样做是为了过滤:如果可能的话,试着通过创建一个Func<object,bool>
而不是装箱而在内部进行任何比较等来避免这个方框。