问题 创建表达式树以访问Generic类型的属性


我需要编写一个泛型方法,它以字符串格式获取泛型类型的实例和属性名称,并返回一个表达式树

我需要转换一个简单的lambda表达式

a => a.SomePropertyName

哪里 a 是泛型类型 将有一个财产 通过这个名字 SomePropertyName

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

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

这可能很简单,但我不熟悉Expression树,如果有类似的问题,请链接并关闭


12322
2018-01-24 11:45


起源



答案:


假设事先不知道参数类型和返回类型,您可能必须使用一些 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 不知道的 签名 兰达,通过:

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

9
2018-01-24 11:51



我们不能通过使用反射来获取类型来将类型传递给Func a 和财产 SomePropertyName ? - Vamsi
@VamsiKrishna第二个例子有lambda代码为你找出所有类型,但是:如果你使用完整的通用版本,你需要知道属性类型 静态。因此我使用的原因 object 在第一个例子中,因为至少这将始终有效。如果你有一个通用的方法 TArg 和 TResult那么你可以建立一个 Expression<Func<TArg,TResult>>, 当然。 - Marc Gravell♦
我想我明白了,谢谢:) - Vamsi


答案:


假设事先不知道参数类型和返回类型,您可能必须使用一些 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 不知道的 签名 兰达,通过:

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

9
2018-01-24 11:51



我们不能通过使用反射来获取类型来将类型传递给Func a 和财产 SomePropertyName ? - Vamsi
@VamsiKrishna第二个例子有lambda代码为你找出所有类型,但是:如果你使用完整的通用版本,你需要知道属性类型 静态。因此我使用的原因 object 在第一个例子中,因为至少这将始终有效。如果你有一个通用的方法 TArg 和 TResult那么你可以建立一个 Expression<Func<TArg,TResult>>, 当然。 - Marc Gravell♦
我想我明白了,谢谢:) - Vamsi


你可以用这个:

var p = Expression.Parameter(a.GetType(), "x");
var body = Expression.Property(p, "SomePropertyName");

Expression.Lambda(body, p);

4
2018-01-24 11:51



在第一行是什么“x”? - Vamsi
@VamsiKrishna只是参数的名称。在你的 a => a.SomePropertyName 例如,它是 a。 - Marc Gravell♦
正如Marc所说,它是参数的名称。它实际上可以省略,没有必要在这里指定它。 - Daniel Hilgarth
@DanielHilgarth谢谢:) - Vamsi