Come combinare due lambda

.net c# expression-trees

Domanda

Possibile duplicato:
combinando due espressioni di lamba in c #

Ho due espressioni seguenti:

Expression<Func<string, bool>> expr1 = s => s.Length == 5;
Expression<Func<string, bool>> expr2 = s => s == "someString";

Ora ho bisogno di combinarli con OR. Qualcosa come questo:

Expression.Or(expr1, expr2)

C'è un modo per rendere questo simile al modo di codice precedente come:

expr1 || expr2

Capisco in questo esempio che posso semplicemente combinarlo in primo luogo:

Expression<Func<string, bool>> expr = s => s.Length == 5 || s == "someString"

ma non posso farlo nel mio codice reale dato che esprimo expr1 ed expr2 come argomenti del metodo.

Risposta accettata

Per completare la risposta di Eric, utilizzare il nuovo ExpressionVisitor introdotto in .NET 4 anziché un rewriter personalizzato:

internal class ParameterReplacer : ExpressionVisitor {
    private readonly ParameterExpression _parameter;

    protected override Expression VisitParameter(ParameterExpression node) {
        return base.VisitParameter(_parameter);
    }

    internal ParameterReplacer(ParameterExpression parameter) {
        _parameter = parameter;
    }
}

class Program {

    static void Main(string[] args) {
        Expression<Func<string, bool>> expr1 = s => s.Length == 5;
        Expression<Func<string, bool>> expr2 = s => s == "someString";
        var paramExpr = Expression.Parameter(typeof(string));
        var exprBody = Expression.Or(expr1.Body, expr2.Body);
        exprBody = (BinaryExpression) new ParameterReplacer(paramExpr).Visit(exprBody);
        var finalExpr = Expression.Lambda<Func<string, bool>>(exprBody, paramExpr);
    }

}

Risposta popolare

Il problema è che i parametri "s" di ogni lambda hanno lo stesso nome e lo stesso tipo, ma sono parametri diversi. I parametri hanno un'identità di riferimento , non un'identità di valore . La semplice combinazione dei due corpi degli alberi di espressione esistenti in un terzo albero di espressioni rende in effetti efficace:

s => s1.Length == 5 || s2 == "somestring"

che non ha alcun senso. Quello che vuoi fare è scrivere un visitatore che esegue una ricerca e sostituzione del parametro s con un nuovo parametro che verrà quindi utilizzato come parametro per la nuova espressione lambda.

Vedi questa domanda correlata per maggiori dettagli:

Combinando due espressioni lambda in c #



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché