【问题标题】:How to get the Display Name Attribute of an Enum member via MVC Razor code?如何通过 MVC Razor 代码获取枚举成员的显示名称属性?
【发布时间】:2012-10-17 11:32:41
【问题描述】:

我的模型中有一个名为Promotion 的属性,它的类型是一个名为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>

【问题讨论】:

  • MVC5 确实支持枚举的 DisplayName 属性。
  • 更清楚一点:只有System.ComponentModel.DataAnnotations.DisplayAttribute。不是System.ComponentModel.DisplayNameAttribute
  • 这是否包括使用反射并因此影响性能?因为这将被称为很多时间。
  • @Nico 诀窍是将结果缓存在static readonly 字段中。这些值只需要从反射中读取一次。

标签: c# asp.net-mvc razor displayattribute


【解决方案1】:

单行 - 流畅的语法

public static class Extensions
{
    /// <summary>
    ///     A generic extension method that aids in reflecting 
    ///     and retrieving any attribute that is applied to an `Enum`.
    /// </summary>
    public static TAttribute GetAttribute<TAttribute>(this Enum enumValue) 
            where TAttribute : Attribute
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<TAttribute>();
    }
}

示例

public enum Season 
{
   [Display(Name = "It's autumn")]
   Autumn,

   [Display(Name = "It's winter")]
   Winter,

   [Display(Name = "It's spring")]
   Spring,

   [Display(Name = "It's summer")]
   Summer
}

public class Foo 
{
    public Season Season = Season.Summer;

    public void DisplayName()
    {
        var seasonDisplayName = Season.GetAttribute<DisplayAttribute>();
        Console.WriteLine("Which season is it?");
        Console.WriteLine (seasonDisplayName.Name);
    } 
}

输出

现在是哪个季节?
夏天来了

【讨论】:

  • 不存在 GetCustomAttribute 的定义
  • @Tito 确保您的项目以 .NET Framework 4.5 为目标,并且您包含以下命名空间 System.Net System.ComponentModel.DataAnnotations
  • 使用 System.Reflection;使用 System.ComponentModel.DataAnnotations;我需要。
  • @curiousBoy GetAttribute&lt;TAttribute&gt; 是一个糟糕的命名约定吗?它检索您指定的属性并像所有公共方法一样使用帕斯卡大小写。
  • @Aydin 我很确定他是在拿“现在是夏天”这样的名字开玩笑。哈。哈。 :-)
【解决方案2】:

更新

第一个解决方案的重点是从枚举中获取显示名称。下面的代码应该是您问题的确切解决方案。

您可以将此帮助类用于枚举:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumHelper<T>
    where T : struct, Enum // This constraint requires C# 7.3 or later.
{
    public static IList<T> GetValues(Enum value)
    {
        var enumValues = new List<T>();

        foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
        {
            enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
        }
        return enumValues;
    }

    public static T Parse(string value)
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }

    public static IList<string> GetNames(Enum value)
    {
        return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
    }

    public static IList<string> GetDisplayValues(Enum value)
    {
        return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
    }

    private static string lookupResource(Type resourceManagerProvider, string resourceKey)
    {
        var resourceKeyProperty = resourceManagerProvider.GetProperty(resourceKey,
            BindingFlags.Static | BindingFlags.Public, null, typeof(string),
            new Type[0], null);
        if (resourceKeyProperty != null)
        {
            return (string)resourceKeyProperty.GetMethod.Invoke(null, null);
        }

        return resourceKey; // Fallback with the key name
    }

    public static string GetDisplayValue(T value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());

        var descriptionAttributes = fieldInfo.GetCustomAttributes(
            typeof(DisplayAttribute), false) as DisplayAttribute[];

        if (descriptionAttributes[0].ResourceType != null)
            return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);

        if (descriptionAttributes == null) return string.Empty;
        return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
    }
}

然后你可以在你的视图中使用它,如下所示:

