你可以使用
Expression
类构建一个Lambda表达式来创建一个合适的谓词。
public static Expression<Func<TInput, bool>> CreateFilterExpression<TInput>(
IEnumerable<Filter> filters)
{
ParameterExpression param = Expression.Parameter(typeof(TInput), "");
Expression lambdaBody = null;
if (filters != null)
{
foreach (Filter filter in filters)
{
Expression compareExpression = Expression.Equal(
Expression.Property(param, filter.FieldName),
Expression.Constant(filter.FilterString));
if (lambdaBody == null)
lambdaBody = compareExpression;
else
lambdaBody = Expression.Or(lambdaBody, compareExpression);
}
}
if (lambdaBody == null)
return Expression.Lambda<Func<TInput, bool>>(Expression.Constant(false));
else
return Expression.Lambda<Func<TInput, bool>>(lambdaBody, param);
}
使用这个帮助方法,你可以在任何IQueryable<T>
类上创建扩展方法,因此它适用于每个LINQ后端:
public static IQueryable<T> Where<T>(this IQueryable<T> source,
IEnumerable<Filter> filters)
{
return Queryable.Where(source, CreateFilterExpression<T>(filters));
}
你可以这样调用它:
var query = context.Persons.Where(userFilters)
如果你想要支持IEnumerable<T>
集合,你需要使用这个额外的扩展方法:
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
IEnumerable<Filter> filters)
{
return Enumerable.Where(source, CreateFilterExpression<T>(filters).Compile());
}
请注意,这仅适用于字符串属性。如果您想要过滤字段,则需要将 Expression.Property
更改为 Expression.Field
(或 MakeMemberAccess
),如果您需���支持其他类型的属性而不仅仅是字符串属性,则必须向 CreateFilterExpression
方法中的 Expression.Constant
部分提供更多类型信息。