使用OrElse和AndAlso表达式方法的异常

时间:2012-02-10 16:54:48

标签: linq entity-framework linq-to-entities dynamic-linq

我正在尝试以编程方式构建表达式树。

我在输入中有一个条件类列表,它们具有以下形式:

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;
}

当我有一个条件时,一切都有效但当我尝试使用AndOrAndAlsoOrElse静态方法之一组合表达式时,我会收到一个InvalidOperationException说:

  

二进制运算符Or未定义类型   'System.Func 2[MyObject,System.Boolean]' and 'System.Func 2 [MyObject的,System.Boolean]'。

我有点困惑。有人能更好地解释异常的原因并提出解决方案吗?

非常感谢!

1 个答案:

答案 0 :(得分:29)

您正在将a => a == 3a => 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