Enum ToString with user friendly strings

后端 未结 23 1739
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 11:44

My enum consists of the following values:

private enum PublishStatusses{
    NotCompleted,
    Completed,
    Error
};

I want to be able to

相关标签:
23条回答
  • 2020-11-22 12:24

    Maybe I'm missing something, but what's wrong with Enum.GetName?

    public string GetName(PublishStatusses value)
    {
        return Enum.GetName(typeof(PublishStatusses), value)
    }
    

    edit: for user-friendly strings, you need to go through a .resource to get internationalisation/localisation done, and it would arguably be better to use a fixed key based on the enum key than a decorator attribute on the same.

    0 讨论(0)
  • 2020-11-22 12:25

    With respect to Ray Booysen, there is a bug in the code: Enum ToString with user friendly strings

    You need to account for multiple attributes on the enum values.

    public static string GetDescription<T>(this object enumerationValue)
                where T : struct
        {
            Type type = enumerationValue.GetType();
            if (!type.IsEnum)
            {
                throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
            }
    
            //Tries to find a DescriptionAttribute for a potential friendly name
            //for the enum
            MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
            if (memberInfo != null && memberInfo.Length > 0)
            {
                object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
    
                if (attrs != null && attrs.Length > 0 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null)
                {
                    //Pull out the description value
                    return ((DescriptionAttribute)attrs.Where(t=>t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description;
                }
            }
            //If we have no description attribute, just return the ToString of the enum
            return enumerationValue.ToString();
    
    0 讨论(0)
  • 2020-11-22 12:25

    I happen to be a VB.NET fan, so here's my version, combining the DescriptionAttribute method with an extension method. First, the results:

    Imports System.ComponentModel ' For <Description>
    
    Module Module1
      ''' <summary>
      ''' An Enum type with three values and descriptions
      ''' </summary>
      Public Enum EnumType
        <Description("One")>
        V1 = 1
    
        ' This one has no description
        V2 = 2
    
        <Description("Three")>
        V3 = 3
      End Enum
    
      Sub Main()
        ' Description method is an extension in EnumExtensions
        For Each v As EnumType In [Enum].GetValues(GetType(EnumType))
          Console.WriteLine("Enum {0} has value {1} and description {2}",
            v,
            CInt(v),
            v.Description
          )
        Next
        ' Output:
        ' Enum V1 has value 1 and description One
        ' Enum V2 has value 2 and description V2
        ' Enum V3 has value 3 and description Three
      End Sub
    End Module
    

    Basic stuff: an enum called EnumType with three values V1, V2 and V3. The "magic" happens in the Console.WriteLine call in Sub Main(), where the last argument is simply v.Description. This returns "One" for V1, "V2" for V2, and "Three" for V3. This Description-method is in fact an extension method, defined in another module called EnumExtensions:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Imports System.Runtime.CompilerServices
    Imports System.Reflection
    Imports System.ComponentModel
    
    Module EnumExtensions
      Private _Descriptions As New Dictionary(Of String, String)
    
      ''' <summary>
      ''' This extension method adds a Description method
      ''' to all enum members. The result of the method is the
      ''' value of the Description attribute if present, else
      ''' the normal ToString() representation of the enum value.
      ''' </summary>
      <Extension>
      Public Function Description(e As [Enum]) As String
        ' Get the type of the enum
        Dim enumType As Type = e.GetType()
        ' Get the name of the enum value
        Dim name As String = e.ToString()
    
        ' Construct a full name for this enum value
        Dim fullName As String = enumType.FullName + "." + name
    
        ' See if we have looked it up earlier
        Dim enumDescription As String = Nothing
        If _Descriptions.TryGetValue(fullName, enumDescription) Then
          ' Yes we have - return previous value
          Return enumDescription
        End If
    
        ' Find the value of the Description attribute on this enum value
        Dim members As MemberInfo() = enumType.GetMember(name)
        If members IsNot Nothing AndAlso members.Length > 0 Then
          Dim descriptions() As Object = members(0).GetCustomAttributes(GetType(DescriptionAttribute), False)
          If descriptions IsNot Nothing AndAlso descriptions.Length > 0 Then
            ' Set name to description found
            name = DirectCast(descriptions(0), DescriptionAttribute).Description
          End If
        End If
    
        ' Save the name in the dictionary:
        _Descriptions.Add(fullName, name)
    
        ' Return the name
        Return name
      End Function
    End Module
    

    Because looking up description attributes using Reflection is slow, the lookups are also cached in a private Dictionary, that is populated on demand.

    (Sorry for the VB.NET solution - it should be relatively straighforward to translate it to C#, and my C# is rusty on new subjects like extensions)

    0 讨论(0)
  • 2020-11-22 12:25

    This is an update to Ray Booysen's code that uses the generic GetCustomAttributes method and LINQ to make things a bit tidier.

        /// <summary>
        /// Gets the value of the <see cref="T:System.ComponentModel.DescriptionAttribute"/> on an struct, including enums.  
        /// </summary>
        /// <typeparam name="T">The type of the struct.</typeparam>
        /// <param name="enumerationValue">A value of type <see cref="T:System.Enum"/></param>
        /// <returns>If the struct has a Description attribute, this method returns the description.  Otherwise it just calls ToString() on the struct.</returns>
        /// <remarks>Based on http://stackoverflow.com/questions/479410/enum-tostring/479417#479417, but useful for any struct.</remarks>
        public static string GetDescription<T>(this T enumerationValue) where T : struct
        {
            return enumerationValue.GetType().GetMember(enumerationValue.ToString())
                    .SelectMany(mi => mi.GetCustomAttributes<DescriptionAttribute>(false),
                        (mi, ca) => ca.Description)
                    .FirstOrDefault() ?? enumerationValue.ToString();
        }   
    
    0 讨论(0)
  • 2020-11-22 12:26

    Use Enum.GetName

    From the above link...

    using System;
    
    public class GetNameTest {
        enum Colors { Red, Green, Blue, Yellow };
        enum Styles { Plaid, Striped, Tartan, Corduroy };
    
        public static void Main() {
    
            Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
            Console.WriteLine("The 4th value of the Styles Enum is {0}", Enum.GetName(typeof(Styles), 3));
        }
    }
    // The example displays the following output:
    //       The 4th value of the Colors Enum is Yellow
    //       The 4th value of the Styles Enum is Corduroy
    
    0 讨论(0)
  • 2020-11-22 12:26

    Even cleaner summary:

    using System;
    using System.Reflection;
    
    public class TextAttribute : Attribute
    {
        public string Text;
        public TextAttribute(string text)
        {
            Text = text;
        }
    }  
    
    public static class EnumExtender
    {
        public static string ToText(this Enum enumeration)
        {
            var memberInfo = enumeration.GetType().GetMember(enumeration.ToString());
            if (memberInfo.Length <= 0) return enumeration.ToString();
    
            var attributes = memberInfo[0].GetCustomAttributes(typeof(TextAttribute), false);
            return attributes.Length > 0 ? ((TextAttribute)attributes[0]).Text : enumeration.ToString();
        }
    }
    

    Same usage as underscore describes.

    0 讨论(0)
提交回复
热议问题