您可以構建一個lambda表達式創建使用Expression
類適當的謂詞。
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);
}
有了這個helper方法,你可以創建任何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
部分提供更多類型信息方法。
這是使用內存中的LINQ或LinqToSql嗎? – JustLoren 2009-08-24 21:06:54
這是內存中的LINQ。我需要使用其他集合中定義的過濾器來查詢集合中定義的一組對象。沒有任何數據庫交互。 – Tigran 2009-08-25 06:51:06