ASP.NET MVC中枚举到DropDownList的转换

ASP.NET MVC应用程序开发中,经常需要将枚举类型转换为下拉列表(DropDownList)的选项。这个过程可以通过多种方式实现,每种方式都有其优缺点。在编写代码时,应始终牢记SOLID和DRY原则。本文将展示两种实现方式,并分析哪一种更好以及为什么更好。

方法1:传统方式

在看来,第一种方法虽然不够优雅,但它确实能够实现想要的功能。考虑以下枚举,希望将其填充到下拉列表中:

public enum eUserRole : int { SuperAdmin = 0, PhoenixAdmin = 1, OfficeAdmin = 2, ReportUser = 3, BillingUser = 4 }

通常,会在动作中通过添加每个枚举值的方式来创建SelectList:

var enumData = from eUserRole e in Enum.GetValues(typeof(eUserRole)) select new { ID = (int)e, Name = e.ToString() }; ViewBag.EnumList = new SelectList(enumData, "ID", "Name");

然后在视图中使用:

@Html.DropDownList("EnumDropDown", ViewBag.EnumList as SelectList)

方法1的问题在于,每当需要将枚举绑定到某个Html Helper时,都需要编写上述Linq查询代码来获取枚举的所有值,这有点繁琐,需要一次又一次地重写相同的东西。接下来将看到如何使其更好且可重用。

方法2:使用扩展方法和泛型

现在,这里有一种更优雅的方式来实现它,使用扩展方法和泛型,它将返回任何类型的枚举值作为SelectList:

public static class ExtensionMethods { public static System.Web.Mvc.SelectList ToSelectList(this TEnum obj) where TEnum : struct, IComparable, IFormattable, IConvertible { return new SelectList(Enum.GetValues(typeof(TEnum)).OfType() .Select(x => new SelectListItem { Text = Enum.GetName(typeof(TEnum), x), Value = (Convert.ToInt32(x)).ToString() }), "Value", "Text"); } }

现在,只需要在动作中调用它:

ViewBag.EnumList = eUserRole.SuperAdmin.ToSelectList();

也可以直接在视图中使用它,只需要包含命名空间,以防它在单独的命名空间中:

@Html.DropDownList("EnumDropDown", eUserRole.SuperAdmin.ToSelectList())

方法2的问题

第二种方法比第一种方法要好得多,但方法2还有一个问题,那就是在扩展中硬编码了属性类型,这是相当可能的,有多个枚举属性,并且它们可以用不同的枚举装饰,调用这个扩展方法在那些上面可能不会很好地工作。

方法3:改进的实现

因此,想出了一个更好的实现,以便消费者可以传递属性类型和需要使用的属性属性。将添加另一个扩展方法,它返回属性值,并且它是泛型的,用户可以指定属性类型本身:

public static string AttributeValue(this TEnum value, Func func) where T : Attribute { FieldInfo field = value.GetType().GetField(value.ToString()); T attribute = Attribute.GetCustomAttribute(field, typeof(T)) as T; return attribute == null ? value.ToString() : func(attribute); }

这个扩展将在返回枚举为SelectList的扩展方法中使用:

public static SelectList ToSelectList(this TEnum obj, Func func, object selectedValue = null) where TEnum : struct, IComparable, IFormattable, IConvertible where TAttribute : Attribute { return new SelectList(Enum.GetValues(typeof(TEnum)).OfType() .Select(x => new SelectListItem { Text = x.AttributeValue(func), Value = (Convert.ToInt32(x)).ToString() }), "Value", "Text", selectedValue); }

现在消费者可以通过传递属性及其要用于显示名称的属性来使用它,视图代码现在看起来像这样:

@Html.DropDownList("EnumDropDownWithSelected", eUserRole.SuperAdmin.ToSelectList(attr => attr.DisplayName, (int)eUserRole.OfficeAdmin))
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485