我想制作一个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>
?
答案 0 :(得分:26)
你正在重新发明轮子。这是Enumerable.Select的目的。
编辑@KeithS:要回答这个问题,如果你想要这个输出,你可以定义一个包装Enumerable的扩展方法。选择:
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));
}
答案 1 :(得分:15)
你走在正确的道路上。
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;
}
如果我建议,您的Func应该是Func<TSource, string>
,因为文本和值是SelectListItem中的字符串。
编辑想到这个......
此外,您不必创建内部列表,而是可以执行 yield return 。以下是我的方法的“优化”版本。
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 return 的参考资料。它允许您将结果作为可枚举元素返回,以隐形方式构建您的可枚举(对您而言)。
答案 2 :(得分:15)
您只需使用您提供的两个函数作为参数来提取文本和值。假设text和value都是字符串,则不需要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) };
}
你可以像这样使用它(你需要提供两个lambdas):
var selectedItems = items.ToSelecListItem(x => ..., x => ...);
但是,您也可以使用Enumerable.Select
:
var selectedItems = items.Select(x => new SelectListItem { Text = ..., Value = ... });
答案 3 :(得分:4)
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();
}
答案 4 :(得分:4)
实现你想要的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)
};
}
答案 5 :(得分:0)
在扩展方法的主体中,这两个参数只是委托,您可以像任何其他函数一样运行它们:
selectList.Add(new SelectListItem() { Text = text(model), Value = value(model)});
答案 6 :(得分:0)
其他解决方案也有效,但我认为Martin Liversage的解决方案是最好的方法:
IEnumerable<SelectListItem> selectListItems = items.Select(x =>
new SelectListItem
{
Text = x.TextProperty,
Value = x.ValueProperty
});