Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Expression.Invoke() Method

Tags:

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:

  1. When and in which situation does it makes sense to use InvocationExpression.
  2. Can anyone explain how 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

like image 743
Tarik Avatar asked Nov 08 '13 23:11

Tarik


People also ask

What is invoke () in C#?

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.

How do you execute an expression?

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.

What is method call expression?

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.

What is expression in LINQ?

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.


1 Answers

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.)

like image 63
svick Avatar answered Sep 27 '22 16:09

svick