Understanding Expression.Invoke() Method - c#

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:
When and in which situation does it makes sense to use InvocationExpression.
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

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

Related

Expression trees, apply predicate to property

Let's say that I have a predicate stored as Expression<Func<typeB, bool>> that I would like to apply to the property of objA, but I have only access to Expression<Func<TypeA, bool>, and I know that objA has property propB of type typeB.
How to combine these expression trees?
An example to better explain what I would like to achieve:
Expression<Func<TypeB, bool>> expr1 = (b => b.Where(b.propC.HasFlag(flag))
Expression<Func<TypeB, bool>> expr2 = (b => b.Where(b.propD != null)
...
// Now let's combine these with Or operator
InvocationExpression invocationExpression = Expression.Invoke((Expression) expr2.Expand<Func<typeB, bool>>(), expr1.Parameters.Cast<Expression>());
Expression<Func<typeB, bool>> combinedExpr = Expression.Lambda<Func<typeB, bool>>((Expression) Expression.OrElse(expr1.Body, (Expression) invocationExpression), (IEnumerable<ParameterExpression>) expr1.Parameters);
// To complete my task I need to pass an argument of type Expression<Func<TypeA, bool>> to method, but I am not sure how to build such an expression tree.
// That also could be written as a literal like that:
AddCriterion(objA => objA.propB.Where(b => b.propC.HasFlag(flag) || b.propD != null))
I've found the answer in another stack overflow question that covers exactly the same topic.
Combine Expression (Expression<Func<TIn,TOut>> with Expression<Func<TOut, bool>>)

Passing compiled expressions to where() clause

I'm using calculated properties on my EF object which can't be passed directly to a where() clause:
{"The specified type member 'SomeProp' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."}
Based on what I read on SO, this could be avoided by passing a Expression<Func<T, bool>> as the argument to where().
Compiling the expression to a Func works fine:
Expression<Func<Foo, bool>> expr = e => f => f.SomeCalculatedProperty == 1;
Func<Foo, bool> compiled = expr.Compile();
Foo result = dbContext.Foo.Where(compiled);
But passing the expression gives me the error above, i.e:
Expression<Func<Foo, bool>> expr = e => f => f.SomeCalculatedProperty == 1;
Foo result = dbContext.Foo.Where(e);
Based on this, shouldn't the last example work fine?
In example one you are calling the extension method Queryable.Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate) this converts the query to sql and applies the filter server side.
In example two you are calling the extension method Enumerable.Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate), this returns all rows from the database then in memory in the program it applies the filter.
For your third example, I will just quote Servy's comment
Your first and third snippets are functionally identical. There must
be some difference that you haven't shown for one to work and another
to not.

Logical Inverse of a Func<T, bool>

I have some fairly complex Entity Framework queries throughout my codebase and I decided to centralize the logic into the models. Basically, picture a bunch of controllers with large queries and lots of repeated code in their expression trees. So I took out parts of those expression trees and moved them to the models, allowing for less repetition.
For example, let's say I often need to fetch models called Entity which are in a state of Not Deleted. On my Entity model I have:
public static Func<Entity, bool> IsNotDeleted = e =>
e.Versions != null ?
e.Versions.OrderByDescending(v => v.VersionDate).FirstOrDefault() != null ?
e.Versions.OrderByDescending(v => v.VersionDate).First().ActivityType != VersionActivityType.Delete :
false :
false;
(This is one of the smaller examples, mostly just checking for valid data before trying to examine that data.)
And using it would look like:
var entities = EntityRepository.Entities.Where(Entity.IsNotDeleted).Where(...
I'm finding, however, that while sometimes I want records which are not deleted, other times I want records which are deleted. To do that, is there a way to invert the logic from the consuming code? Something conceptually akin to this (which obviously doesn't work):
var entities = EntityRepository.Entities.Where(!Entity.IsDeleted).Where(...
I'd prefer not to have two Func<>s on the object, one for IsDeleted and one for IsNotDeleted which are nearly identical. The Func<> returns a bool, is there a syntax to call the inverse of it when putting it in a .Where() clause?
Consider the following extension methods.
public static class Functional
{
public static Func<T, bool> Not<T>(this Func<T, bool> f)
{
return x => !f(x);
}
public static Expression<Func<T, bool>> Not<T>(
this Expression<Func<T, bool>> f)
{
// 1. Break the lambda f apart into its parameters and body.
// 2. Wrap the body expression with a unary not expression (!).
// 3. Construct a new lambda with the modified body.
return Expression.Lambda<Func<T, bool>>(
Expression.Not(f.Body), f.Parameters);
}
}
Entity.IsDeleted.Not() is the same as Entity.IsNotDeleted().
Note you probably want to be using Expression<Func<T, bool>> - not Func<T, bool> - so that your lambda logic can be used database-side rather than client-side.
You can use it like this:
Expression<Func<int, bool>> isNegative = x => x < 0;
Expression<Func<int, bool>> isNonNegative = isNegative.Not();
You don't need full blown functional lambda decalration. Go the Church-Turing way - reccursion for the IsNotDeleted definition:
public static Func<Entity, bool> IsNotDeleted = e => !IsDeleted(e);
Answer above is even more "Church-Turing-y" :)

Linq: Create logical inverse of expression

I would like to create a method that accepts an Expression<Func<T, bool>> and creates the logical inverse of it (i.e. it would return false where it would have returned true, and vice versa. This is much harder than I thought. This is where I am up to:
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression)
{
return Expression.Lambda<Func<T, bool>>(Expression.Not(expression.Body));
}
This compiles fine but throws the following Exception when called:
Test method Tests.Common.Unit.LinqPredicateBuilderTests.CanInverseAPredicate threw exception:
System.ArgumentException: Incorrect number of parameters supplied for lambda declaration
I have no idea what I'm doing. Could anyone fill in the blanks?
You're calling Expression.Lambda to create an expression with no parameters at all, when you should be forwarding the single parameter of the source expression.
Note that we are trying to create an Expression<Func<T, bool>> and not an Expression<Func<bool>>.
Try this instead:
return Expression.Lambda<Func<T, bool>>(Expression.Not(expression.Body),
expression.Parameters);

Convert Expression<Func<T, T2, bool>> to Expression<Func<T2, bool>> by introducing a constant for T

I have an expression in the format of Expression<Func<T, T2, bool>> that I need to convert into an expression on the format of Expression<Func<T2, bool>> by replacing the T in the first expression with a constant value.
I need this to stay as an expression so I can't just Invoke the expression with a constant as the first parameter.
I've looked at the other questions here about expression trees but I can't really find a solution to my problem. I suspect I have to walk the expression tree to introduce the constant and remove one parameter but I don't even know where to start at the moment. :(
You can use Expression.Invoke to create a new lambda expression that calls the other:
static Expression<Func<T2, bool>> PartialApply<T, T2>(Expression<Func<T, T2, bool>> expr, T c)
{
var param = Expression.Parameter(typeof(T2), null);
return Expression.Lambda<Func<T2, bool>>(
Expression.Invoke(expr, Expression.Constant(c), param),
param);
}

Categories