通用枚举到SelectList扩展方法

我需要在项目中的任何Enum中创建一个SelectList

我有下面的代码,我从特定的枚举创建一个选择列表,但我想为任何枚举创建一个扩展方法。 此示例检索每个Enum值上的DescriptionAttribute

 var list = new SelectList( Enum.GetValues(typeof(eChargeType)) .Cast() .Select(n => new { id = (int)n, label = n.ToString() }), "id", "label", charge.type_id); 

参考这篇文章 ,我该如何处理?

 public static void ToSelectList(this Enum e) { // code here } 

我认为你正在努力的是检索描述。 我相信一旦你有那些你可以定义你的最终方法,给出你的确切结果。

首先,如果您定义了一个扩展方法,它将使用枚举的值,而不是枚举类型本身。 我认为,为了便于使用,您希望在类型上调用方法(如静态方法)。 不幸的是,你无法定义那些。

你能做的是以下几点。 首先定义一个方法来检索枚举值的描述​​,如果它有一个:

 public static string GetDescription(this Enum value) { string description = value.ToString(); FieldInfo fieldInfo = value.GetType().GetField(description); DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0) { description = attributes[0].Description; } return description; } 

接下来,定义一个获取枚举的所有值的方法,并使用前面的方法查找我们想要显示的值,并返回该列表。 可以推断出generics参数。

 public static List> ToEnumDescriptionsList(this TEnum value) { return Enum .GetValues(typeof(TEnum)) .Cast() .Select(x => new KeyValuePair(x, ((Enum)((object)x)).GetDescription())) .ToList(); } 

最后,为了便于使用,一种无需直接调用它的方法。 但是generics参数不是可选的。

 public static List> ToEnumDescriptionsList() { return ToEnumDescriptionsList(default(TEnum)); } 

现在我们可以像这样使用它:

 enum TestEnum { [Description("My first value")] Value1, Value2, [Description("Last one")] Value99 } var items = default(TestEnum).ToEnumDescriptionsList(); // or: TestEnum.Value1.ToEnumDescriptionsList(); // Alternative: EnumExtensions.ToEnumDescriptionsList() foreach (var item in items) { Console.WriteLine("{0} - {1}", item.Key, item.Value); } Console.ReadLine(); 

哪个输出:

 Value1 - My first value Value2 - Value2 Value99 - Last one 

晚会,但由于没有接受的答案,它可能会帮助其他人:

正如@Maarten所提到的,扩展方法对枚举的值起作用,而不是enum类型itelf,因此与Maarteen的灵魂一样,你可以创建一个虚拟或默认值来调用扩展方法,但是,你可能会发现,就像我是的,只使用这样的静态助手方法更简单:

 public static class EnumHelper { public static SelectList GetSelectList(string selectedValue, bool useNumeric = false) { Type enumType = GetBaseType(typeof(T)); if (enumType.IsEnum) { var list = new List(); // Add empty option list.Add(new SelectListItem { Value = string.Empty, Text = string.Empty }); foreach (Enum e in Enum.GetValues(enumType)) { list.Add(new SelectListItem { Value = useNumeric ? Convert.ToInt32(e).ToString() : e.ToString(), Text = e.Description() }); } return new SelectList(list, "Value", "Text", selectedValue); } return null; } private static bool IsTypeNullable(Type type) { return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)); } private static Type GetBaseType(Type type) { return IsTypeNullable(type) ? type.GetGenericArguments()[0] : type; } 

您可以像这样创建选择列表:

  viewModel.ProvinceSelect = EnumHelper.GetSelectList(model.Province); 

或使用可选的数值而不是字符串:

 viewModel.MonthSelect = EnumHelper.GetSelectList(model.Month,true); 

我从这里得到的基本想法,虽然我改变它以满足我的需要。 我添加的一件事是可以选择使用int的值。 我还添加了一个枚举扩展来获取基于此博客文章的description属性:

 public static class EnumExtensions { public static string Description(this Enum en) { Type type = en.GetType(); MemberInfo[] memInfo = type.GetMember(en.ToString()); if (memInfo != null && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs != null && attrs.Length > 0) { return ((DescriptionAttribute)attrs[0]).Description; } } return en.ToString(); } } 

由于枚举不能将扩展固定到整个集合,因此扩展Enum基类的便捷方法是使用静态类型类。 这将允许简洁的代码,例如:

 Enum.GetSelectItems(); 

使用以下代码可以实现:

 public static class Enum { public static SelectListItem[] GetSelectItems() { Type type = typeof(T); return Enum.GetValues(type) .Cast() .Select(v => new SelectListItem() { Value = v.ToString(), Text = Enum.GetName(type, v) }) .ToArray(); } } 

由于枚举没有共享接口,因此可以使用类型滥用,但类名称Enum应该消除任何混淆。

这是一个更正的[类型转换为int]和简化[使用tostring override而不是getname]版本的Nathaniels答案返回List而不是数组:

 public static class Enum { //usage: var lst = Enum.GetSelectList(); public static List GetSelectList() { return Enum.GetValues( typeof(T) ) .Cast() .Select(i => new SelectListItem() { Value = ((int)i).ToString() ,Text = i.ToString() }) .ToList(); } }