Присоединение лямбда-выражений - PullRequest
8 голосов
/ 01 марта 2010

Как бы я мог объединить два лямбда-выражения, такие как theese:

Expression<Func<string, bool>> expr1 = a => a.Length > 100;
Expression<Func<string, bool>> expr2 = b => b.Length < 200;

... в такое выражение:

Expression<Func<string, bool>> expr3 = s => s.Length < 100 && s.Length < 200;

То есть, соединяя их с оператором AndAlso. (Или любой другой оператор в этом отношении ...)

Я действительно преуспел с некоторой неприятной рекурсивной заменой лямбда-параметров, а затем соединился с методом Expression.AndAlso. Но я ищу что-то более простое.

Например, что-то вроде: (что, очевидно, не работает.)

Expression<Func<string, bool>> expr3 = c => expr1(a) && expr2(b);

Ответы [ 3 ]

2 голосов
/ 01 марта 2010

Это не так уж плохо с Expression.Invoke ...:

    var strings = (new [] { "a", "bb", "ccc", "dddd", "eeeee", "fffff" });
Expression<Func<string, bool>> expr1 = a => a.Length > 1; 
Expression<Func<string, bool>> expr2 = b => b.Length < 4;

ParameterExpression p = expr1.Parameters[0];

var andAlso = System.Linq.Expressions.Expression.AndAlso(Expression.Invoke(expr1, p), Expression.Invoke(expr2, p)); 
var lambda = LambdaExpression.Lambda<Func<string, bool>>(andAlso, p);
var filteredStrings = strings.AsQueryable().Where(lambda);
2 голосов
/ 01 марта 2010

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

В .NET 4 вы можете использовать System.Linq.Expressions.ExpressionVisitor, чтобы сделать этот вид рекурсивной замены намного проще. Для .NET 3.5 взгляните на этот пример: http://msdn.microsoft.com/en-us/library/bb882521.aspx

Используя ExpressionVisitor, вам нужно только переопределить методы для типов узлов, которые вы хотите заменить, и окружающее дерево будет автоматически восстановлено.

Если вы имеете дело с условиями для использования с LINQ, гораздо более простым решением для динамического объединения условий является простой вызов Where () несколько раз.

1 голос
/ 01 марта 2010

Я только что обнаружил, как сделать это с .NET 4, используя новый метод обновления. Так как это новый метод, я полагаю, что он, должно быть, тоже нуждался в этом. Я действительно доволен этим, потому что решение med .NET 3.5 действительно ужасно. (ПРИМЕЧАНИЕ. Это решение все равно не работает. Проверьте комментарии.)

Expression<Func<string, bool>> expr1 = a => a.Length > 100;
Expression<Func<string, bool>> expr2 = b => b.Length < 200;

// This produces a new expression where the parameter b is replaced with a
expr2 = expr2.Update(expr1.Body, expr1.Parameters);

// So now we can join the bodies and produce a new lambda expression.
Expression<Func<string, bool>> expr3 = Expression.Lambda<Func<string, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...