2010-03-05 50 views
13

我是相当新的(好的,真的是新的)泛型,但我喜欢它们的想法。我会在视图中有几个下拉列表,我想一个通用的方式,采取对象的列表并将其转换成的SelectListItems如何编写泛型IEnumerable <SelectListItem>扩展方法

列表,我现在拥有的一切:

public static IEnumerable<SelectListItem> ToSelectListItems(
    this IEnumerable<SpecificObject> items, long selectedId) 
    { 
     return 
      items.OrderBy(item => item.Name) 
      .Select(item => 
        new SelectListItem 
        { 
         Selected = (item.Id == selectedId), 
         Text = item.Name, 
         Value = item.Id.ToString() 
        }); 
    } 

麻烦的是,我需要重复的代码为每个下拉的对象具有代表的SelectListItem

这里Text性质不同的领域,是想我做到:

public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items, string key, string value, int SelectedId) { 
    // I really have no idea how to proceed from here :(
} 

回答

20

嗯,你可以做这样的事情:

public static IEnumerable<SelectListItem> ToSelectListItems(
    this IEnumerable<T> items, 
    Func<T,string> nameSelector, 
    Func<T,string> valueSelector, 
    Func<T,bool> selected) 
{ 
    return items.OrderBy(item => nameSelector(item)) 
      .Select(item => 
        new SelectListItem 
        { 
         Selected = selected(item), 
         Text = nameSelector(item), 
         Value = valueSelector(item) 
        }); 
} 
+0

取消,必须做ToSelectListItems :) – Dan 2010-03-05 20:05:01

+1

我怎么会这样称呼,特别是使用'selected'代表? – Dan 2010-03-05 20:12:10

+0

非常好的解决方案! – Samuel 2012-07-30 17:33:04

3

为了书面这项工作,你的类型T将需要实现一些接口,它提供了NameId属性:

public interface ISelectable 
{ 
    string Name { get; } 
    int Id { get; } 
} 

有了这个地方,你可以这样做:

public static IEnumerable<SelectListItem> ToSelectListItems<T>(this IEnumerable<T> items, long selectedId) 
    where T : ISelectable 
{ 
    return 
     items.OrderBy(item => item.Name) 
     .Select(item => 
       new SelectListItem 
       { 
        Selected = (item.Id == selectedId), 
        Text = item.Name, 
        Value = item.Id.ToString() 
       }); 
} 

这是在您的扩展方法中使用NameId属性所必需的...您可以改为提供接收这些属性的其他方法(即:传递代理),但可能会或不会不会增加您场景中的维护成本。

+0

朋友,用这种方法,我怎么会用它 ?看起来比其他答案更清洁。谢谢 ! – 2011-12-20 18:57:19

8

您可以传入代表进行比较和属性检索。事情是这样的:

public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items, 
    int selectedId, Func<T,int> getId, Func<T, string> getName, 
    Func<T, string> getText, Func<T, string> getValue) 
{ 
    return 
     items.OrderBy(item => getName(item)) 
     .Select(item => 
       new SelectListItem 
       { 
        Selected = (getId(item) == selectedId), 
        Text = getText(item), 
        Value = getValue(item) 
       }); 
} 

那么你可以使用它像这样:

var selected = specificObjects.ToSelectListItem(10, s => s.Id, s=> s.Name, s => s.Name, s => s.Id.ToString()); 
+0

您还需要一个getName委托(根据Bruno的答案) - OrderBy子句中的item.Name引用当前不会编译。 – itowlson 2010-03-05 19:33:10

+0

嗯,我想把这个和下一个问题都标记为答案:)。两者都是我正在寻找的! – Dan 2010-03-05 19:41:40

+0

@itowlson - 谢谢,我错过了那一个。 – 2010-03-05 19:43:40