I've been understanding PredicateBuilder
extension methods written Joseph Albahari and I saw this Expression.Invoke
and honestly I couldn't understand the reason of it in the following method :
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);
}
Even though he explained it a little bit:
The interesting work takes place inside the And and Or methods. 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.
MSDN tells me that:
Creates an InvocationExpression that applies a delegate or lambda expression to a list of argument expressions.
and this makes sense to me little bit. So basically I don't have to pass in any arguments if I use the expression like that.
But for some reason I couldn't quite understand it. Maybe I am tired or something.
Questions:
InvocationExpression
.Or<T>
method (or AndElse<T>
) method works little better?Update:
I was thinking about InvocationExpression
when I was coming from work to home and it hinted in my mind like this:
When we invoke a method, we simple say CallMe(phoneNumber, time);
and this is called method invocation. Then, InvocationExpression
should be an expression that expresses CallMe(phoneNumber, time);
. It is similar to LambdaExpression
which express a lambda such as t => t + 2
. So basically it is a method invocation that is applied to arguments (not parameters). So as invocation, it is no longer expected to need a parameters but perhaps return something since arguments are already applied to its parameters.
For more information about the code I am talking about, please visit http://www.albahari.com/nutshell/predicatebuilder.aspx
Imagine you weren't working with expressions, but with delegates. Then you could write Or
like this:
public static Func<T, bool> Or<T>(this Func<T, bool> expr1, Func<T, bool> expr2)
{
return x => expr1(x) || expr2(x);
}
You create a new delegate that invokes the two delegates, combined using ||
. When you rewrite this to use expressions, invoking a delegate turns into Expression.Invoke()
:
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var parameter = Expression.Parameter(typeof(T), "x");
var invokedExpr1 = Expression.Invoke(expr1, parameter);
var invokedExpr2 = Expression.Invoke(expr2, parameter);
return Expression.Lambda<Func<T, bool>>(
Expression.OrElse(invokedExpr1, invokedExpr2), parameter);
}
The reason why the actual Or
isn't written like this is (most likely) an optimization: you don't have to invoke both expressions, you can reuse the body and parameter from one of them. (But you can't reuse both of them, because they have different parameters.)