Вам нужно будет построить дерево выражений, представляющее все условия, которые вас интересуют, в сочетании с Expression.OrElse
, а затем вызовите Where
один раз в конце.
Это может быть несколько сложно, если ваш текущий источник является анонимным, но в противном случае это не должно быть слишком плохо. Вот пример: может быть проще использовать замену параметров, но это не так уж плохо. (Хотя ExpressionVisitor
работает только в .NET 4 ... Вы должны были бы реализовать что-то подобное себе, если вы хотите использовать это в .NET 3.5.)
using System;
using System.Linq;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
IQueryable<string> strings = (new[] { "Jon", "Tom", "Holly",
"Robin", "William" }).AsQueryable();
Expression<Func<string, bool>> firstPredicate = p => p.Contains("ll");
Expression<Func<string, bool>> secondPredicate = p => p.Length == 3;
Expression combined = Expression.OrElse(firstPredicate.Body,
secondPredicate.Body);
ParameterExpression param = Expression.Parameter(typeof(string), "p");
ParameterReplacer replacer = new ParameterReplacer(param);
combined = replacer.Visit(combined);
var lambda = Expression.Lambda<Func<string, bool>>(combined, param);
var query = strings.Where(lambda);
foreach (string x in query)
{
Console.WriteLine(x);
}
}
// Helper class to replace all parameters with the specified one
class ParameterReplacer : ExpressionVisitor
{
private readonly ParameterExpression parameter;
internal ParameterReplacer(ParameterExpression parameter)
{
this.parameter = parameter;
}
protected override Expression VisitParameter
(ParameterExpression node)
{
return parameter;
}
}
}
Только что мне нужно: D –
Что именно делает Replacer? – seebiscuit
@Seabiscuit: в основном, все выражения параметров в результирующем дереве выражений ссылаются на одно и то же выражение параметра, а не на отдельные для верхнего уровня и каждого из «подвыражений». –