我有一个 MVC 控制器,它将根据类别过滤产品列表。
Products = repository.Products.Where(p => category == null || p.Category1 == "category1" );
如果我想让用户过滤具有两个类别的产品,我将不得不添加另一个if
包含 Category1 和 Category2 的语句。我可以想象,如果我有更多的类别,用户可以选择类别 1,3,5 等等,排列会变得非常大。
有没有正确的方法来做到这一点?
我有一个 MVC 控制器,它将根据类别过滤产品列表。
Products = repository.Products.Where(p => category == null || p.Category1 == "category1" );
如果我想让用户过滤具有两个类别的产品,我将不得不添加另一个if
包含 Category1 和 Category2 的语句。我可以想象,如果我有更多的类别,用户可以选择类别 1,3,5 等等,排列会变得非常大。
有没有正确的方法来做到这一点?
我假设您的对象模型是按照以下方式定义的:
public class Product
{
// ...
public Category Category1 { get; set; }
public Category Category2 { get; set; }
public Category Category3 { get; set; }
// ...
}
(您可能使用字符串而不是类别类)
如果对象模型在您的控制范围内,那么我建议对其进行更改,以便产品具有类别集合,而不是 Category1、Category2、Category3 等的多个命名属性,所以更像这样:
public class Product
{
// ...
public IList<Category> Categories { get; set; }
// ...
}
如果产品类是固定的并且它已经具有多个单独的类别属性,我建议为您的产品类编写一个扩展方法,该方法返回一个非空类别列表。这样您就可以where
更简洁地编写表达式。
例如:
public static class ProductExtension
{
public static IList<Category> GetCategories(this Product product)
{
List<Category> categories = new List<Category>();
if (product.Category1 != null)
{
categories.Add(product.Category1);
}
if (product.Category2 != null)
{
categories.Add(product.Category2);
}
// etc.
return categories;
}
}
...然后可以按照以下方式使用
repository.Products.Where(p => p.GetCategories().Contains("category1"));
另一种选择是创建一个 ProductFilter 对象来为您进行过滤。
为 ProductFilter 类提供每个可以过滤的类别的字段,每个类别都存储谓词,以及一个 PassesFilter(Product p) 方法,该方法确定 p 是否通过已设置谓词的所有类别的谓词,例如
method PassesFilter(Product p):
if Category1Filter is not null:
if p does not pass Category1Filter:
return false
if Category2Filter is not null:
if p does not pass Category2Filter:
return false
return true
(请原谅伪代码,我不做C#,已经很晚了)
所以你可以像这样使用它:
ProductFilter pf = new ProductFilter();
...
/*build up your filters for all categories that apply in this search...*/
pf.ColourFilter = (Product p) => { return p.Colour == "Red"; };
pf.PriceFilter = (Product p) => { return p.Price > 100.00; };
...
Products = repository.Products.Where(p => category == null || pf.PassesFilter(p) );
您还可以轻松地以不同的方式实现 PassesFilter 方法以处理 OR 而不是 AND(或为每个实现创建一个类)。
我知道以我描述的方式使用谓词可以让你在颜色谓词字段中放置一个价格谓词,但我只是想我会把这个例子放在那里来说明使用对象来完成 lambdas 工作的概念:-)
1.您可以使用表达式来构造条件表达式
2.在linq中使用表达式。