Как был бы я идти о присоединении к двум лямбда-выражениям как они:
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);
Ваше "что-то вроде" будет работать, если вы имеете дело с обычными делегатами. Но если вы должны использовать деревья выражений, я не вижу другого решения, кроме рекурсивной замены.
В .NET 4 вы можете использовать System.Linq.Expressions.ExpressionVisitor, чтобы сделать такую рекурсивную замену намного проще. Для .NET 3.5 посмотрите на этот пример: http://msdn.microsoft.com/en-us/library/bb882521.aspx
Используя ExpressionVisitor, вам нужно переопределить методы только для тех типов узлов, которые вы хотите заменить, и окружающее дерево будет автоматически реконструировано.
Если вы имеете дело с условиями для использования в LINQ, гораздо более простым решением для динамического объединения условий является просто многократный вызов Where().
Это не так уж плохо с 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);
Я только что обнаружил, как это сделать с .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);