Generic Enum to SelectList Method

I need to create a SelectList from any Enum in my project.

I have code below which I create a selection list from a specific enumeration, but I would like to make an extension method for ANY enum. This example retrieves the DescriptionAttribute value for each Enum value.

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

Link to this post , how can I continue?

 public static void ToSelectList(this Enum e) { // code here } 
+5
enums c # asp.net-mvc extension-methods
Aug 09 '13 at
source share
4 answers

I think that you are fighting, it is a search for a description. I am sure that as soon as you have those that you can determine by your final method, which gives your exact result.

First, if you define an extension method, it works on the value of the enumeration, and not on the type of enumeration itself. And I think for convenience you would like to call a type method (e.g. static method). Unfortunately, you cannot define them.

What you can do is the following. First, define a method that retrieves a description of the enumeration value, if it has one:

 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; } 

Then define a method that takes all the values ​​of the enumeration, and use the previous method to find the value that we want to show, and return this list. The general argument can be inferred.

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

And finally, for ease of use, the method for direct invocation without value. But then the general argument is not optional.

 public static List<KeyValuePair<TEnum, string>> ToEnumDescriptionsList<TEnum>() { return ToEnumDescriptionsList<TEnum>(default(TEnum)); } 

Now we can use it as follows:

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

What outputs:

 Value1 - My first value Value2 - Value2 Value99 - Last one 
+4
Aug 09 '13 at 11:29 on
source share

Late to the party, but since there is no accepted answer, and this may help others:

As @Maarten mentioned, the extension method works on the enum value, not the enum type itelf, because with myarteen soultion you can create a dummy value or a default value to call the extension method, however you can find, like me, just easier use static helper method:

 public static class EnumHelper { public static SelectList GetSelectList<T>(string selectedValue, bool useNumeric = false) { Type enumType = GetBaseType(typeof(T)); if (enumType.IsEnum) { var list = new List<SelectListItem>(); // 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; } 

You must create a selection list as follows:

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

or using optional numeric values ​​instead of strings:

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

I got the basic idea for this from here , although I changed it to suit my needs. One thing I added is the ability to optionally use ints for a value. I also added the enum extension to get a description attribute based on this blog post:

 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(); } } 
+1
Jul 27 '15 at 12:10
source share

Since an enumeration cannot have extensions attached to the entire collection, a convenient way to extend the Enum base class with a static typed class. This will allow you to get compressed code, for example:

 Enum<MyCustomEnumType>.GetSelectItems(); 

What can be achieved with the following code:

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

Since the enumeration does not have a common interface, it is possible that the type is abused, but the Enum class name should reject any confusion.

0
Mar 02 '16 at 19:36
source share

Here is the corrected [type casted value to int] value and simplified [uses tostring override instead of getname] version of Nathaniels answer that returns a list instead of an array:

 public static class Enum<T> { //usage: var lst = Enum<myenum>.GetSelectList(); public static List<SelectListItem> GetSelectList() { return Enum.GetValues( typeof(T) ) .Cast<object>() .Select(i => new SelectListItem() { Value = ((int)i).ToString() ,Text = i.ToString() }) .ToList(); } } 
0
Mar 22 '16 at 18:30
source share



All Articles