【发布时间】:2015-08-21 17:55:55
【问题描述】:
我正在尝试创建以下形式的表达式:
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 扩展而来(表达式树似乎还不支持多态性)。
尽管如此,我在网上搜索并偶然发现了这个类似的问题:
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?
【问题讨论】:
-
你需要构造一个
Expression<Func<Entity, object>>吗?您可以创建一个非泛型LambdaExpression并改为构造一个Func<Entity, long>。 -
@Lee 我想使用相同的辅助方法来构建任何
MemberExpression,这意味着有时我会返回long,有时会返回string。如果我不通用,那么我将不得不为每个返回类型或实现复制相同的方法逻辑 -
你可以把它变成
Expression<Func<Entity, TResult>>,类似于OrderByin linqIQueryable -
如果你想对
OrderBy使用这个表达式,有更好的方法,见stackoverflow.com/a/31959568/1847988
标签: c# .net linq reflection expression-trees