Как совместить две лямбды

Возможный дубликат:
объединяя два выражения лямбы в C#

У меня есть два следующих выражения:

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

Теперь мне нужно объединить их с OR. Что-то вроде этого:

Expression.Or(expr1, expr2)

Есть ли способ сделать это похожим на приведенный выше код, например:

expr1 || expr2

Я понимаю, что в этом примере я могу просто объединить это в первую очередь:

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

но я не могу сделать это в моем реальном коде, так как я получаю expr1 и expr2 в качестве аргументов метода.

2 ответа

Решение

Чтобы завершить ответ Эрика, используя новый ExpressionVisitor представлен в.NET 4, а не в пользовательском переписывателе:

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

}

Проблема в том, что параметры "s" в каждой лямбде имеют одинаковое имя и один и тот же тип, но это разные параметры. Параметры имеют ссылочную идентичность, а не идентичность значения. Простое объединение двух тел существующих деревьев выражений в третье дерево выражений позволяет получить:

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

что не имеет никакого смысла. Вам нужно написать посетителя, который выполняет поиск и замену параметра s новым параметром, который вы затем будете использовать в качестве параметра нового лямбда-выражения.

Смотрите этот связанный вопрос для более подробной информации:

Объединение двух лямбда-выражений в C#

Другие вопросы по тегам