使用 OrElse 和 AndAlso 表达式方法时出现异常
我正在尝试以编程方式构建表达式树。
我的输入中有一个条件类列表,其形式如下:
public class Filter
{
public string field { get; set; }
public string operator { get; set; }
public string value { get; set; }
}
当我构建 Expression
对象时,我按以下方式为每个条件创建一个 Expression
foreach ( Filter sf in rules ) {
Expression ex = sf.ToExpression( query );
if ( mainExpression == null ) {
mainExpression = ex;
}
else {
if ( logicalCondition == "AND" ) {
mainExpression = Expression.And( mainExpression, ex );
}
else if ( logicalCondition == "OR" ) {
mainExpression = Expression.Or( mainExpression, ex );
}
}
}
过滤器.ToExpression() 方法是这样实现的
public override Expression ToExpression( IQueryable query ) {
ParameterExpression parameter = Expression.Parameter( query.ElementType, "p" );
MemberExpression memberAccess = null;
foreach ( var property in field.Split( '.' ) )
memberAccess = MemberExpression.Property( memberAccess ?? ( parameter as Expression ), property );
ConstantExpression filter = Expression.Constant( Convert.ChangeType( value, memberAccess.Type ) );
WhereOperation condition = (WhereOperation)StringEnum.Parse( typeof( WhereOperation ), operator );
LambdaExpression lambda = BuildLambdaExpression( memberAccess, filter, parameter, condition, value );
return lambda;
}
当我有一个条件但当我尝试使用 And
、Or
、AndAlso 之一组合表达式时,一切正常
、OrElse
静态方法我收到一个 InvalidOperationException
,内容如下:
没有为类型定义二元运算符 Or 'System.Func
2[MyObject,System.Boolean]' 和 'System.Func
2[MyObject,System.Boolean]'。
我有点困惑了。有人可以更好地解释异常的原因并提出解决方案吗?
非常感谢!
I am trying to build an expression tree programmatically.
I have in my input, a list of condition classes which have the following form:
public class Filter
{
public string field { get; set; }
public string operator { get; set; }
public string value { get; set; }
}
When I build the Expression
object I create an Expression
for every condition in the following way
foreach ( Filter sf in rules ) {
Expression ex = sf.ToExpression( query );
if ( mainExpression == null ) {
mainExpression = ex;
}
else {
if ( logicalCondition == "AND" ) {
mainExpression = Expression.And( mainExpression, ex );
}
else if ( logicalCondition == "OR" ) {
mainExpression = Expression.Or( mainExpression, ex );
}
}
}
The Filter.ToExpression() method is implemented like this
public override Expression ToExpression( IQueryable query ) {
ParameterExpression parameter = Expression.Parameter( query.ElementType, "p" );
MemberExpression memberAccess = null;
foreach ( var property in field.Split( '.' ) )
memberAccess = MemberExpression.Property( memberAccess ?? ( parameter as Expression ), property );
ConstantExpression filter = Expression.Constant( Convert.ChangeType( value, memberAccess.Type ) );
WhereOperation condition = (WhereOperation)StringEnum.Parse( typeof( WhereOperation ), operator );
LambdaExpression lambda = BuildLambdaExpression( memberAccess, filter, parameter, condition, value );
return lambda;
}
Everything works when I have a single condition but when I try to combine expressions using one of the And
, Or
, AndAlso
, OrElse
static methods I receive an InvalidOperationException
that says:
The binary operator Or is not defined for the types
'System.Func2[MyObject,System.Boolean]' and
2[MyObject,System.Boolean]'.
'System.Func
I am getting a little bit confused. Can somebody better explain the reasons of the exception and suggest a solution?
Thanks very much!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您正在组合
a =>; a == 3 和 a => a == 4
变为(a => a == 3) || (a => a == 4)
,但你应该尝试使其a =>; (a == 3 || a == 4)
。手动完成此操作并不难,但是有人已经为您完成了。寻找“组合表达式”。编辑:根据要求,如何手动执行此操作的简单示例。
编辑 2:它使用 .NET 4 中新增的
ExpressionVisitor
,但是在 MSDN 上您可以找到早期版本的可用实现。我假设 MSDN 代码不符合您的目的的“第三方”。您只需将protected virtual Expression Visit(Expression exp)
方法更改为public
即可。由于Enumerable.Zip
对您不可用并且没有必要,因此它现在已经消失了。You're combining
a => a == 3
anda => a == 4
into(a => a == 3) || (a => a == 4)
, but you should instead be trying to make ita => (a == 3 || a == 4)
. This is not too hard to do manually, but someone has done it for you already. Look for "Combining Expressions".Edit: as requested, a simple example of how to do this manually.
Edit 2: it uses
ExpressionVisitor
which is new to .NET 4, but at MSDN you can find a usable implementation for earlier versions. I'm assuming MSDN code doesn't qualify as "third party" for your purposes. You only need to change theprotected virtual Expression Visit(Expression exp)
method topublic
. And asEnumerable.Zip
is unavailable for you and it isn't necessary, it is gone now.