2011-06-12 91 views
3

我试图用给定的类型和属性名称来构建属性选择器表达式。即t => t.PropertyName。动态属性选择器lambda函数

以下代码编译得很好,但结果为空值。有人可以指出代码中的错误吗?

public static Expression<Func<T,object>> CreatePropSelectorExpression(string propName) where T:class,new() 
    { 
    var temp = Activator.CreateInstance<T>(); 
    ParameterExpression t = Expression.Parameter(typeof(T),"t"); 
    MemberExpression member = Expression.PropertyOrField(Expression.Constant(temp),propName); 
    return Expression.Lambda<Func<T,object>>(member,t); 
    } 

在此先感谢

+0

不要打扰。已经找到了解决方案。 需要使用成员表达式而不是临时变量 – user759141 2011-06-12 07:06:59

回答

8

你实际上并不需要创建对象T,你只是创造一些表达式树的一个实例。这一切都归结到这真的:

Expression<Func<T, object>> CreatePropSelectorExpression<T>(string propertyName) 
{ 
    var parameter = Expression.Parameter(typeof(T)); 
    var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(object)); 
    return Expression.Lambda<Func<T, object>>(body, parameter); 
} 
+0

Expression.Convert()的用途是什么?它看起来像只适用于:var body = Expression.PropertyOrField(parameter,propertyName); – 0lukasz0 2013-03-23 16:55:01

+1

convert方法确保表达式具有某种类型。最终归结为演员阵容。如果属性类型是“ValueType”,它将被要求,因为它会变成一个装箱操作。尽管在构建表达式时,最好尽可能生成预期类型的​​表达式。 – 2013-03-23 18:04:04

+0

好,但你可以提供一个嵌套的选择器与IEnumerable propertyNames''作为参数 – bradgonesurfing 2013-04-17 09:10:48

1

嵌套版本

static Expression<Func<R, O>> 
CreatePropSelectorExpression<R,O>(IEnumerable<string> propertyName) 
{ 
    ParameterExpression parameter = Expression.Parameter(typeof(R)); 
    Expression selector = propertyName 
     .Aggregate((Expression)parameter, 
       (a, name) => Expression.PropertyOrField(a, name)); 
    return Expression.Lambda<Func<R,O>>(selector, parameter); 
}