将枚举项映射到匿名类型

本文关键字:类型 映射 枚举 | 更新日期: 2023-09-27 18:33:54

我有一个扩展将枚举转换为选择列表,如下所示:

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( ...

所以基本上我想要一个枚举扩展方法,它将枚举映射到匿名类型的 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 之后应用的扩展。

将枚举项映射到匿名类型

有什么理由不想直接映射到 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 });

我认为您不需要中间步骤,而是可以将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);