类型为“System.Int64”的表达式不能用作返回类型“System.Object”。

5
我会尽力帮助您翻译以下内容,这是关于编程的:

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

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”的表达式无法用作返回类型“System.Object”

这很奇怪,因为据我所知,所有类型都是从object派生的(似乎表达式树还不支持多态)。
尽管如此,我在网上搜索并发现了类似的问题:

类型为“System.Int32”的表达式无法用作返回类型“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(即成员访问操作),就会抛出异常。

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

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


你需要构建一个 Expression<Func<Entity, object>> 吗?你可以创建一个非泛型的 LambdaExpression,并构造一个 Func<Entity, long> - Lee
@Lee 我想使用同一个辅助方法来构建任何 MemberExpression,这意味着有时我会返回一个 long,有时返回一个 string。如果我不使用泛型,那么我将不得不为每个返回类型或实现重复相同的方法逻辑。 - Matias Cicero
你可以将它定义为 Expression<Func<Entity, TResult>>,类似于linq中的IQueryable中的OrderBy - Taher Rahgooy
如果您想在“OrderBy”中使用此表达式,有更好的方法可以实现,请参见https://dev59.com/xlwZ5IYBdhLWcg3wBcMJ#31959568。 - Taher Rahgooy
2个回答

2

根据你使用 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
短答案:不,这是不可能的。值类型需要装箱才能被视为对象。编译器通常会为您完成此操作,但如果您自己构建代码(例如表达式树),则需要将其指定为显式转换,就像您在找到的答案中看到的那样。如果您无法将其作为非泛型LambdaExpression,则应额外处理转换情况,在您期望MemberExpression时使用PropertyInfo,并仅在最后一刻构造orderby Expression。

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