Как совместить две лямбды
Возможный дубликат:
объединяя два выражения лямбы в 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 новым параметром, который вы затем будете использовать в качестве параметра нового лямбда-выражения.
Смотрите этот связанный вопрос для более подробной информации: