将枚举项映射到匿名类型
本文关键字:类型 映射 枚举 | 更新日期: 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);