Расширение IEnumerable
Я хочу создать расширение IEnumerable<TSource>
, которое может преобразовать себя в IEnumerable<SelectListItem>
. До сих пор я пытался сделать это следующим образом:
public static
IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(this
IEnumerable<TSource> enumerable, Func<TSource, TKey> text,
Func<TSource, TKey> value)
{
List<SelectListItem> selectList = new List<SelectListItem>();
foreach (TSource model in enumerable)
selectList.Add(new SelectListItem() { Text = ?, Value = ?});
return selectList;
}
Это правильный способ сделать это? Если да, то каким образом я рисую значения из соответствующих значений из Func<TSource, TKey>
?
Ответы
Ответ 1
Вам просто нужно использовать две функции, которые вы предоставляете в качестве параметров для извлечения текста и значения. Предполагая, что текст и значение являются строками, вам не нужен параметр типа TKey
. И нет необходимости создавать список в методе расширения. Блок-итератор с использованием yield return
является предпочтительным и как строятся аналогичные методы расширения в LINQ.
public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
this IEnumerable<TSource> enumerable,
Func<TSource, string> text,
Func<TSource, string> value)
{
foreach (TSource model in enumerable)
yield return new SelectListItem { Text = text(model), Value = value(model) };
}
Вы можете использовать его так (вам нужно поставить два лямбда):
var selectedItems = items.ToSelecListItem(x => ..., x => ...);
Однако вы могли бы использовать Enumerable.Select
:
var selectedItems = items.Select(x => new SelectListItem { Text = ..., Value = ... });
Ответ 2
Вы изобретаете колесо. Это то, что предназначено Enumerable.Select.
EDIT BY @KeithS: Чтобы ответить на вопрос, если вы хотите этот вывод, вы можете определить способ расширения, который включает Enumerable.Select:
public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
this IEnumerable<TSource> enumerable,
Func<TSource, string> text,
Func<TSource, string> value)
{
return enumerable.Select(x=>new SelectListItem{Text=text(x), Value=value(x));
}
Ответ 3
Вы на правильном пути.
Funcs - это методы, хранящиеся в переменных, и вызываются как обычные методы.
public static IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(
this IEnumerable<TSource> enumerable,
Func<TSource, TKey> text,
Func<TSource, TKey> value)
{
List<SelectListItem> selectList = new List<SelectListItem>();
foreach (TSource model in enumerable)
{
selectList.Add(new SelectListItem()
{
Text = text(model),
Value = value(model)
});
}
return selectList;
}
Если бы я мог порекомендовать, ваши Funcs должны быть Func<TSource, string>
, так как текст и значение являются строками в SelectListItem.
Изменить Просто подумал об этом...
Кроме того, вам не нужно создавать внутренний список, но вместо этого можно выполнить возврат доходности. Ниже приведена моя "оптимизированная" версия вашего метода.
public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
this IEnumerable<TSource> enumerable,
Func<TSource, string> text,
Func<TSource, string> value)
{
foreach (TSource model in enumerable)
{
yield return new SelectListItem()
{
Text = text(model),
Value = value(model)
};
}
}
Вот ссылка на возвращение yeild. Он позволяет вам возвращать ваши результаты в виде элемента в перечислимом, создавая ваше перечисляемое невидимо (для вас).
http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx
Ответ 4
Мне кажется, что пересечь реку, чтобы получить воду. Почему бы просто не использовать select?
enumerable.Select(item =>
new SelectListItem{
Text = item.SomeProperty,
Value item.SomeOtherProperty
}).ToList();
если вам действительно нужен метод, вы можете сделать это:
public static
IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(this
IEnumerable<TSource> enumerable, Func<TSource, TKey> text,
Func<TSource, TKey> value)
{
return (from item in enumerable
select new SelectListItem{
Text = text(item),
Value = value(item)
}).ToList();
}
Ответ 5
Способ LINQ для достижения того, что вы хотите:
public static IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(
this IEnumerable<TSource> enumerable,
Func<TSource, TKey> textSelector,
Func<TSource, TKey> valueSelector)
{
return from model in enumerable
select new SelectListItem
{
Text = textSelector(model),
Value = valueSelector(model)
};
}
Ответ 6
Внутри вашего метода расширения эти два параметра являются просто делегатами, и вы можете запускать их как любую другую функцию:
selectList.Add(new SelectListItem() { Text = text(model), Value = value(model)});
Ответ 7
Другие решения также работают, но я думаю, что один из Martin Liversage - лучший способ сделать это:
IEnumerable<SelectListItem> selectListItems = items.Select(x =>
new SelectListItem
{
Text = x.TextProperty,
Value = x.ValueProperty
});