我正在尝试以编程方式构建表达式树。
我在输入中有一个条件类列表,它们具有以下形式:
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 );
}
}
}
Filter.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]' and 'System.Func
2 [MyObject的,System.Boolean]'。
我有点困惑。有人能更好地解释异常的原因并提出解决方案吗?
非常感谢!
答案 0 :(得分:29)
您正在将a => a == 3
和a => a == 4
合并到(a => a == 3) || (a => a == 4)
,但您应该尝试将其a => (a == 3 || a == 4)
。这不是很难手动完成,而是someone has done it for you already。寻找“结合表达式”。
修改:根据要求,提供了一个如何手动执行此操作的简单示例。
编辑2 :它使用了{4}这是.NET 4的新功能,但是at MSDN you can find a usable implementation for earlier versions。我假设MSDN代码不符合您的“第三方”的条件。您只需将ExpressionVisitor
方法更改为protected virtual Expression Visit(Expression exp)
即可。由于public
对您来说无法使用而且没有必要,现在它已经消失了。
Enumerable.Zip