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

本文关键字:System 用于 返回类型 不能 Object 类型 Int64 表达式 | 更新日期: 2023-09-27 18:09:13

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

e => e.CreationDate;

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

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

> 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);

我得到以下异常:

System类型的表达式。Int64'不能用作返回类型的系统。对象'

这很奇怪,因为据我所知,所有类型都从object扩展(似乎多态性尚未被表达式树支持)。

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

System类型的表达式。Int32'不能用于返回类型'System '。对象'

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

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

这工作得很好,但它不能生成我想要的表达式。相反,它生成如下内容:

e => Convert(e.CreationDate)

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

我一直在网上寻找一个满意的答案,但没有找到。

返回类型为objecte => e.CreationDate如何实现?

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

根据您使用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);

简短回答:不,这是不可能的。值类型需要装箱才能被视为对象。编译器通常会为你做,但如果你自己构建代码(例如表达式树),你需要将其指定为显式转换,就像你在找到的答案中看到的那样。如果您不能将其作为非泛型LambdaExpression,那么我会在您期望MemberExpression的地方额外处理转换情况,或者使用PropertyInfo,并仅在最后一刻构造order Expression。