Присоединение к лямбда-выражениям

Как был бы я идти о присоединении к двум лямбда-выражениям как они:

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. (Или любой другой оператор в этом отношении...)

Я на самом деле успешно выполнился с некоторой противной рекурсивной заменой параметров лямбды и затем присоединяющийся к Выражению. Метод AndAlso. Но я ищу что-то более простое.

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

Expression<Func<string, bool>> expr3 = c => expr1(a) && expr2(b);
8
задан plinth 1 March 2010 в 18:52
поделиться

3 ответа

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

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

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

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

2
ответ дан 5 December 2019 в 23:14
поделиться

Это не так уж плохо с 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
ответ дан 5 December 2019 в 23:14
поделиться

Я только что обнаружил, как это сделать с .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);
1
ответ дан 5 December 2019 в 23:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: