Comment combiner deux lambdas

.net c# expression-trees

Question

Dupliquer possible:
combinant deux expressions de lamba en c #

J'ai deux expressions suivantes:

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

Maintenant, je dois les combiner avec OR. Quelque chose comme ça:

Expression.Or(expr1, expr2)

Y a-t-il un moyen de faire ceci similaire au code ci-dessus comme:

expr1 || expr2

Je comprends dans cet exemple que je peux simplement le combiner en premier lieu:

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

mais je ne peux pas le faire dans mon vrai code car j'obtiens expr1 et expr2 comme arguments de la méthode.

Réponse acceptée

Pour compléter la réponse d'Eric, utilisez le nouveau ExpressionVisitor introduit dans .NET 4 plutôt qu'un réécriteur personnalisé:

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

}

Réponse populaire

Le problème est que les paramètres "s" dans chaque lambda ont le même nom et le même type, mais ce sont des paramètres différents. Les paramètres ont une identité de référence , pas une identité de valeur . En combinant simplement les deux corps des arbres d'expression existants dans un troisième arbre d'expression, on obtient efficacement:

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

ce qui n'a aucun sens. Ce que vous voulez faire, c'est écrire un visiteur qui effectue une recherche-remplacement du paramètre s avec un nouveau paramètre que vous utiliserez ensuite comme paramètre de la nouvelle expression lambda.

Voir cette question connexe pour plus de détails:

Combinaison de deux expressions lambda en c #



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow