15

我想制作一个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>

4

7 回答 7

26

你在重新发明轮子。这就是Enumerable.Select的用途。

@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));
}
于 2012-05-29T12:43:11.023 回答
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;
}

如果我可以推荐,您的 Funcs 应该是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的参考。它允许您将结果作为可枚举的元素返回,以不可见的方式(对您)构造您的可枚举。

http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

于 2012-05-29T12:41:03.810 回答
15

您只需要使用作为参数提供的两个函数来提取文本和值。假设 text 和 value 都是字符串,则不需要TKeytype 参数。并且不需要在扩展方法中创建列表。使用迭代器块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) };
}

您可以像这样使用它(您需要提供两个 lambda):

var selectedItems = items.ToSelecListItem(x => ..., x => ...);

但是,您也可以使用Enumerable.Select

var selectedItems = items.Select(x => new SelectListItem { Text = ..., Value = ... });
于 2012-05-29T12:43:39.947 回答
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();  
    }
于 2012-05-29T12:48:34.483 回答
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) 
           };
}
于 2012-05-29T12:57:01.757 回答
0

在扩展方法的主体中,这两个参数只是委托,您可以像运行任何其他函数一样运行它们:

        selectList.Add(new SelectListItem() { Text = text(model), Value = value(model)});
于 2012-05-29T12:41:29.870 回答
0

其他解决方案也可以,但我认为 Martin Liversage 的解决方案是最好的方法:

IEnumerable<SelectListItem> selectListItems = items.Select(x => 
    new SelectListItem 
        { 
            Text = x.TextProperty, 
            Value = x.ValueProperty 
        });
于 2012-05-29T14:17:26.523 回答