将枚举项映射到匿名类型

时间:2014-12-11 12:24:15

标签: c#

我有一个扩展,可以将Enum转换为SelectList,如下所示:

public static SelectList ToSelectList(this Enum value, Object selected = null) {

  return new SelectList(Enum.GetValues(value.GetType()).Cast<Enum>().Select(x => 
    new { 
      Value = Convert.ToInt32(x), 
      Description = x.Attribute<DescriptionAttribute>().Description }
    ), "Value", "Description", selected);

}

这应用如下:

Countries = new CountryEnum().ToSelectList(currentCountry);

这样可以正常工作但在某些情况下我需要从枚举列表中删除一个项目或使用不同的顺序,我现在无法做到这一点。

所以我希望有更灵活的东西。例如:

new CountryEnum()
  .Map(x => new { 
    Value = Convert.ToInt32(x), 
    Name = x.Attribute<DescriptionAttribute>().Description
  )
  .OrderBy(x => x.Description)
  .Remove(x => x.Id > 30)
  .ToSelectList( ...

所以基本上我想有一个Enum扩展方法,它将enum映射到IEnumerable的匿名类型,供其他方法使用。

这有意义吗?我怎么能这样做?

更新1

我尝试了以下内容:

public static IEnumerable<T> Map<T>(this Enum value, Func<Enum, T> expression) {

  Type type = value.GetType();

  IEnumerable<Enum> items = new List<Enum> { value };

  foreach (Enum item in items)
    yield return expression(item);

} // Map

然后使用以下内容:

var items = new CountryEnum().Map(x => new { Id = Convert.ToInt32(x) });

但这会返回0 ......

更新2

我想我解决了地图部分如下:

public static IEnumerable<T> Map<T>(this Enum value, Func<Enum, T> expression) {

  Type type = value.GetType();

  var items = Enum.GetValues(type).Cast<Enum>();

  foreach (Enum item in items)
    yield return expression(item);

}

现在我可以按如下方式使用它:

new CountryType()
.Map(x => new { 
  Id = Convert.ToInt32(x), 
  Description = x.Attribute<DescriptionAttribute>().Description })
.OrderBy(x => x.Description);

现在我缺少的是一种将其转换为SelectList的扩展方法。

我目前的扩展名是:

public static SelectList ToSelectList(this Enum value, Object selected = null) {

  return new SelectList(Enum.GetValues(value.GetType()).Cast<Enum>().Select(x => new { Value = Convert.ToInt32(x), Description = x.Attribute<DescriptionAttribute>().Description }), "Value", "Description", selected);

} // ToSelectList

所以我想创建一个在Map one之后应用的扩展。

2 个答案:

答案 0 :(得分:0)

您是否有理由不想直接映射到SelectList?

更像这样:

public static SelectList MapToSelectList(this Enum value, 
                                         Func<Enum, SelectListItem> expression)
{
    Type type = value.GetType();

    var items = Enum.GetValues(type).Cast<Enum>();

    return new SelectList(
        items.Select(i => expression(i)).ToList());
}

允许你传入一个func,它可以控制枚举如何映射到SelectListItem,如下所示:

SelectList mySelectList = new CountryType()
    .MapToSelectList(x => new SelectListItem { 
         Value = Convert.ToInt32(x), 
         Text = x.Attribute<DescriptionAttribute>().Description });

答案 1 :(得分:0)

我认为您不需要中间步骤,而是可以将您需要的Func传递给现有的ToSelectList方法。您可以使用Func<Enum, bool>过滤枚举,并使用Func<Enum, T>订购。这样的事情应该能实现你的目标:

public static SelectList ToSelectList<T>(this Enum value, 
                                         Func<Enum, bool> filter, 
                                         Func<Enum, T> order,
                                         bool orderAsc = true,
                                         Object selected = null)
{
    //get all values from the enum
    IEnumerable<Enum> temp = Enum.GetValues(value.GetType()).Cast<Enum>();

    //filter if required
    if (filter != null)
    {
        temp = temp.Where(filter);
    }

    //order if required
    if (order != null)
    {
        temp = orderAsc ? temp.OrderBy(order) : temp.OrderByDescending(order);
    }

    //map to a SelectList
    return new SelectList(temp.Select(x =>
        new
        {
            Value = Convert.ToInt32(x),
            Description = x.Attribute<DescriptionAttribute>().Description
        }), "Value", "Description", selected);
}

然后可以像这样调用上述内容,例如,仅包含该国家/地区的值大于30的任何国家/地区,其中结果按说明顺序排列并且currentCountry被选中值:

var Countries = new CountryEnum().ToSelectList(x => Convert.ToInt32(x) > 30,
                                               x => x.Attribute<DescriptionAttribute>().Description,
                                               true,
                                               currentCountry);

如果您通常需要通过描述按升序排序的输出,您可以创建一个小的包装方法,如下所示:

public static SelectList ToSelectList(this Enum value, Func<Enum, bool> filter, Object selected = null)
{
    return value.ToSelectList(filter, x => x.Attribute<DescriptionAttribute>().Description, true, selected);
}

这将简化上述调用:

var Countries2 = new CountryEnum().ToSelectList(x => Convert.ToInt32(x) > 30, 
                                                currentCountry);