【问题标题】:Succinct LINQ filter expression简洁的 LINQ 过滤器表达式
【发布时间】:2013-08-29 13:48:07
【问题描述】:

我有一个 MVC 控制器,它将根据类别过滤产品列表。

Products = repository.Products.Where(p => category == null || p.Category1 == "category1" );

如果我想让用户过滤具有两个类别的产品,我必须添加另一个包含 Category1 和 Category2 的 if 语句。我可以想象,如果我有更多的类别,用户可以选择类别 1,3,5 等等,排列会变得非常大。

有合适的方法吗?

【问题讨论】:

标签: c# asp.net-mvc linq lambda


【解决方案1】:

1.可以使用Expression来构造条件表达式

2.在linq中使用表达式。

【讨论】:

    【解决方案2】:

    另一种选择是创建一个 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 的工作:-)

    【讨论】:

      【解决方案3】:

      我假设您的对象模型是按照以下方式定义的:

      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"));
      

      【讨论】:

      • 你能稍微详细说明一下第一种情况吗?您的意思是创建一个名为 Categories 的新类并在我的 Product Class 中创建一个成员实例吗?
      猜你喜欢
      • 2020-11-12
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 2012-07-20
      • 1970-01-01
      • 1970-01-01
      • 2013-10-15
      • 1970-01-01
      相关资源
      最近更新 更多