Question

I am using the PredicateBuilder class from http://www.albahari.com/nutshell/predicatebuilder.aspx

public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }

this extension method is chaining Predicates with the OR operator. on the page, the explanation says

We start by invoking the second expression with the first expression’s parameters. An Invoke expression calls another lambda expression using the given expressions as arguments. We can create the conditional expression from the body of the first expression and the invoked version of the second. The final step is to wrap this in a new lambda expression.


so if for example i have

Predicate<Book> p1 = b => b.Title.Contains("economy");
Predicate<Book> p2 = b=>b.PublicationYear>2001;
Predicate chain = p1.And(p2);

I didn't quite get the exlanation. can someone please explain how the code of the extension method above is working? thanks

Était-ce utile?

La solution

Let's rewrite the method body like this:

return Expression.Lambda<Func<T, bool>>(
    Expression.OrElse(
        expr1.Body,
        Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>())
    ),
    expr1.Parameters);

We should also keep in mind that expr1 is your existing expression that takes a T and returns a bool. Additionally, while the expression trees we are working with do not actually do anything (they represent something instead), I am going to use "do" henceforth because it makes for much easier reading. Technically for an expression tree to actually do something you have to compile it first and then invoke the resulting delegate.

Ok, so what do we have here? This is a lambda expression that takes whatever parameters expr1 takes (see last line) and whose body, as per the documentation, is

a BinaryExpression that represents a conditional OR operation that evaluates the second operand only if the first operand evaluates to false.

The first operand is expr1.Body, which means the resulting function (not actually a function, see note above) evaluates expr1. If the result is true it returns true on the spot. Otherwise, it invokes expr2 with the same parameters as those passed to expr1 (this means the single T parameter) and returns the result of that.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top