Tendrá que crear un árbol de expresiones que represente todas las condiciones que le interesan, combinado con Expression.OrElse
, y luego llamar al Where
una sola vez al final.
Esto puede ser un poco complicado si su fuente actual es de tipo anónimo, pero no debería ser tan malo de lo contrario. Aquí hay una muestra: puede haber una manera más simple de hacer la sustitución de parámetros, pero esto no es tan malo. (Aunque ExpressionVisitor
sólo funciona en .NET 4 ... habría que aplicar algo similar a sí mismo si quiere utilizar esto en .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;
}
}
}
Justo lo que necesitaba: D –
¿Qué está haciendo exactamente el Replacer? – seebiscuit
@Seabiscuit: Básicamente se trata de hacer que todas las expresiones de parámetros en el árbol de expresiones resultante se refieran a la misma expresión de parámetros, en lugar de tener distintas para el nivel superior y cada una de las "subexpresiones". –