创建访问泛型类型属性的表达式树

12

我需要编写一个通用方法,该方法接受泛型类型的实例和以字符串格式表示的属性名称,并返回一个表达式树。

我需要将一个简单的Lambda表达式转换。

a => a.SomePropertyName

其中a是泛型类型,其将有一个名为SomePropertyName的属性。

我知道我们可以使用以下反射代码获取属性信息。

System.Reflection.PropertyInfo propInfo = a.GetType().GetProperty("SomePropertyName");

这可能很简单,但我不熟悉表达式树。如果有类似的问题,请提供链接并关闭此问题。

2个回答

9

假设参数类型和返回类型事先不知道,你可能需要使用一些object,但从根本上讲这只是:

var p = Expression.Parameter(typeof(object));
var expr = Expression.Lambda<Func<object, object>>(
    Expression.Convert(
        Expression.PropertyOrField(
             Expression.Convert(p, a.GetType()), propName), typeof(object)), p);

如果输入和输出类型已知,您可以调整Func<,>参数,并可能删除Expression.Convert。在极端情况下,您可以通过以下方式获得一个lambda表达式,而不知道lambda的签名:

var p = Expression.Parameter(a.GetType());
var expr = Expression.Lambda(Expression.PropertyOrField(p, propName), p);

我们不能通过使用反射来获取a和属性SomePropertyName的类型并将其传递给Func吗? - Vamsi
@VamsiKrishna 第二个示例中的lambda代码可以为您找出所有类型,但是:如果您使用完整的通用版本,则需要静态地知道属性类型。这就是为什么我在第一个示例中使用了“object”的原因,因为至少它总是有效的。当然,如果您有一个接受TArgTResult的通用方法,那么您可以构建一个Expression<Func<TArg,TResult>> - Marc Gravell

4
您可以使用以下方法:
var p = Expression.Parameter(a.GetType(), "x");
var body = Expression.Property(p, "SomePropertyName");

Expression.Lambda(body, p);

在第一行中,“x”是什么? - Vamsi
2
@VamsiKrishna只是参数的名称。在您的 a => a.SomePropertyName 示例中,它是 a - Marc Gravell
1
正如Marc所说,这是参数的名称。实际上它可以省略,这里并不真正需要指定它。 - Daniel Hilgarth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接