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
The Invoke method searches up the control's parent chain until it finds a control or form that has a window handle if the current control's underlying window handle does not exist yet. If no appropriate handle can be found, the Invoke method will throw an exception.
Only expression trees that represent lambda expressions can be executed. Expression trees that represent lambda expressions are of type LambdaExpression or Expression<TDelegate>. To execute these expression trees, call the Compile method to create an executable delegate, and then invoke the delegate.
Object. Gets the Expression that represents the instance for instance method calls or null for static method calls. Type. Gets the static type of the expression that this Expression represents.
LINQ introduced the new type called Expression that represents strongly typed lambda expression. It means lambda expression can also be assigned to Expression<TDelegate> type. The . NET compiler converts the lambda expression which is assigned to Expression<TDelegate> into an Expression tree instead of executable code.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With