2015-01-07 18 views
6

Come si effettua il refactoring di questo codice in modo da poter centralizzare la proiezione?Centralizzare o consolidare LINQ selezionare

public IEnumerable<ItemDto> GetItemsByType(int itemId, ItemType itemType) 
{ 
    IEnumerable<ItemDto> items = null; 
    try 
    { 
     var tempItems= _Items.Get(i => i.ItemId == itemId 
      && o.Active == true); 
     switch (itemType) 
     { 
      case ItemType.Normal: 
       items = from item in tempItems 
         select new ItemDto 
         { 
          // many fields here 
         }; 
       break; 
      case ItemType.Damaged: 
       items = from item in tempItems 
         join itemDetail in _ItemDetails.Get() on item.ID equals itemDetail.ItemID 
         select new ItemDto 
         { 
          // many fields here 
         }; 
       break; 
      case ItemType.Fixed: 
       items = from item in tempItems 
         join itemDetail in _ItemDetails.Get() on item.ID equals itemDetail.ItemID 
         where item.Status.ToLower() == "fixed" 
         select new ItemDto 
         { 
          // many fields here 
         }; 
       break; 

      // more case statements here... 

      default: 
       break; 
     } 
    } 
    catch { ... } 
} 

Fondamentalmente, ho un sacco di dichiarazioni di casi e una proiezione lunga su ogni dichiarazione di caso. Sono preoccupato che una volta che il DTO deve cambiare, ad esempio aggiungi un nuovo campo, la proiezione degli altri casi potrebbe non essere coerente tra loro (aggiornamento dimenticato o mancato). Come posso centralizzare questo?

+0

Ognuno di questi "// campi qui" contiene lo stesso codice? – Enigmativity

+0

Sì, sono lo stesso codice –

+0

Quindi la mia risposta potrebbe essere utile. – Enigmativity

risposta

2

Potrebbe avvicinarsi in questo modo?

var query = tempItems.AsQueryable(); 

switch(itemType) 
{ 
    case ItemType.Damaged: 
     query.Join(...); 
     break; 

    case ItemType.Fixed: 
     query.Where(...); 
} 

query.Select(e => new ItemDto{//Lots of properties}); 

return query.ToList(); 
+0

Anche le altre risposte sono state utili, ma alla fine questo mi ha portato alla mia soluzione. Grazie! –

3

Si potrebbe fare qualcosa di simile:

var baseQuery = from item in tempItems select item; 
switch (itemType) 
{ 
    case ItemType.Fixed: 
     baseQuery = from item in baseQuery where item.ID equals itemID select item; 
     break; 
} 

return (from item in baseQuery select new ItemDTO (...projection here...)); 
+0

La cosa qui è che alcuni casi selezionati si sono uniti ad altre raccolte di cui ho bisogno per il DTO. Se faccio 'selezionare solo l'articolo', quei campi delle raccolte unite non sarebbero disponibili per me. –

1

Questo tipo di approccio può aiutare?

public IEnumerable<ItemDto> GetItemsByType2(int itemId, ItemType itemType) 
{ 
    var cases = new Dictionary<ItemType, Func<IEnumerable<ItemDto>, IEnumerable<ItemDto>>>() 
    { 
     { ItemType.Normal, xs => xs }, 
     { ItemType.Damaged, xs => 
      from item in xs 
      join itemDetail in _ItemDetails.Get() on item.ID equals itemDetail.ItemID 
      select item }, 
     { ItemType.Fixed, xs => 
      from item in xs 
      join itemDetail in _ItemDetails.Get() on item.ID equals itemDetail.ItemID 
      where item.Status.ToLower() == "fixed" 
      select item }, 
    }; 

    return cases[itemType](_Items.Get(i => i.ItemId == itemId && o.Active == true)) 
     .Select(x => new ItemDto { .... }); 
}