简洁的LINQ过滤器表达式

时间:2013-08-26 23:49:10

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

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

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

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

有没有正确的方法呢?

3 个答案:

答案 0 :(得分:1)

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

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; }
    // ...
}

如果产品类已修复且已有多个单独的类别属性,我建议为您的产品类编写一个扩展方法,该方法返回非null的类别列表。这样你就可以更简洁地写一个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"));

答案 1 :(得分:1)

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

答案 2 :(得分:0)

1.您可以将Expression用于构造函数条件表达式

2.在linq中使用表达式。