Как написать общий метод расширения IEnumerable <SelectListItem>
Я довольно новый (нормально, REALLY новый) для дженериков, но мне нравится их идея. Я собираюсь иметь несколько выпадающих списков в представлении, и мне бы хотелось, чтобы общий список объектов и преобразование в список 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
для SelectListItem
Вот что я хотел бы сделать:
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 :(
}
Ответы
Ответ 1
Хорошо, вы могли бы сделать что-то вроде этого:
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)
});
}
Ответ 2
Вы можете передать делегатам возможность выполнять сравнения и поиск свойств. Что-то вроде этого:
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());
Ответ 3
Для того, чтобы это работало как написано, вашему типу T
потребуется реализовать некоторый интерфейс, который предоставляет свойства Name
и Id
:
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()
});
}
Это необходимо для использования свойств Name
и Id
в вашем методе расширения... Вместо этого вы можете предоставить различные способы их получения (то есть: передача делегатов), но это может или может не увеличивайте стоимость обслуживания в вашем сценарии.