您可以创建一个扩展方法,将您的string
选择器一起编译成一个表达式:
public static class CompileExpressions
{
public static IQueryable<T> SearchTextFieldsOr<T>(this IQueryable<T> source,
ICollection<string> wordsFromSearch, params Func<T, string>[] stringSelectors)
{
Expression<Func<T, bool>> compiledExpression = t => false;
foreach (var filter in stringSelectors)
{
compiledExpression = compiledExpression.Or(t => wordsFromSearch.Contains(filter(t)));
}
var compiled = compiledExpression.Compile();
return source.Where(t => compiled(t));
}
public static IQueryable<T> SearchTextFieldsAnd<T>(this IQueryable<T> source,
ICollection<string> wordsFromSearch, params Func<T, string>[] stringSelectors)
{
foreach (var filter in stringSelectors)
{
source = source.Where(t => wordsFromSearch.Contains(filter(t)));
}
return source;
}
//Taken from http://www.albahari.com/nutshell/predicatebuilder.aspx
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
}
如何使用它的一个例子:
public class Entity
{
public string Name { get; set; }
public string Type { get; set; }
public string Model { get; set; }
public string Colour { get; set; }
}
class Program
{
static void Main(string[] args)
{
var source = new[]{
new Entity { Colour = "Red", Model = "New", Name="Super", Type="Filter"},
new Entity { Colour = "Green", Model = "New", Name="Super", Type="Filter"},
new Entity { Colour = "Green", Model = "New", Name="Super", Type="Filter"},
new Entity { Colour = "Green", Model = "New", Name="Super", Type="Filter"},
new Entity { Colour = "Green", Model = "New", Name="Super", Type="Filter"},
new Entity { Colour = "Green", Model = "New", Name="Super", Type="Amazing"},
};
var filters = new[] {"Red", "Amazing" };
var filteredOr = source
.AsQueryable()
.SearchTextFieldsOr(filters, t => t.Colour, t => t.Type)
.ToList();
//2 records found because we're filtering on "Colour" OR "Type"
var filteredAnd = source
.AsQueryable()
.SearchTextFieldsAnd(filters, t => t.Colour, t => t.Type)
.ToList();
//1 record found because we're filtering on "Colour" AND "Type"
}
}
因为您的string
选择器参数是 type params Func<T, string>[]
,所以您可以添加任意数量的string
选择器以包含在查询中。