String representation of an Enum

后端 未结 30 1970
不思量自难忘°
不思量自难忘° 2020-11-22 02:44

I have the following enumeration:

public enum AuthenticationMethod
{
    FORMS = 1,
    WINDOWSAUTHENTICATION = 2,
    SINGLESIGNON = 3
}

T

30条回答
  •  灰色年华
    2020-11-22 03:07

    For larger string enum sets, the listed examples can become tiresome. If you want a list of status codes, or a list of other string based enums, an attribute system is annoying to use, and a static class with instances of itself is annoying to configure. For my own solution, I make use of T4 templating to make it easier to have string-backed enums. The result comes out similar to how the HttpMethod class works.

    You can use it like this:

        string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed
        ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found
    
        // Implements TypeConverter so you can use it with string conversion methods.
        var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode));
        ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode);
    
        // You can get a full list of the values
        bool canIterateOverValues = ResponseStatusCode.Values.Any(); 
    
        // Comparisons are by value of the "Name" property. Not by memory pointer location.
        bool implementsByValueEqualsEqualsOperator = "SUCCESS" == ResponseStatusCode.SUCCESS; 
    

    You start out with a Enum.tt file.

    <#@ include file="StringEnum.ttinclude" #>
    
    
    <#+
    public static class Configuration
    {
        public static readonly string Namespace = "YourName.Space";
        public static readonly string EnumName = "ResponseStatusCode";
        public static readonly bool IncludeComments = true;
    
        public static readonly object Nodes = new
        {
            SUCCESS = "The response was successful.",
            NON_SUCCESS = "The request was not successful.",
            RESOURCE_IS_DISCONTINUED = "The resource requested has been discontinued and can no longer be accessed."
        };
    }
    #>
    

    Then, you add in your StringEnum.ttinclude file.

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ import namespace="System" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Reflection" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ output extension=".cs" #>
    <#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>
    
    //------------------------------------------------------------------------------
    // 
    //     This code was generated by a tool.
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // 
    //------------------------------------------------------------------------------
    
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    
    namespace <#= Configuration.Namespace #>
    {
        /// 
        /// TypeConverter implementations allow you to use features like string.ToNullable(T).
        /// 
        public class <#= Configuration.EnumName #>TypeConverter : TypeConverter
        {
            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
            }
    
            public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
            {
                var casted = value as string;
    
                if (casted != null)
                {
                    var result = <#= Configuration.EnumName #>.ValueOf(casted);
                    if (result != null)
                    {
                        return result;
                    }
                }
    
                return base.ConvertFrom(context, culture, value);
            }
    
            public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
            {
                var casted = value as <#= Configuration.EnumName #>;
                if (casted != null && destinationType == typeof(string))
                {
                    return casted.ToString();
                }
    
                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    
        [TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))]
        public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>>
        {
    //---------------------------------------------------------------------------------------------------
    // V A L U E S _ L I S T
    //---------------------------------------------------------------------------------------------------
    <# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #>
    
            private static List<<#= Configuration.EnumName #>> _list { get; set; } = null;
            public static List<<#= Configuration.EnumName #>> ToList()
            {
                if (_list == null)
                {
                    _list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>))
                        .Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList();
                }
    
                return _list;
            }
    
            public static List<<#= Configuration.EnumName #>> Values()
            {
                return ToList();
            }
    
            /// 
            /// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
            /// 
            /// 
            /// 
            public static <#= Configuration.EnumName #> ValueOf(string key)
            {
                return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
            }
    
    
    //---------------------------------------------------------------------------------------------------
    // I N S T A N C E _ D E F I N I T I O N
    //---------------------------------------------------------------------------------------------------      
            public string Name { get; private set; }
            public string Description { get; private set; }
            public override string ToString() { return this.Name; }
    
            /// 
            /// Implcitly converts to string.
            /// 
            /// 
            public static implicit operator string(<#= Configuration.EnumName #> d)
            {
                return d.ToString();
            }
    
            /// 
            /// Compares based on the == method. Handles nulls gracefully.
            /// 
            /// 
            /// 
            /// 
            public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
            {
                return !(a == b);
            }
    
            /// 
            /// Compares based on the .Equals method. Handles nulls gracefully.
            /// 
            /// 
            /// 
            /// 
            public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
            {
                return a?.ToString() == b?.ToString();
            }
    
            /// 
            /// Compares based on the .ToString() method
            /// 
            /// 
            /// 
            public override bool Equals(object o)
            {
                return this.ToString() == o?.ToString();
            }
    
            /// 
            /// Compares based on the .ToString() method
            /// 
            /// 
            /// 
            public bool Equals(<#= Configuration.EnumName #> other)
            {
                return this.ToString() == other?.ToString();
            }
    
            /// 
            /// Compares based on the .Name property
            /// 
            /// 
            public override int GetHashCode()
            {
                return this.Name.GetHashCode();
            }
        }
    }
    
    <#+
    
    public static class Helpers
    {
            public static string PrintEnumProperties(object nodes)
            {
                string o = "";
                Type nodesTp = Configuration.Nodes.GetType();
                PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray();
    
                for(int i = 0; i < props.Length; i++)
                {
                    var prop = props[i];
                    if (Configuration.IncludeComments)
                    {
                        o += "\r\n\r\n";
                        o += "\r\n        ///";
                        o += "\r\n        /// "+Helpers.PrintPropertyValue(prop, Configuration.Nodes);
                        o += "\r\n        ///";
                    }
    
                    o += "\r\n        public static readonly "+Configuration.EnumName+" "+prop.Name+ " = new "+Configuration.EnumName+"(){ Name = \""+prop.Name+"\", Description = "+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+ "};";
                }
    
                o += "\r\n\r\n";
    
                return o;
            }
    
            private static Dictionary GetValuesMap()
            {
                Type nodesTp = Configuration.Nodes.GetType();
                PropertyInfo[] props= nodesTp.GetProperties();
                var dic = new Dictionary();
                for(int i = 0; i < props.Length; i++)
                {
                    var prop = nodesTp.GetProperties()[i];
                    dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString();
                }
                return dic;
            }
    
            public static string PrintMasterValuesMap(object nodes)
            {
                Type nodesTp = Configuration.Nodes.GetType();
                PropertyInfo[] props= nodesTp.GetProperties();
                string o = "        private static readonly Dictionary ValuesMap = new Dictionary()\r\n        {";
                for(int i = 0; i < props.Length; i++)
                {
                    var prop = nodesTp.GetProperties()[i];
                    o += "\r\n            { \""+prop.Name+"\", "+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },");
                }
                o += ("\r\n        };\r\n");
    
                return o;
            }
    
    
            public static string PrintPropertyValue(PropertyInfo prop, object objInstance)
            {
                switch(prop.PropertyType.ToString()){
                    case "System.Double":
                        return prop.GetValue(objInstance).ToString()+"D";
                    case "System.Float":
                        return prop.GetValue(objInstance).ToString()+"F";
                    case "System.Decimal":
                        return prop.GetValue(objInstance).ToString()+"M";
                    case "System.Long":
                        return prop.GetValue(objInstance).ToString()+"L";
                    case "System.Boolean":
                    case "System.Int16":
                    case "System.Int32":
                        return prop.GetValue(objInstance).ToString().ToLowerInvariant();
                    case "System.String":
                        return "\""+prop.GetValue(objInstance)+"\"";
                }
    
                return prop.GetValue(objInstance).ToString();
            }
    
            public static string _ (int numSpaces)
            {
                string o = "";
                for(int i = 0; i < numSpaces; i++){
                    o += " ";
                }
    
                return o;
            }
    }
    #>
    

    Finally, you recompile your Enum.tt file and the output looks like this:

    //------------------------------------------------------------------------------
    // 
    //     This code was generated by a tool.
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // 
    //------------------------------------------------------------------------------
    
    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    namespace YourName.Space
    {
        public class ResponseStatusCode
        {
    //---------------------------------------------------------------------------------------------------
    // V A L U E S _ L I S T 
    //---------------------------------------------------------------------------------------------------
    
    
    
            ///
            /// "The response was successful."
            ///
            public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name = "SUCCESS", Description = "The response was successful."};
    
    
            ///
            /// "The request was not successful."
            ///
            public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name = "NON_SUCCESS", Description = "The request was not successful."};
    
    
            ///
            /// "The resource requested has been discontinued and can no longer be accessed."
            ///
            public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name = "RESOURCE_IS_DISCONTINUED", Description = "The resource requested has been discontinued and can no longer be accessed."};
    
    
            private static List _list { get; set; } = null;
            public static List ToList()
            {
                if (_list == null)
                {
                    _list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode))
                        .Select(x => x.GetValue(null)).OfType().ToList();
                }
    
                return _list;
            }
    
            public static List Values()
            {
                return ToList();
            }
    
            /// 
            /// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
            /// 
            /// 
            /// 
            public static ResponseStatusCode ValueOf(string key)
            {
                return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
            }
    
    
    //---------------------------------------------------------------------------------------------------
    // I N S T A N C E _ D E F I N I T I O N 
    //---------------------------------------------------------------------------------------------------       
            public string Name { get; set; }
            public string Description { get; set; }
            public override string ToString() { return this.Name; }
    
            /// 
            /// Implcitly converts to string.
            /// 
            /// 
            public static implicit operator string(ResponseStatusCode d)
            {
                return d.ToString();
            }
    
            /// 
            /// Compares based on the == method. Handles nulls gracefully.
            /// 
            /// 
            /// 
            /// 
            public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b)
            {
                return !(a == b);
            }
    
            /// 
            /// Compares based on the .Equals method. Handles nulls gracefully.
            /// 
            /// 
            /// 
            /// 
            public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b)
            {
                return a?.ToString() == b?.ToString();
            }
    
            /// 
            /// Compares based on the .ToString() method
            /// 
            /// 
            /// 
            public override bool Equals(object o)
            {
                return this.ToString() == o?.ToString();
            }
    
            /// 
            /// Compares based on the .Name property
            /// 
            /// 
            public override int GetHashCode()
            {
                return this.Name.GetHashCode();
            }
        }
    }
    

提交回复
热议问题