Как я могу объединить два лямбда-выражения в одно использование ИЛИ?
Я попробовал следующее, но слияние их требует, чтобы я передал параметры в Выражение. Вызовите вызовы, однако я хочу, чтобы значение, переданное в новую лямбду, было передано на каждую дочернюю лямбду..
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);
Какие-либо идеи, как объединить два лямбда-выражения в одно и иметь аргументы дочерних лямбд быть идеей родителя?
Лучший способ, который я нашел для изучения выражений, - это взглянуть на исходный код PredicateBuilder .
Если вы хотите объединить несколько операторов, вы можете:
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);
Expression.Invoke
создает InvocationExpression, который применяет параметры к вашей func2
.
Фактически, PredicateBuilder может быть всем, что вам нужно.
var predicate = PredicateBuilder.False<int>();
predicate = predicate.Or(x => x > 5);
predicate = predicate.Or(x => x > 10);
Я бы изменил " x> 5
или x> 10
", это кажется странным для OR.
Надеюсь, что это поможет.
Звучит интересно ... Я не очень разбираюсь в лямбда-выражениях, но нашел эту статью . В разделе Исходный код PredicateBuilder является примером для или , который работает для меня:
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 );
}
Почему бы просто не сделать:
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
?
Это избавляет от необходимости возиться со сторонними библиотеками.
** edit: oops read over the OR thing, updated it ***
Hi,
Не уверен, хотите ли вы просто называть их отдельно или хотите объединить их с академической точки зрения.
Вы можете просто назвать их так:
bool OR(int i1, Func<int, bool> f1, Func<int, bool> f2){
return f1(i1) || f2(i1);
}
Это поможет.
Или вы можете переписать это как
bool MyOR = (i1, f1, f2) => f1(i1) || f2(i1);
И когда вы будете любопытны, создайте выражение из этого и посмотрите на него. (делаю это от руки, сейчас у меня нет VS, поэтому прошу не обижаться на мои опечатки)
Expression<Func<int, Func<int, bool>, Func<int, bool>, bool>> exprOR =
(i1, f1, f2) => f1(i1) || f2(i1);
Если вы хотите посмотреть на анатомию выражения, вы можете посмотреть эту статью, которую я написал: http://www.codeproject.com/KB/WPF/WpfExpressionTree.aspx
Просто передайте выражение в apadater и посмотрите, как оно строится.
Regards Gert-Jan