<ul>
    @foreach (var value in @EnumHelper<UserPromotion>.GetValues(UserPromotion.None))
    {
         if (value == Model.JobSeeker.Promotion)
        {
            var description = EnumHelper<UserPromotion>.GetDisplayValue(value);
            <li>@Html.DisplayFor(e => description )</li>
        }
    }
</ul>

希望对您有所帮助! :)

【讨论】:

  • 所有答案都使用.ToString,但从stackoverflow.com/q/483794/179311,它说要使用Enum.GetName
  • value.GetType().GetField(value.ToString()) 正是我想要的!
  • 添加一些空值检查后,这个答案很好,但如果您不使用 dotfuscation,stackoverflow.com/a/4412730/852806 的答案似乎更简单。
  • 我建议未成年人更改:public static IList GetValues(Enum value) 可以是 public static IList GetValues(T value)。 EnumHelper to => public static class EnumHelper where T : struct, IConvertible。也许是静态构造函数? static EnumHelper() { if (!typeof(T).IsEnum) { throw new ArgumentException("T 必须是枚举类型"); } }
【解决方案3】:

基于Aydin's great answer,这是一个不需要任何类型参数的扩展方法。

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum enumValue)
    {
        return enumValue.GetType()
                        .GetMember(enumValue.ToString())
                        .First()
                        .GetCustomAttribute<DisplayAttribute>()
                        .GetName();
    }
}

注意:GetName() 应该用来代替 Name 属性。这可确保在使用 ResourceType 属性时返回本地化字符串。

示例

要使用它,只需在视图中引用枚举值即可。

@{
    UserPromotion promo = UserPromotion.SendJobOffersByMail;
}

Promotion: @promo.GetDisplayName()

输出

促销:通过邮件发送工作机会

