【问题标题】:MVC.net get enum display name in view without having to refer to enum type in viewMVC.net 在视图中获取枚举显示名称,而无需在视图中引用枚举类型
【发布时间】:2012-03-08 21:29:25
【问题描述】:

我在 ViewModelBase 类中有以下辅助方法,它被其他视图模型继承:

public string GetEnumName<T>(Enum value)
        {
            Type enumType = typeof(T);
            var enumValue = Enum.GetName(enumType, value);
            MemberInfo member = enumType.GetMember(enumValue)[0];

            var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
            var outString = ((DisplayAttribute)attrs[0]).Name;

            if (((DisplayAttribute)attrs[0]).ResourceType != null)
            {
                outString = ((DisplayAttribute)attrs[0]).GetName();
            }

            return outString;
        }

然后我从这样的视图中调用它:

<p>
@{var rel = Model.GetEnumDisplayName<Enums.wheteverEnum>(Model.wheteverEnum); }
@rel
</p>

问题是——我可以使用这种方法,这样我就不必告诉它enum 的类型了吗?基本上我想为所有enums 做这个:

@Model.GetEnumDisplayName(Model.wheteverEnum)

没有typeof,没有T,不需要在视图中添加对Enums命名空间的引用...

可能吗?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 generics c#-4.0 enums


    【解决方案1】:

    您可以简单地删除类型参数并使其成为扩展方法。

        public static string DisplayName(this Enum value)
        {
            Type enumType = value.GetType();
            var enumValue = Enum.GetName(enumType, value);
            MemberInfo member = enumType.GetMember(enumValue)[0];
    
            var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
            var outString = ((DisplayAttribute)attrs[0]).Name;
    
            if (((DisplayAttribute)attrs[0]).ResourceType != null)
            {
                outString = ((DisplayAttribute)attrs[0]).GetName();
            }
    
            return outString;
        }
    
        @Model.wheteverEnum.DisplayName()
    

    【讨论】:

    • +1 非常好。它使用原始代码并添加了扩展方法的代码实现,包括如何调用它。
    • 为了完整起见,您应该检查是否有任何DisplayAttributes 应用于枚举值,如果没有,则默认返回value.ToString()。否则,当您拨打 ((DisplayAttribute)attrs[0]).Name 时,您将收到 IndexOutOfRangeException
    • 如果有人试图从控制器调用:DisplayName((MyEnum)id);
    • 当我将此扩展方法添加到包含枚举类型的模型中时,ide 报告错误Extension method must be defined in a non-generic static class 并且当我将模型类更改为静态类时,我得到了大量由于静态而产生的其他错误定义。我不知道在哪里添加这个sn-p?我还为模型创建了一个静态基类,但是我无法从基本静态模型类继承非静态模型。
    【解决方案2】:

    你不能把它写成扩展方法吗?比如……

    public static class EnumExtensions
    {
      public static string ToDescription(this Enum e)
      {
         var attributes = (DisplayAttribute[])e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false);
         return attributes.Length > 0 ? attributes[0].Description : string.Empty;
      }
    }
    

    用法:

    @Model.WhateverEnum.ToDescription();
    

    【讨论】:

      【解决方案3】:

      干得好@jrummell!

      我在下面添加了一个小调整,它捕获了枚举没有关联 Display 属性的场景(目前它会引发异常)

      /// <summary>
      /// Gets the DataAnnotation DisplayName attribute for a given enum (for displaying enums values nicely to users)
      /// </summary>
      /// <param name="value">Enum value to get display for</param>
      /// <returns>Pretty version of enum (if there is one)</returns>
      /// <remarks>
      /// Inspired by :
      ///     http://stackoverflow.com/questions/9328972/mvc-net-get-enum-display-name-in-view-without-having-to-refer-to-enum-type-in-vi
      /// </remarks>
      public static string DisplayFor(this Enum value) {
          Type enumType = value.GetType();
          var enumValue = Enum.GetName(enumType, value);
          MemberInfo member = enumType.GetMember(enumValue)[0];
          string outString = "";
      
          var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
          if (attrs.Any()) {
              var displayAttr = ((DisplayAttribute)attrs[0]);
      
              outString = displayAttr.Name;
      
              if (displayAttr.ResourceType != null) {
                  outString = displayAttr.GetName();
              }
          } else {
              outString = value.ToString();
          }
      
          return outString;
      }
      

      【讨论】:

        【解决方案4】:

        @jrummell 在 VB.NET 中对我们少数人的回答...

        Module ModuleExtension
        
            <Extension()>
            Public Function DisplayName(ByVal value As System.Enum) As String
        
                Dim enumType As Type = value.GetType()
                Dim enumValue = System.Enum.GetName(enumType, value)
                Dim member As MemberInfo = enumType.GetMember(enumValue)(0)
        
                Dim attrs = member.GetCustomAttributes(GetType(DisplayAttribute), False)
                Dim outString = CType(attrs(0), DisplayAttribute).Name
        
                If (CType(attrs(0), DisplayAttribute).ResourceType IsNot Nothing) Then
                    outString = CType(attrs(0), DisplayAttribute).GetName()
                End If
        
                Return outString
            End Function
        
        
        End Module
        

        【讨论】:

          【解决方案5】:

          对于可能遇到此问题的任何人,我发现这比其他任何事情都容易得多: https://www.codeproject.com/articles/776908/dealing-with-enum-in-mvc

          只需在“Views\Shared”下创建一个文件夹“DisplayTemplate”,并在新文件夹“DisplayTemplate”中创建一个空视图(命名为“Enum”),并将这段代码复制到其中”

          @model Enum
          
          @if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
          {
              // Display Enum using same names (from [Display] attributes) as in editors
              string displayName = null;
              foreach (SelectListItem item in EnumHelper.GetSelectList(ViewData.ModelMetadata, (Enum)Model))
              {
                  if (item.Selected)
                  {
                      displayName = item.Text ?? item.Value;
                  }
              }
          
              // Handle the unexpected case that nothing is selected
              if (String.IsNullOrEmpty(displayName))
              {
                  if (Model == null)
                  {
                      displayName = String.Empty;
                  }
                  else
                  {
                      displayName = Model.ToString();
                  }
              }
          
              @Html.DisplayTextFor(model => displayName)
          }
          else
          {
              // This Enum type is not supported.  Fall back to the text.
              @Html.DisplayTextFor(model => model)
          }
          

          【讨论】:

            【解决方案6】:

            这是我为此编写的一个扩展方法……它有一些额外的逻辑来解析枚举名称并用大写字母分割。您可以使用显示属性覆盖任何名称

            public static TAttribute GetAttribute<TAttribute>(this ICustomAttributeProvider parameterInfo) where TAttribute : Attribute
            {
                object[] attributes = parameterInfo.GetCustomAttributes(typeof(TAttribute), false);
                return attributes.Length > 0 ? (TAttribute)attributes[0] : null;
            }
            public static bool HasAttribute<TAttribute>(this ICustomAttributeProvider parameterInfo) where TAttribute : Attribute
            {
                object[] attributes = parameterInfo.GetCustomAttributes(typeof(TAttribute), false);
                return attributes.Length > 0 ? true : false;
            }
            
            public static string ToFriendlyEnum(this Enum type)
            {
                return type.GetType().HasAttribute<DescriptionAttribute>() ? type.GetType().GetAttribute<DescriptionAttribute>().Description : type.ToString().ToFriendlyEnum();
            }
            
            public static string ToFriendlyEnum(this string value)
            {
                char[] chars = value.ToCharArray();
                string output = string.Empty;
            
                for (int i = 0; i < chars.Length; i++)
                {
                    if (i <= 0 || chars[i - 1].ToString() != chars[i - 1].ToString().ToUpper() && chars[i].ToString() != chars[i].ToString().ToLower())
                    {
                        output += " ";
                    }
            
                    output += chars[i];
                }
            
                return output.Trim();
            }
            

            GetAttribute 扩展方法可能有点矫枉过正,但我​​在项目的其他地方使用它们,所以当我编写 Enum 扩展时它们被重用。您可以轻松地将它们组合回 ToFriendlyEnum(this Enum type) 方法

            【讨论】:

              【解决方案7】:

              建议的解决方案不适用于 MVC3:所以下面的助手很好。:

                  public static string GetEnumDescription(this Enum value)
                  {
                      Type type = value.GetType();
                      string name = Enum.GetName(type, value);
                      if (name != null)
                      {
                          FieldInfo field = type.GetField(name);
                          if (field != null)
                          {
                              string attr = field.GetCustomAttributesData()[0].NamedArguments[0].TypedValue.Value.ToString();
                              if (attr == null)
                              {
                                  return name;
                              }
                              else
                              {
                                  return attr;
                              }
                          }
                      }
                      return null;
                  }
              

              【讨论】:

                猜你喜欢
                • 2023-03-26
                • 2017-04-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-01-14
                • 2022-10-03
                • 2018-04-05
                相关资源
                最近更新 更多