2009-05-06 55 views
5

我见过一些使用'T'的样本来为不同类的泛型集合重用一个方法,但我从来没有真正理解它或理解样本。如何将这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; 
     } 

SOLUTION

,我使用的溶液:

用法

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"); 
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; 
    } 

编辑:使用泛型关于,它不是什么帮助在这种情况下,因为

  • 要传递需要的对象实施Id和说明
  • 不必返回这些对象,所以在这方面,你不必在意泛型类型安全
+0

Ofcourse! 谢谢。我一直在想着那些带有'T'的样本,我没有意识到我所需要的界面。非常感谢。 – 2009-05-06 08:52:54

+2

我会说在这种情况下使用泛型和函数将是一个更好的事情。然后你不必强制一堆类来实现一个接口。您可能希望在没有ID或说明的类上使用该ToSelectList函数,并且添加它的位置不是很合乎逻辑(或者例如,Description属性实际上应该被称为其他内容)。 – Svish 2009-05-06 09:10:53

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

然后,您可以通过适当的lambda函数(或直接调用)来调度它。

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

} 
相关问题