2010-07-20 15 views
14

Come posso combinare due espressioni lambda in una utilizzando un OR?Espressioni lambda e come combinarle?

Ho provato quanto segue ma loro fusione mi obbliga a passare parametri nelle Expression.Invoke chiede tuttavia voglio che il valore passato nella nuova lambda da passare su ogni bambino-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); 

Qualche idea su come combinare due espressioni lambda in una e avere gli argomenti del figlio lambda è quella del genitore?

+1

Quando dici "combinare", cosa vuoi veramente che succeda? Dite che l'argomento passato è '7' -' func1' restituirà true, e 'func2' restituirà false. Cosa vuoi che la combinazione restituisca? –

risposta

18

Il modo migliore che ho trovato per imparare le espressioni è di dare un'occhiata al codice sorgente di PredicateBuilder.

Quando si desidera combinare più le sue dichiarazioni, è possibile:

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

Il Expression.Invoke crea un InvocationExpression che applica i parametri alla vostra func2.

In effetti, PredicateBuilder può essere tutto ciò che serve.

var predicate = PredicateBuilder.False<int>(); 
predicate = predicate.Or(x => x > 5); 
predicate = predicate.Or(x => x > 10); 

vorrei rivedere "x > 5 o x > 10", sembra come una cosa strana da OR.

Spero che questo aiuti.

+0

Eccellente, questo è proprio quello che stavo cercando. –

+1

'Expression.Lamda' manca una 'b', quindi dovrebbe essere .Expression.Lambda ' – Bern

+2

'Expression.Invoke' non è supportato da Linq alle Entità. Quindi, anche se questo verrà compilato per IL. Non verrà compilato in SQL. – Aron

1

Sembra interessante ... Non so molto sull'espressione lambda, ma ho trovato this article. Sotto PredicateBuilder Source Code è un esempio per o che funziona per 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); 
} 
0

** edit: oops leggere oltre la cosa o, aggiornato esso ***

Ciao,

Non sei sicuro di volerli chiamare separatamente o di combinarli da un punto di vista accademico.

si può semplicemente chiamare in questo modo:

bool OR(int i1, Func<int, bool> f1, Func<int, bool> f2){ 
    return f1(i1) || f2(i1); 
} 

che farà il trucco.

o si può riscrivere che come

bool MyOR = (i1, f1, f2) => f1(i1) || f2(i1); 

E quando sei qurious, creare un'espressione da quello e guarda che. (Facendo tutto a mano, don; t hanno VS qui ora, quindi si prega di essere facile sui miei errori di battitura)

Expression<Func<int, Func<int, bool>, Func<int, bool>, bool>> exprOR = 
(i1, f1, f2) => f1(i1) || f2(i1); 

Se si vuole guardare l'anatomia dell'espressione, si può guardare a questo articolo che ho scritto: http://www.codeproject.com/KB/WPF/WpfExpressionTree.aspx

Basta passare l'espressione all'apadater e vedere come è stata costruita.

Saluti Gert-Jan

1

Perché non basta fare:

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 

?

Salva problemi con le librerie di terze parti.

+0

Il problema è che voglio mantenerli in un albero di espressioni, quindi vengono analizzati dal framework di entità ... –

+1

Abbastanza corretto, il mio suggerimento probabilmente non è così valido allora –

Problemi correlati