How can I combine two lambda expressions into one using an OR ?
I have tried the following but merging them requires me to pass parameters into the Expression.Invoke calls, however I want the value passed into the new lambda to be passed onto each child-lambda..
Expression<Func<int, bool>> func1 = (x) => x > 5;
Expression<Func<int, bool>> func2 = (x) => x < 0;
//Combines the lambdas but result in runtime error saying I need to pass in arguments
//However I want the argument passed into each child lambda to be whatever is passed into the new main lambda
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(Expression.Or(Expression.Invoke(func1), Expression.Invoke(func2)));
//The 9 should be passed into the new lambda and into both child lambdas
bool tst = lambda.Compile().Invoke(9);
开发者_运维问答
Any ideas how to combine two lambda expressions into one and have the arguments of the child lambdas be that of the parent ?
The best way I found to learn expressions, is to take a look at the source code of PredicateBuilder.
When you want to combine multiple your statements, you can:
Expression<Func<int, bool>> func1 = (x) => x > 5;
Expression<Func<int, bool>> func2 = (x) => x > 10;
var invocation = Expression.Invoke(func2, func1.Parameters.Cast<Expression>());
var expression = Expression.Lambda<Func<int, bool>>(Expression.OrElse(func1.Body, invocation), func1.Parameters);
The Expression.Invoke
creates an InvocationExpression that applies the parameters to your func2
.
In fact, PredicateBuilder may be everything you need.
var predicate = PredicateBuilder.False<int>();
predicate = predicate.Or(x => x > 5);
predicate = predicate.Or(x => x > 10);
I would revise "x > 5
or x > 10
", seems like an odd thing to OR.
Hope that helps.
Sound interesting ... I don't know much about lambda expression, but I found this article. Under PredicateBuilder Source Code is an example for or that works for me:
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2 )
{
var invExpr = Expression.Invoke( expr2, expr1.Parameters.Cast<Expression>() );
return Expression.Lambda<Func<T, bool>>
( Expression.OrElse( expr1.Body, invExpr ), expr1.Parameters );
}
Why not just do:
Func<int, bool> func1 = (x) => x > 5;
Func<int, bool> func2 = (x) => x > 10;
List<Func<int, bool>> funcs = new List<Func<int, bool>> { func1, func2 };
var value = 7;
Console.WriteLine(funcs.Any(x => x(value))); // OR
Console.WriteLine(funcs.All(x => x(value))); // AND
?
Saves messing about with 3rd party libraries.
** edit: oops read over the OR thing, updated it ***
Hi,
Not sure if you just want to call them seperatley or you want to combine them from an academic point of view.
You can just call them like this:
bool OR(int i1, Func<int, bool> f1, Func<int, bool> f2){
return f1(i1) || f2(i1);
}
That will do the trick.
or you can rewrite that as
bool MyOR = (i1, f1, f2) => f1(i1) || f2(i1);
And when you're qurious, create an expression from that and look at that. (doing this by hand, don;t have VS here now, so please be easy on my typos)
Expression<Func<int, Func<int, bool>, Func<int, bool>, bool>> exprOR =
(i1, f1, f2) => f1(i1) || f2(i1);
If you want to look at the anatomy of the expression, you can look at this article i wrote: http://www.codeproject.com/KB/WPF/WpfExpressionTree.aspx
Just pass the expression to the apadater and see how it;s built up.
Regards Gert-Jan
精彩评论