I have two expressions of type Expression<Func<T, bool>>
and I want to take to OR, AND or NOT of these and get a new expression of the same type
Expression<Func<T, bool>> expr1;
Expression<Func<T, bool>> expr2;
...
//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2
You can use Expression.AndAlso / OrElse to combine logical expressions, but you have to make sure the ParameterExpressions are the same.
I was having trouble with EF and the PredicateBuilder so I made my own without resorting to Invoke, that I could use like this:
Source code for my PredicateBuilder:
And the utility class to substitute the parameters in a lambda:
If you provider does not support Invoke and you need to combine two expression, you can use an ExpressionVisitor to replace the parameter in the second expression by the parameter in the first expression.
I suggest one more improvement to PredicateBuilder and
ExpressionVisitor
solutions. I called itUnifyParametersByName
and you can find it in MIT library of mine: LinqExprHelper. It allows for combining arbitary lambda expressions. Usually the questions are asked about predicate expression, but this idea extends to projection expressions as well.The following code employs a method
ExprAdres
which creates a complicated parametrized expression, using inline lambda. This complicated expression is coded only once, and then reused, thanks to theLinqExprHelper
mini-library.And this is the subexpression building code:
What I tried to achieve was to perform parametrized queries without need to copy-paste and with ability to use inline lambdas, which are so pretty. Without all these helper-expression stuff, I would be forced to create whole query in one go.
I think this works fine, isn't it ?
Joe Albahari (Author of C# 3.0 in a Nutshell and LINQPad) wrote a utility called PredicateBuilder which can be used to AND and OR functions together.
http://www.albahari.com/nutshell/predicatebuilder.aspx
While it works on functions it is open source so you can check it out and see how it works.
I needed to achieve the same results, but using something more generic (as the type was not known). Thanks to marc's answer I finally figured out what I was trying to achieve: