Mat*_*ero 5 .net c# linq reflection expression-trees
我正在尝试创建以下形式的表达式:
e => e.CreationDate;
Run Code Online (Sandbox Code Playgroud)
CreationDate
类型为long
,但是我希望表达式返回 an object
。
我想用作object
返回类型,因为表达式是在运行时根据查询参数动态构建的。查询参数指定表达式中要访问的属性,例如:
> entities?order=creationDate
> entities?order=score
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我可以按不同类型的不同属性进行排序,因此返回类型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);
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
“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);
Run Code Online (Sandbox Code Playgroud)
这工作正常,但它不会生成我想要的表达式。相反,它会生成如下内容:
e => Convert(e.CreationDate)
Run Code Online (Sandbox Code Playgroud)
我无法使用此解决方案,因为稍后在程序中,如果表达式主体不是 a MemberExpression
(即成员访问操作),则会引发异常
我一直在互联网上寻找令人满意的答案,但没有找到。
我怎样才能实现e => e.CreationDate
返回类型的位置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);
Run Code Online (Sandbox Code Playgroud)