如何编写通用IEnumerable <selectlistitem>扩展方法</selectlistitem>

时间:2010-03-05 19:20:22

标签: c# generics extension-methods

对于仿制药我是相当新的(好的,真的很新),但我喜欢它们的想法。我将在视图上有一些下拉列表,我想要一种通用的方法来获取对象列表并将其转换为SelectListItems

列表

我现在拥有的:

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

麻烦的是,我需要为每个下拉列表重复该代码,因为对象具有代表Text的{​​{1}}属性的不同字段

以下是我想要完成的事情:

SelectListItem

4 个答案:

答案 0 :(得分: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)
                    });
}

答案 1 :(得分: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());

答案 2 :(得分: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属性,这是必需的...相反,您可以提供一种接收这些属性的不同方法(即:传递代理),但是可能会也可能不会增加您的方案中的维护成本。

答案 3 :(得分:0)

///您需要使用反射来获取

的值
   public static IEnumerable<SelectListItem> GetListItems<T> 
     (this IEnumerable<T> items, int selectedVal)
    {
        return from item in items
               select new SelectListItem
               {
                   Text =item.GetPropValue("Name"),
                    Value = item.GetPropValue("Id"),
                     Selected = 
                item.GetPropValue("Id").Equals(selectedVal.ToString())
               };
    }

    public static string GetPropValue<T> (this T item,string refName)
    {

        return 
           item.GetType().GetProperty(refName).GetValue(item).ToString();
    }