2009-05-06 3 views
5

Я видел несколько примеров использования «Т», чтобы сделать метод повторно используемым для общих коллекций разных классов, но я никогда не попадал в него или не понимал образцы.Как реорганизовать эти два похожих метода в один?

Интересно, можно ли поместить 2 метода ниже в один и что может означать, что это будет (с точки зрения производительности).

Кто-нибудь?

 [NonAction] 
     public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, string defaultOption) 
     { 
      var items = departments.Select(d => new SelectListItem() { Text = d.Code + " - " + d.Description, Value = d.Id.ToString() }).ToList(); 
      items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
      return items; 
     } 

     [NonAction] 
     public List<SelectListItem> ToSelectList(IEnumerable<Function> functions, string defaultOption) 
     { 
      var items = functions.Select(f => new SelectListItem() { Text = f.Description, Value = f.Id.ToString() }).ToList(); 
      items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
      return items; 
     } 

РЕШЕНИЕ

Решение, которое я использовал:

использование

var departmentItems = departments.ToSelectList(d => d.Code + " - " + d.Description, d => d.Id.ToString(), " - "); 
var functionItems = customerFunctions.ToSelectList(f => f.Description, f => f.Id.ToString(), " - "); 

с

public static class MCVExtentions 
    { 
     public static List<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption) 
     { 
      var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList(); 
      items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
      return items; 
     } 
    } 

ответ

7

Без implementiong общего интерфейса, как @Grzenio предложенного, вы могли бы использовать общий метод, как это:

public List<SelectListItem> ToSelectList<T>(IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption) 
    { 
     var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList(); 
     items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
     return items; 
    } 

    // use like 

    t.ToSelectList(departments, d => d.Code + " - " + d.Description, d => d.Id.ToString(), "default"); 
    t.ToSelectList(functions, f => f.Description, f => f.Id.ToString(), "default"); 
+0

Спасибо!Это то, что я искал в первую очередь. Я попытаюсь реализовать ваши и посмотреть, нравится ли мне работать с ним. –

+0

Эй, мой ответ идентичен и отправлен за три минуты до этого ответа, но этот ответ получает 3 голоса и мой ноль! OK Я все равно проголосую, хотя бы для того, чтобы иметь общие параметры для функции в правильном порядке ... – Motti

+1

ToSelectList также можно сделать методом расширения. – idursun

8

старой школы способом было бы создать общий интерфейс как для отдела и функции:

interface A 
{ 
int ID{get;} 
string Description{get;} 
} 

Вы реализуете Описание на Департамент вернуть d.Code + " - " + d.Description. и написать функцию, чтобы использовать этот интерфейс вместо конкретных классов:

[NonAction] 
    public List<SelectListItem> ToSelectList(IEnumerable<A> as, string defaultOption) 
    { 
     var items = as.Select(a => new SelectListItem() { Text = a.Description, Value = a.Id.ToString() }).ToList(); 
     items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
     return items; 
    } 

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

  • объекты, проходящие потребности для реализации Id и описание
  • вы не возвращаете эти объекты, так что в этом отношении вы не должны заботиться о безопасности типа воспроизведенных
+0

Ofcourse! Спасибо. Я слишком застрял, думая о тех образцах с «Т», что я не понимал, что интерфейс - это все, что мне нужно. Большое спасибо. –

+2

Я бы сказал, что использование дженериков и функций было бы лучше в этом случае. Тогда вам не нужно принуждать кучу классов к реализации интерфейса. Вы можете использовать эту функцию ToSelectList для класса, у которого нет идентификатора или описания, и где его добавление будет не очень логичным (или, например, свойство Description должно действительно быть вызвано чем-то другим). – Svish

+0

Спасибо, Svish. Хорошая точка зрения. –

4

На самом деле вы можете сделать это с помощью комбинации дженериков и функций, что-то вроде этого (непроверенный может даже не компилироваться).

[NonAction] 
public List<SelectListItem> ToSelectList<T>(IEnumerable<T> en, 
              Function<string, T> text, 
              Function<string, T> value, 
              string defaultOption) 
{ 
    var items = en.Select(x => new SelectListItem() { Text = text(x) , Value = value(x) }).ToList(); 
    items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
    return items; 
} 

Затем вы можете отправить на него соответствующие функции лямбда (или позвонить напрямую).

[NonAction] 
public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, 
             string defaultOption) 
{ 
    return ToSelectList<Department>(departments, d => d.Code + '-' + d.Description, d => d.Id.ToString(), defaultOption); 

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