我在我的模型中有一个属性叫做Promotion,它的类型是一个标志enum叫做UserPromotion。枚举成员的显示属性设置如下:
[Flags]
public enum UserPromotion
{
None = 0x0,
[Display(Name = "Send Job Offers By Mail")]
SendJobOffersByMail = 0x1,
[Display(Name = "Send Job Offers By Sms")]
SendJobOffersBySms = 0x2,
[Display(Name = "Send Other Stuff By Sms")]
SendPromotionalBySms = 0x4,
[Display(Name = "Send Other Stuff By Mail")]
SendPromotionalByMail = 0x8
}
现在我想要能够在我的视图中创建一个ul来显示我的Promotion属性的选定值。这就是我到目前为止所做的但问题是,我如何在这里获得显示名称?
<ul>
@foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
{
var currentPromotion = (int)Model.JobSeeker.Promotion;
if ((currentPromotion & aPromotion) == aPromotion)
{
<li>Here I don't know how to get the display attribute of "currentPromotion".</li>
}
}
</ul>
对于这个问题,我有两个解决方案。
第一个解决方案是从enum中获取显示名称。
public enum CourseLocationTypes
{
[Display(Name = "On Campus")]
OnCampus,
[Display(Name = "Online")]
Online,
[Display(Name = "Both")]
Both
}
public static string DisplayName(this Enum value)
{
Type enumType = value.GetType();
string enumValue = Enum.GetName(enumType, value);
MemberInfo member = enumType.GetMember(enumValue)[0];
object[] attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
string outString = ((DisplayAttribute)attrs[0]).Name;
if (((DisplayAttribute)attrs[0]).ResourceType != null)
{
outString = ((DisplayAttribute)attrs[0]).GetName();
}
return outString;
}
<h3 class="product-title white">@Model.CourseLocationType.DisplayName()</h3>
第二个解决方案是从枚举名称中获取显示名称,但在开发人员语言中它被称为patch。
public static string SplitOnCapitals(this string text)
{
var r = new Regex(@"
(?<=[A-Z])(?=[A-Z][a-z]) |
(?<=[^A-Z])(?=[A-Z]) |
(?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace);
return r.Replace(text, " ");
}
<div class="widget-box pt-0">
@foreach (var item in Enum.GetNames(typeof(CourseLocationType)))
{
<label class="pr-2 pt-1">
@Html.RadioButtonFor(x => x.CourseLocationType, item, new { type = "radio", @class = "iCheckBox control-label" }) @item.SplitOnCapitals()
</label>
}
@Html.ValidationMessageFor(x => x.CourseLocationType)
</div>
从上面将所有边情况组合在一起:
枚举包含基对象成员名的成员(Equals, ToString)
可选显示属性
这是我的代码:
public enum Enum
{
[Display(Name = "What a weird name!")]
ToString,
Equals
}
public static class EnumHelpers
{
public static string GetDisplayName(this Enum enumValue)
{
var enumType = enumValue.GetType();
return enumType
.GetMember(enumValue.ToString())
.Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == enumType)
.First()
.GetCustomAttribute<DisplayAttribute>()?.Name ?? enumValue.ToString();
}
}
void Main()
{
Assert.Equals("What a weird name!", Enum.ToString.GetDisplayName());
Assert.Equals("Equals", Enum.Equals.GetDisplayName());
}
我想贡献与区域性相关的GetDisplayName enum扩展。希望这对以前像我一样在谷歌上搜索这个答案的人有用:
Aydin Adn和Todd提到的“标准”方式:
public static string GetDisplayName(this Enum enumValue)
{
return enumValue
.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>()
.GetName();
}
“文化相关的”方式:
public static string GetDisplayName(this Enum enumValue, CultureInfo ci)
{
var displayAttr = enumValue
.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
var resMan = displayAttr.ResourceType?.GetProperty(@"ResourceManager", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null, null) as ResourceManager;
return resMan?.GetString(displayAttr.Name, ci) ?? displayAttr.GetName();
}
基于Todd的答案,建立在Aydin的答案之上,这是一个不需要任何类型参数的泛型扩展方法。
/// <summary>
/// Gets human-readable version of enum.
/// </summary>
/// <returns>effective DisplayAttribute.Name of given enum.</returns>
public static string GetDisplayName<T>(this T enumValue) where T : IComparable, IFormattable, IConvertible // C# 7.3+: where T : struct, Enum
{
if (!typeof(T).IsEnum) // Not needed in C# 7.3+ with above updated constraint
throw new ArgumentException("Argument must be of type Enum");
DisplayAttribute displayAttribute = enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>();
string displayName = displayAttribute?.GetName();
return displayName ?? enumValue.ToString();
}
我需要这个为我的项目,因为像下面的代码,其中不是每个成员的enum有一个DisplayAttribute,抛出一个异常与Todd的解决方案:
public class MyClass
{
public enum MyEnum
{
[Display(Name="ONE")]
One,
// No DisplayAttribute
Two
}
public void UseMyEnum()
{
MyEnum foo = MyEnum.One;
MyEnum bar = MyEnum.Two;
Console.WriteLine(foo.GetDisplayName());
Console.WriteLine(bar.GetDisplayName());
}
}
// Output:
//
// ONE
// Two
如果这是一个简单问题的复杂解决方案,请让我知道,但这是我使用的修复。