我正在尝试在Web应用程序中创建一个过滤系统。问题是我不知道从客户端向API请求多少个过滤器。我已经构建好了,所以过滤器的数组来自像这样的单个字符串:?sizeFilters=big,small,medium
然后我用一个string[] names = sizeFilters.Split(',');
来获得像Where(x => x.listOfSizes.contains(names[index]));
我还需要使用AND和OR来制作表达式的链,因为我将使用另一个过滤器,例如: '?typeFilters=normal,extra,spicy'
因此,我需要使整个表达式看起来像这样,但可能要长几倍,并且需要使用不同大小的数组:
退换货品 Where size is big OR small OR medium AND Where type is normal OR extra OR spicy
Where(x => x.Sizes == "Small" || x => x.Sizes == "Medium" || x => x.Sizes == "Big" &&
x => x.Types == "normal" || x => x.Types == "extra" || x => x.Types == "Spicy")
正如其他人所指出的那样,最简单的选择是在表达式中OR
使用构建您的Enumerable.Contains
;并AND
通过Where
多次调用来构建。
// using these values as an example
string[] sizeTerms = /* initialize */;
string[] typeTerms = /* initialize */;
IQueryable<Item> items = /* initialize */
if (sizeTerms.Any()) {
items = items.Where(x => sizeTerms.Contains(x.Size));
}
if (typeTerms.Any()) {
items = items.Where(x => typeTerms.Contains(x.Type));
}
如果需要,可以将此逻辑包装到扩展方法中,该方法接受要过滤的表达式,并IEnumerable<string>
为过滤器值添加;并构造并应用该Contains
方法:
// using System.Reflection
// using static System.Linq.Expressions.Expression
private static MethodInfo containsMethod = typeof(List<>).GetMethod("Contains");
public static IQueryable<TElement> WhereValues<TElement, TFilterTarget>(
this IQueryable<TElement> qry,
Expression<Func<TElement, TFilterTarget>> targetExpr,
IEnumerable<string> values
) {
var lst = values.ToList();
if (!lst.Any()) { return qry; }
return qry.Where(
Lambda<Expression<Func<TElement, bool>>>(
Call(
Constant(lst),
containsMethod.MakeGenericMethod(typeof(T)),
targetExpr.Body
),
targetExpr.Parameters.ToArray()
)
);
}
可以这样称呼:
qry = qry
.WhereValues(x => x.Size, sizeTerms)
.WhereValues(x => x.Type, typeTerms);
一个警告:查询将基于传递给方法的值进行构建;如果以后进行更改,查询将不会反映这些更改。如果这是一个问题:
Enumerable.Contains
,而不是List.Contains
和Expression.Call
会生成静态方法调用,而不是实例方法调用。本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句