我正在使用一个包含一个带有表达式参数x =>的函数的库。 x.Name。
使用反射,我试图为Foo的每个属性调用它。这意味着我需要创建Expression< Func< Foo,object>>类型的表达式。对于每个房产。
我一直在阅读表达树,但没有任何内容涵盖这种情况。
foreach (var property in typeof(Foo).GetProperties())
{
ParameterExpression pe = Expression.Parameter(typeof(Foo), "x");
MemberExpression me = Expression.Property(pe, property.Name);
Expression<Func<Foo, object>> expression = ... // x => x.Name
Bar(expression, property.Name);
}
解决:
foreach (var property in typeof(Foo).GetProperties())
{
ParameterExpression pe = Expression.Parameter(typeof(Foo), "x");
MemberExpression me = Expression.Property(pe, property.Name);
var expression = (Expression<Func<Foo, object>>)
Expression.Lambda(Expression.Convert(me, typeof(object)), pe);
Bar(expression, property.Name);
}
答案 0 :(得分:1)
问题是你在编译时显然不知道类型Foo
,否则你可以使用泛型Expression.Lambda
重载创建一个lambda表达式并且没问题。
有一个重载Expression.Lambda
将创建LambdaExpression
并从您指定的表达式派生类型参数。这意味着,它将从参数表达式和您用作主体的成员表达式中扣除它。
在这两种实现中,都有一个问题。返回类型object
是引用类型。但是,属性可能会返回值类型(例如int
),这需要强制转换。通常,编译器会为您执行此操作。在这种情况下,你必须自己做。
private IEnumerable<LambdaExpression> CreateExpressions(Type fooType)
{
foreach (var property in fooType.GetProperties())
{
ParameterExpression pe = Expression.Parameter(fooType, "x");
MemberExpression me = Expression.Property(pe, property.Name);
yield return Expression.Lambda(Expression.Convert(me, typeef(object)), pe);
}
}
如果您在编译时知道类型Foo
,则只需将通用参数Func<Foo, object>
添加到Lambda
方法即可。