2013-08-26 4 views
1

У меня есть контроллер MVC, который будет фильтровать список продуктов на основе категории.Явное выражение фильтра LINQ

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

Если бы я хотел, чтобы позволить пользователю выбирать продукт с двумя категориями, я бы добавить еще if заявление, которое содержит category1 и category2. Я могу себе представить, есть ли у меня больше категорий, и пользователь может выбрать категорию 1,3,5 и т. Д., Перестановка будет безумно большой.

Есть ли правильный способ сделать это?

+0

вам может понадобиться построить выражение лямбда ... см. Эту ссылку, возможно, это хороший старт http: // stackoverflow.com/questions/16240630/dynamic-add-new-lambda-expressions-to-create-a-filter –

ответ

1

Я предполагаю, что ваша модель объекта определяется по линиям:

public class Product 
{ 
    // ... 
    public Category Category1 { get; set; } 
    public Category Category2 { get; set; } 
    public Category Category3 { get; set; } 
    // ... 
} 

(где вы могли бы использовать строки вместо того, чтобы иметь класс категории)

Если модель объекта находится в пределах вашего тогда я бы рекомендовал изменить его, чтобы продукт имел набор категорий, а не несколько именованных свойств для категорий 1, категории 2, категории 3 и т. д., так вот:

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

Можете ли вы немного подробнее остановиться на первом случае? Вы хотите создать новый класс под названием «Категории» и создать экземпляр участника в моем классе продукта? – jingchyu

+0

Я добавил его выше –

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 (или создавать класс для каждой реализации).

Я знаю, что использование предикатов в том, как я описал, позволит вам поставить предикат цены в поле предиката цвета, но я просто подумал, что я бы бросил этот пример там, чтобы проиллюстрировать концепцию использования объекта работа лямбды :-)

0

1.Если может использовать выражение для выражения состояния конструктора

выражение 2.Use в LINQ.

Смежные вопросы