2015-09-23 8 views
1

У меня есть следующий фрагмент кода:Как хранить различные GroupBy в одной переменной с минимальным дублированием кода?

var newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds, 
        null, widgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value) 
        .GroupBy(s => new { widgetId = s.widgetId, ProductId = s.ProductId }); 

Если у меня есть условие Показать все, что я хочу, чтобы взять следующий из GroupBy:

WidgetId = s.WidgetId 

Так что теперь было бы:

var newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds, 
        null, widgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value) 
        .GroupBy(s => new {ProductId = s.ProductId }); 

Существует много кода, который зависит от newProducts, и когда я создал оператор if и поместил var newProducts в outerscrope, он останавливается. E все работает.

Я знаю, что это, наверное, глупый вопрос, но как я могу это сделать с минимальным повторяющимся кодом?

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

var newProducts;  
if(model.allWidgets) 
    {newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds, 
          null, WidgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value) 
          .GroupBy(s => new {ProductId = s.ProductId });} 
else 
{ 
newProducts = _summaryRepository.GetFilteredSummaries(manufacturerIds, countryIds, categoryIds, 
         null, WidgetIds, startDate, null).Where(s => s.Product.ProductCountries.FirstOrDefault(pc => pc.CountryId == s.CountryId).CreatedAt >= startDate.Value) 
         .GroupBy(s => new { WidgetId = s.WidgetId, ProductId = s.ProductId }); 
} 
+0

ваш рефакторинга во многом зависит от того, как вы используете 'newProducts'. Как вы видите, «newProducts» может быть совершенно другого типа (разветвленный по-разному). Это означает, что ваш код становится *** динамическим *** (позже). – Hopeless

ответ

4

Вы можете изменить свой GroupBy игнорировать s.WidgetId когда model.allWidgets верно:

query.GroupBy(s => new { WidgetId = model.allWidgets ? 0 : s.WidgetId, ProductId = s.ProductId }); 
+0

Это похоже на то, что я ищу, но по какой-то причине мой model.allWidgets возвращается как неопределенный, если его не проверять, поэтому просто пытаюсь выяснить, почему это так ... – anna

+0

жаль что-то, что я пропустил в представлении отлично работает Спасибо – anna

2

С LINQ Conditional Group, вы можете добавить «нулевой» группировке (WidgetId = 0), в результате чего GroupBy вернуть то же самое анонимный тип группировки в обоих случаях:

var newProducts = _summaryRepository.GetFilteredSummaries(...) 
            .Where(s => ...) 

var groupedProducts = newProducts.GroupBy(s => 
{ 
    if(model.allWidgets) 
    { 
     return new 
     { 
      ProductId = s.ProductId, 
      WidgetId = 0, 
     }; 
    } 
    else 
    { 
     return new 
     { 
      ProductId = s.ProductId, 
      WidgetId = s.WidgetId, 
     }; 
    } 
}); 

И, конечно же, как just-added answer indicates, это может быть значительно уменьшена с помощью условного оператора:

var groupedProducts = newProducts.GroupBy(s => 
    new 
    { 
     ProductId = s.ProductId, 
     WidgetId = model.allWidgets ? 0 : s.WidgetId, 
    }); 

Этот тип еще анонимным и, таким образом, непосредственно не доступны из кода, поэтому для того, чтобы вернуть его из метода, введем класс держать группу:

public class ProductGrouping 
{ 
    public int ProductId { get; set; } 
    public int? WidgetId { get; set; } 
} 

public IGrouping<ProductGrouping, Summary> GetGroupedSummaries() 
{ 
    return _summaryRepository.GetFilteredSummaries(...) 
          .Where(s => ...) 
          .GroupBy(s => new ProductGrouping 
          { 
           ProductId = s.ProductId, 
           WidgetId = model.allWidgets ? (int?)null : s.WidgetId, 
          }); 
} 
+0

Но так как 'group by' возвращает разные типы в каждом случае, как бы вы определили общую 'IGrouping '? – sstan

1

Что вы пытаетесь do не реально, потому что ваши 2 запроса возвращают разные анонимные типы, если вы не хотите возвращать результаты обратно в переменную типа object, которая не кажется очень полезной (или dynamic, но тогда вы теряете преимущества времени компиляции используя LINQ).

Чтобы иметь возможность использовать ключевое слово var, компилятор должен иметь возможность определять тип объявления, что означает, что вы должны предоставить назначение прямо там, где вы объявляете свою переменную.

Как указано в документации Implicitly Typed Local Variables:

var ключевое слово указывает компилятору вывести тип переменной из выражения в правой части оператора инициализации.

А также ...

Важно понимать, что var ключевое слово не означает «вариант» и не указывает, что переменная слабо типизированным, или с поздним связаны. Это просто означает, что компилятор определяет и присваивает наиболее подходящий тип.

+0

ОК, так что, к сожалению, мне нужно будет повторить код, на самом деле нет пути вокруг, это правильно? – anna

+0

Нет, если вы не готовы пожертвовать временем проверки компиляции и ранним связыванием. – sstan