【讨论】:

  • 一定要添加以下命名空间: using System;使用 System.ComponentModel.DataAnnotations;使用 System.Linq;使用 System.Reflection;
  • 巧妙的解决方案,但我得到{“模板只能用于字段访问、属性访问、单维数组索引或单参数自定义索引器表达式。”}
  • 查看此错误消息的其他 SO 答案(我对此不熟悉),看来您可能是在 Html 辅助方法中使用它(如 @Html.DisplayFor(m =&gt; m.myEnum.GetDisplayName()),这将不起作用, 因为他们希望计算的表达式产生一个属性或类似的东西。你应该像上面的例子一样使用裸枚举值。
  • 我在GetCustomAttribute&lt;DisplayAttribute&gt;() 的结果中添加了一个空引用检查,因为对于某些枚举,这可能不存在。如果 DisplayAttribute 不存在,它将回退到 enumValue.ToString()
  • 我用它创建了一个 List&lt;SelectListItem&gt;,它由一个带有所有单独 DisplayAttribute.Name 注释的 Enum 填充 - 这非常有效,谢谢! public List&lt;SelectListItem&gt; MySelectListItem = new List&lt;SelectListItem&gt;(); foreach (MyEnum MyEnum in Enum.GetValues(typeof(MyEnum)).Cast&lt;MyEnum&gt;().Where(x =&gt; x != MyEnum.Default)) { MySelectListItem.Add(new SelectListItem() { Text = MyEnum.GetDisplayName(), Value = ((int)MyEnum).ToString() }); }
【解决方案4】:

基于Aydin's answer,我建议使用较少“重复”的实现(因为我们可以轻松地从Enum 值本身获取Type,而不是将其作为参数提供?:

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public static string GetDisplayName(this Enum enumValue)
{
    return enumValue.GetType().GetMember(enumValue.ToString())
                   .First()
                   .GetCustomAttribute<DisplayAttribute>()
                   .Name;
}

编辑(基于@Vahagn Nahapetyan 的评论)

public static string GetDisplayName(this Enum enumValue)
{
    return enumValue.GetType()?
                    .GetMember(enumValue.ToString())?
                    .First()?
                    .GetCustomAttribute<DisplayAttribute>()?
                    .Name;
}

现在我们可以通过这种方式非常干净地使用它:

public enum Season 
{
    [Display(Name = "The Autumn")]
    Autumn,

    [Display(Name = "The Weather")]
    Winter,

    [Display(Name = "The Tease")]
    Spring,

    [Display(Name = "The Dream")]
    Summer
}

Season.Summer.GetDisplayName();

结果

“梦想”

【讨论】:

  • 您应该小心使用 .First()。例如,如果您的枚举名称是“Equals”,这将引发异常
  • 我理解 First() 的“危险”。在这种特殊情况下,这似乎不是问题。因为它是一种扩展方法,其中this 必须是有效(非空)枚举值。否则调用该方法将已经抛出(这是调用代码的责任)。这使得GetType() 肯定会提供正确的枚举类型,enumvalue 肯定会成为其中的成员。但是 GetCustomAttribute 可能会返回一个 null 值,所以我提供了一个非异常版本的方法,当方法调用链在某处有一个 null 返回值时返回 null。谢谢!
  • 对于您的代码的第二个变体,似乎不需要在 GetMember 之后使用空条件运算符,因为此方法始终返回 MemberInfo 数组并且从不返回 null。对我来说,似乎最好使用 FirstOrDefault 而不是 First。那么在 FirstOrDefault 之后的空条件运算符的使用就会被认为是一致的。
  • 您应该考虑检查 ResourceType 是否不为空,以便加载资源字符串。在多语言应用程序中,显示名称是从资源加载的。
【解决方案5】:

如果您使用的是 MVC 5.1 或更高版本,则有更简单、更清晰的方法:只需使用数据注释(来自 System.ComponentModel.DataAnnotations 命名空间),如下所示:

public enum Color
{
    [Display(Name = "Dark red")]
    DarkRed,
    [Display(Name = "Very dark red")]
    VeryDarkRed,
    [Display(Name = "Red or just black?")]
    ReallyDarkRed
}

在视图中,只需将其放入适当的 html 助手中:

@Html.EnumDropDownListFor(model => model.Color)

【讨论】:

  • @SegmentationFault 为什么?你能描述你的问题吗?您使用哪个版本的 .NET/MVC?你有什么错误?请更具体。
  • 因为它只适用于下拉菜单,而不适用于其他任何地方。
  • .net core 中似乎不存在
  • .net 核心使用 Html.GetEnumSelectList(typeof(YourEnum)) @Lonefish
  • 如果我们想使用 @Html.DisplayFor(yourEnumField) 我们可以在 DisplayTemplates 目录(在共享目录中)放置一个 Enum.cshtml。在这个文件中,我们只需要放 2 行。第一个是:“@model Enum”,第二个是:“@GetDisplayName(Model)”。 GetDisplayName 方法需要与@Bernoulli IT answare 中的一样
【解决方案6】:

基于Aydin's great answerTodd's great answer,这是一个不需要任何类型参数的通用 扩展方法。

/// <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
{
    if (!typeof(T).IsEnum)
        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();
}

我的项目需要这个,因为类似于下面的代码,不是枚举的每个成员都有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

如果这是一个简单问题的复杂解决方案,请告诉我,但这是我使用的解决方案。

【讨论】:

    【解决方案7】:

    你可以使用Type.GetMember Method,然后使用反射get the attribute info

    // display attribute of "currentPromotion"
    
    var type = typeof(UserPromotion);
    var memberInfo = type.GetMember(currentPromotion.ToString());
    var attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false);
    var description = ((DisplayAttribute)attributes[0]).Name;
    

    这里有一些类似的帖子:

    Getting attributes of Enum's value

    How to make MVC3 DisplayFor show the value of an Enum's Display-Attribute?

    【讨论】:

      【解决方案8】:

      对于 ASP.Net Core 3.0,这对我有用(感谢之前的回答者)。

      我的枚举类:

      using System;
      using System.Linq;
      using System.ComponentModel.DataAnnotations;
      using System.Reflection;
      
      public class Enums
      {
          public enum Duration
          { 
              [Display(Name = "1 Hour")]
              OneHour,
              [Display(Name = "1 Day")]
              OneDay
          }
      
          // Helper method to display the name of the enum values.
          public static string GetDisplayName(Enum value)
          {
              return value.GetType()?
             .GetMember(value.ToString())?.First()?
             .GetCustomAttribute<DisplayAttribute>()?
             .Name;
          }
      }
      

      我的视图模型类:

      public class MyViewModel
      {
          public Duration Duration { get; set; }
      }
      

      显示标签和下拉列表的剃刀视图示例。注意下拉列表不需要辅助方法:

      @model IEnumerable<MyViewModel> 
      
      @foreach (var item in Model)
      {
          <label asp-for="@item.Duration">@Enums.GetDisplayName(item.Duration)</label>
          <div class="form-group">
              <label asp-for="@item.Duration" class="control-label">Select Duration</label>
              <select asp-for="@item.Duration" class="form-control"
                  asp-items="Html.GetEnumSelectList<Enums.Duration>()">
              </select>
          </div>
      }
      

      【讨论】:

      • 我会检查 GetDisplayName 方法返回 string.IsNullOrEmpty(retVal) 吗? enumValue.ToString() : retVal;
      【解决方案9】:

      使用核心 2.1,

      public static string GetDisplayName(Enum enumValue)
      {
        return enumValue.GetType()?
       .GetMember(enumValue.ToString())?[0]?
       .GetCustomAttribute<DisplayAttribute>()?
       .Name;
      }
      

      【讨论】:

        【解决方案10】:
        <ul>
            @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion)))
            {
                var currentPromotion = (int)Model.JobSeeker.Promotion;
                if ((currentPromotion & aPromotion) == aPromotion)
                {
                <li>@Html.DisplayFor(e => currentPromotion)</li>
                }
            }
        </ul>
        

        【讨论】:

        • 不起作用:/我收到错误InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
        【解决方案11】:

        在 .NET5 中,我使用 DisplayTextFor 而不需要帮助器或扩展方法:

        @Html.DisplayTextFor(m => m.SomeEnumProperty)
        

        SomeEnumProperty 的值为:

        public enum MyEnum
        {
            [Display(Name = "Not started")]
            NotStarted = 0,
            [Display(Name = "Weird display name instead of just 'Started'")]
            Started = 1,
        }
        

        【讨论】:

          【解决方案12】:

          从上面将所有边缘情况组合在一起:

          • 具有基础对象成员名称的枚举成员(EqualsToString
          • 可选Display属性

          这是我的代码:

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

          【讨论】:

          • 处理可选显示属性的好解决方案。谢谢!
          【解决方案13】:

          您需要使用一些反射来访问该属性:

          var type = typeof(UserPromotion);
          var member = type.GetMember(Model.JobSeeker.Promotion.ToString());
          var attributes = member[0].GetCustomAttributes(typeof(DisplayAttribute), false);
          var name = ((DisplayAttribute)attributes[0]).Name;
          

          我建议将此方法包装在扩展方法中或在视图模型中执行。

          【讨论】:

            【解决方案14】:

            很抱歉这样做,但我无法按原样使用任何其他答案,也没有时间在 cmets 中一决高下。

            使用 C# 6 语法。

            static class EnumExtensions
            {
                /// returns the localized Name, if a [Display(Name="Localised Name")] attribute is applied to the enum member
                /// returns null if there isnt an attribute
                public static string DisplayNameOrEnumName(this Enum value)
                // => value.DisplayNameOrDefault() ?? value.ToString()
                {
                    // More efficient form of ^ based on http://stackoverflow.com/a/17034624/11635
                    var enumType = value.GetType();
                    var enumMemberName = Enum.GetName(enumType, value);
                    return enumType
                        .GetEnumMemberAttribute<DisplayAttribute>(enumMemberName)
                        ?.GetName() // Potentially localized
                        ?? enumMemberName; // Or fall back to the enum name
                }
            
                /// returns the localized Name, if a [Display] attribute is applied to the enum member
                /// returns null if there is no attribute
                public static string DisplayNameOrDefault(this Enum value) =>
                    value.GetEnumMemberAttribute<DisplayAttribute>()?.GetName();
            
                static TAttribute GetEnumMemberAttribute<TAttribute>(this Enum value) where TAttribute : Attribute =>
                    value.GetType().GetEnumMemberAttribute<TAttribute>(value.ToString());
            
                static TAttribute GetEnumMemberAttribute<TAttribute>(this Type enumType, string enumMemberName) where TAttribute : Attribute =>
                    enumType.GetMember(enumMemberName).Single().GetCustomAttribute<TAttribute>();
            }
            

            【讨论】:

              【解决方案15】:

              在 Aydin 和 Todd 的回答的基础上进一步构建,这里有一个扩展方法,它还可以让您从资源文件中获取名称

              using AppResources;
              using System;
              using System.ComponentModel.DataAnnotations;
              using System.Linq;
              using System.Reflection;
              using System.Resources;
              
              public static class EnumExtensions
              {
                  public static string GetDisplayName(this Enum enumValue)
                  {
                      var enumMember= enumValue.GetType()
                                      .GetMember(enumValue.ToString());
              
                      DisplayAttribute displayAttrib = null;
                      if (enumMember.Any()) {
                          displayAttrib = enumMember 
                                      .First()
                                      .GetCustomAttribute<DisplayAttribute>();
                      }
              
                      string name = null;
                      Type resource = null;
              
                      if (displayAttrib != null)
                      {
                          name = displayAttrib.Name;
                          resource = displayAttrib.ResourceType;
                      }
              
                      return String.IsNullOrEmpty(name) ? enumValue.ToString()
                          : resource == null ?  name
                          : new ResourceManager(resource).GetString(name);
                  }
              }
              

              并像使用它

              public enum Season 
              {
                  [Display(ResourceType = typeof(Resource), Name = Season_Summer")]
                  Summer
              }
              

              【讨论】:

              • 我正在尝试让它为我的项目工作,但我收到“new ResourceManager(resource).GetString(name);”错误线。我问了一个问题 (stackoverflow.com/questions/31319251/…),然后我被送到了这里。当我在运行时查看“ResourceManager(resource)”时,它会返回“Resources.Enums.resource”。任何帮助将不胜感激。谢谢!
              • 更新了代码以在您没有为某些枚举值设置显示名称时更好地处理空值 - 可能会有所帮助
              • 那还是不行。我用错误消息更新了我在stackoverflow.com/questions/31319251/… 上的问题。感谢您的帮助!
              【解决方案16】:

              对于这个问题,我有两个解决方案。

              1. 第一个解决方案是从枚举中获取显示名称。
              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>
              
              1. 第二个解决方案是从枚举名称中获取显示名称,但这将在开发人员语言中拆分枚举,称为补丁。
              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" })&nbsp; @item.SplitOnCapitals()
                       </label>
                   }
                   @Html.ValidationMessageFor(x => x.CourseLocationType)
               </div>
              

              【讨论】:

              • 喜欢这里的 SplitOnCapitals 方法!我只使用了比 RegEx 更有效的 StringBuilder 重写了它: public static string SplitOnCapitals(this string text) { var sb = new StringBuilder(text); for (int i = sb.Length-1; i > 0; i--) { if (char.IsUpper(sb[i])) { sb.Insert(i, ' '); } } 返回 sb.ToString(); }
              【解决方案17】:

              我想为依赖于文化的 GetDisplayName 枚举扩展做出贡献。希望这对以前像我一样在谷歌上搜索这个答案的人有用:

              Aydin AdnTodd 提到的“标准”方式:

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

              【讨论】:

                【解决方案18】:

                2020 年更新:此线程中许多人提供的函数的更新版本,但现在适用于 C# 7.3 及更高版本:

                现在您可以将泛型方法限制为枚举类型,这样您就可以编写一个方法扩展来将它与您的所有枚举一起使用,如下所示:

                通用扩展方法:

                public static string ATexto<T>(this T enumeración) where T : struct, Enum {
                    var tipo = enumeración.GetType();
                    return tipo.GetMember(enumeración.ToString())
                    .Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == tipo).First()
                    .GetCustomAttribute<DisplayAttribute>()?.Name ?? enumeración.ToString();
                } 
                

                枚举:

                public enum TipoImpuesto { 
                IVA, INC, [Display(Name = "IVA e INC")]IVAeINC, [Display(Name = "No aplica")]NoAplica };
                

                使用方法:

                var tipoImpuesto = TipoImpuesto.IVAeINC;
                var textoTipoImpuesto = tipoImpuesto.ATexto(); // Prints "IVA e INC".
                

                奖金,带标志的枚举:如果您正在处理普通枚举,上面的函数就足够了,但是如果您的任何枚举可以使用标志获取多个值,那么您将需要修改像这样(此代码使用 C#8 功能):

                    public static string ATexto<T>(this T enumeración) where T : struct, Enum {
                
                        var tipo = enumeración.GetType();
                        var textoDirecto = enumeración.ToString();
                
                        string obtenerTexto(string textoDirecto) => tipo.GetMember(textoDirecto)
                            .Where(x => x.MemberType == MemberTypes.Field && ((FieldInfo)x).FieldType == tipo)
                            .First().GetCustomAttribute<DisplayAttribute>()?.Name ?? textoDirecto;
                
                        if (textoDirecto.Contains(", ")) {
                
                            var texto = new StringBuilder();
                            foreach (var textoDirectoAux in textoDirecto.Split(", ")) {
                                texto.Append($"{obtenerTexto(textoDirectoAux)}, ");
                            }
                            return texto.ToString()[0..^2];
                
                        } else {
                            return obtenerTexto(textoDirecto);
                        }
                
                    } 
                

                带有标志的枚举:

                [Flags] public enum TipoContribuyente {
                    [Display(Name = "Común")] Común = 1, 
                    [Display(Name = "Gran Contribuyente")] GranContribuyente = 2, 
                    Autorretenedor = 4, 
                    [Display(Name = "Retenedor de IVA")] RetenedorIVA = 8, 
                    [Display(Name = "Régimen Simple")] RégimenSimple = 16 } 
                

                使用方法:

                var tipoContribuyente = TipoContribuyente.RetenedorIVA | TipoContribuyente.GranContribuyente;
                var textoAux = tipoContribuyente.ATexto(); // Prints "Gran Contribuyente, Retenedor de IVA".
                

                【讨论】:

                  【解决方案19】:

                  仅显示枚举的 显示名称属性 只需使用 Microsoft.AspNetCore.Mvc.Rendering

                  @Html.DisplayFor(x => EnumType.EnumValue)
                  

                  这就够了。

                  为了显示SelectList,如下:

                   <select id="someIdForTheEndPoint" asp-items="Html.GetEnumSelectList<EnumType>()">
                       <option selected="selected" value="">Select value</option>
                   </select>
                  

                  【讨论】:

                    【解决方案20】:

                    根据以前的答案,我创建了这个舒适的助手,以一种可读的方式支持所有 DisplayAttribute 属性:

                    public static class EnumExtensions
                        {
                            public static DisplayAttributeValues GetDisplayAttributeValues(this Enum enumValue)
                            {
                                var displayAttribute = enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttribute<DisplayAttribute>();
                    
                                return new DisplayAttributeValues(enumValue, displayAttribute);
                            }
                    
                            public sealed class DisplayAttributeValues
                            {
                                private readonly Enum enumValue;
                                private readonly DisplayAttribute displayAttribute;
                    
                                public DisplayAttributeValues(Enum enumValue, DisplayAttribute displayAttribute)
                                {
                                    this.enumValue = enumValue;
                                    this.displayAttribute = displayAttribute;
                                }
                    
                                public bool? AutoGenerateField => this.displayAttribute?.GetAutoGenerateField();
                                public bool? AutoGenerateFilter => this.displayAttribute?.GetAutoGenerateFilter();
                                public int? Order => this.displayAttribute?.GetOrder();
                                public string Description => this.displayAttribute != null ? this.displayAttribute.GetDescription() : string.Empty;
                                public string GroupName => this.displayAttribute != null ? this.displayAttribute.GetGroupName() : string.Empty;
                                public string Name => this.displayAttribute != null ? this.displayAttribute.GetName() : this.enumValue.ToString();
                                public string Prompt => this.displayAttribute != null ? this.displayAttribute.GetPrompt() : string.Empty;
                                public string ShortName => this.displayAttribute != null ? this.displayAttribute.GetShortName() : this.enumValue.ToString();
                            }
                        }
                    

                    【讨论】:

                      【解决方案21】:

                      我尝试将其作为编辑但被拒绝;我不明白为什么。

                      如果您使用包含自定义属性和普通项目的 Enum 调用它,上面将引发异常,例如

                      public enum CommentType
                      {
                          All = 1,
                          Rent = 2,
                          Insurance = 3,
                          [Display(Name="Service Charge")]
                          ServiceCharge = 4
                      }
                      

                      所以我稍微修改了代码,以便在尝试访问自定义属性之前检查它们,如果没有找到则使用名称。

                      using System;
                      using System.Collections.Generic;
                      using System.ComponentModel.DataAnnotations;
                      using System.Linq;
                      using System.Reflection;
                      
                      public static class EnumHelper<T>
                      {
                          public static IList<T> GetValues(Enum value)
                          {
                              var enumValues = new List<T>();
                      
                              foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
                              {
                                  enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false));
                              }
                              return enumValues;
                          }
                      
                          public static T Parse(string value)
                          {
                              return (T)Enum.Parse(typeof(T), value, true);
                          }
                      
                          public static IList<string> GetNames(Enum value)
                          {
                              return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList();
                          }
                      
                          public static IList<string> GetDisplayValues(Enum value)
                          {
                              return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList();
                          }
                      
                          private static string lookupResource(Type resourceManagerProvider, string resourceKey)
                          {
                              foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
                              {
                                  if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager))
                                  {
                                      System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null);
                                      return resourceManager.GetString(resourceKey);
                                  }
                              }
                      
                              return resourceKey; // Fallback with the key name
                          }
                      
                          public static string GetDisplayValue(T value)
                          {
                              var fieldInfo = value.GetType().GetField(value.ToString());
                      
                              var descriptionAttributes = fieldInfo.GetCustomAttributes(
                                  typeof(DisplayAttribute), false) as DisplayAttribute[];
                      
                              if (descriptionAttributes.Any() && descriptionAttributes[0].ResourceType != null)
                                  return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name);
                      
                              if (descriptionAttributes == null) return string.Empty;
                              return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
                          }
                      }
                      

                      【讨论】:

                        【解决方案22】:

                        使用 MVC5 你可以使用:

                        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
                        }
                        

                        如果你想创建一个下拉选择器,你可以使用:

                        @Html.EnumDropdownListFor(expression: model => model.PromotionSelector, optionLabel: "Select") 
                        

                        【讨论】:

                          【解决方案23】:

                          这可能是作弊,但它有效:

                           @foreach (var yourEnum in Html.GetEnumSelectList<YourEnum>())
                           {
                               @yourEnum.Text
                           }
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2017-04-21
                            • 2021-08-06
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多