Как объединить два лямбда
Возможный дубликат:
объединение двух выражений lamba в С#
У меня есть два следующих выражения:
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 в качестве аргументов метода.
Ответы
Ответ 1
Чтобы закончить ответ Эрика, используйте новый 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);
}
}
Ответ 2
Проблема состоит в том, что параметры "s" в каждой лямбда имеют одно и то же имя и один и тот же тип, но это разные параметры. Параметры имеют идентификатор ссылки, а не идентификатор ценности. Простое объединение двух тел существующих деревьев выражений в третье дерево выражений эффективно делает:
s => s1.Length == 5 || s2 == "somestring"
что не имеет никакого смысла. То, что вы хотите сделать, это написать посетителю, который выполняет поиск и замену параметра s новым параметром, который затем будет использоваться в качестве параметра для нового выражения лямбда.
См. этот родственный вопрос для более подробной информации:
Сочетание двух лямбда-выражений в С#