表达式类型System.Int64'不能用于返回类型' System.Object'

时间:2015-08-21 17:55:55

标签: c# .net linq reflection expression-trees

我正在尝试创建以下形式的表达式:

e => e.CreationDate;

CreationDate的类型为long,但我希望表达式返回object

我想使用object作为返回类型,因为表达式是在运行时基于查询参数动态构建的。 query参数指定要在表达式中访问的属性,例如:

> entities?order=creationDate
> entities?order=score

正如您所看到的,我可以使用不同类型的不同属性进行排序,因此返回类型object将允许我将表达式构建为尽可能通用。

问题在于,当我尝试创建表达式时:

ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e");
Expression propertyAccess = Expression.Property(entityParameter, property);
Expression<Func<Entity, object>> result = Expression.Lambda<Func<Entity, object>>(propertyAccess, entityParameter);

我得到以下异常:

  

表达类型&Systems.Int64&#39;不能用于返回类型   &#39; System.Object的&#39;

很奇怪,因为据我所知,所有类型都从object延伸(似乎表达树还不支持多态)。

然而,我在网上搜索并偶然发现了类似的问题:

Expression of type 'System.Int32' cannot be used for return type 'System.Object'

按照Jon Skeet的回答,我将最后一行修改为:

Expression<Func<Entity, object>> result = Expression.Lambda<Func<Entity, object>>(Expression.Convert(propertyAccess, typeof(object)), entityParameter);

这很好用,但它不能生成我想要的表达式。相反,它生成这样的东西:

e => Convert(e.CreationDate)

我无法使用此解决方案,因为如果表达式主体不是MemberExpression(即成员访问操作),程序后面会抛出异常

我一直在互联网上搜索一个令人满意的答案,但是找不到任何答案。

如何在返回类型为e => e.CreationDate的情况下实现object

2 个答案:

答案 0 :(得分:1)

根据您使用result的方式,您可以使用委托类型Func<Entity, long>动态创建它,并将其键入LambdaExpression

ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e");
Expression propertyAccess = Expression.Property(entityParameter, property);
var funcType = typeof(Func<,>).MakeGenericType(typeof(Entity), property.PropertyType);
LambdaExpression result = Expression.Lambda(funcType, propertyAccess, entityParameter);

答案 1 :(得分:1)

简短的回答:不,这是不可能的。需要将值类型加框以将其视为对象。编译器通常会为您执行此操作,但如果您自己构建代码(例如表达式树),则需要将其指定为显式转换,就像您在找到的答案中看到的那样。如果您不能将它作为非泛型的LambdaExpression,我会在您期望MemberExpression或使用PropertyInfo的情况下另外处理转换情况,并仅在最后一刻构造orderby Expression。