Retrieve enum value based on XmlEnumAttribute name value

后端 未结 5 1928
北海茫月
北海茫月 2020-12-15 20:20

I need a Generic function to retrieve the name or value of an enum based on the XmlEnumAttribute \"Name\" property of the enum. For example I have the following enum define

相关标签:
5条回答
  • 2020-12-15 20:50

    @Dean, @Jason and @Camron, thank you for your solutions. Your solutions helped me in solving my problem, where, given an XmlEnumAttribute name, the actual enum value was needed.

    My variant is mentioned here.

    I am also including it here as as asked by one of our moderators:

    The actual problem was how to get Item10, when given a value of 10. Taking a cue from the solution cited by our above mentioned friends, I came up with the following method, which when passed a value contained in XmlEnumAttribute, would return the enum value:

    private static T GetEnumValueFromXmlAttrName<T>(string attribVal)
    {
        T val = default(T);
    
        if (typeof(T).BaseType.FullName.Equals("System.Enum"))
        {
            FieldInfo[] fields = typeof(T).GetFields();
    
            foreach (FieldInfo field in fields)
            {
                object[] attribs = field.GetCustomAttributes(typeof(XmlEnumAttribute), false);
    
                foreach (object attr in attribs)
                {
                    if ((attr as XmlEnumAttribute).Name.Equals(attribVal))
                    {
                        val = (T)field.GetValue(null);
                        return val;
                    }
                }
            }
        }
        else
            throw new Exception("The supplied type is not an Enum.");
    
        return val;
    }
    
    0 讨论(0)
  • 2020-12-15 20:52

    Slightly modified from: http://www.wackylabs.net/2006/06/getting-the-xmlenumattribute-value-for-an-enum-field/

    public static string ToString2 (this Enum e) {
        // Get the Type of the enum
        Type t = e.GetType ();
    
        // Get the FieldInfo for the member field with the enums name
        FieldInfo info = t.GetField (e.ToString ("G"));
    
        // Check to see if the XmlEnumAttribute is defined on this field
        if (!info.IsDefined (typeof (XmlEnumAttribute), false)) {
            // If no XmlEnumAttribute then return the string version of the enum.
            return e.ToString ("G");
        }
    
        // Get the XmlEnumAttribute
        object[] o = info.GetCustomAttributes (typeof (XmlEnumAttribute), false);
        XmlEnumAttribute att = (XmlEnumAttribute)o[0];
        return att.Name;
    }
    
    0 讨论(0)
  • 2020-12-15 20:57

    Here's a variation that generates a dictionary from the enum, allowing you to potentially cache the reflection part of it should you need to use it a lot.

    /// <summary>
    /// Generates a dictionary allowing you to get the csharp enum value
    /// from the string value in the matching XmlEnumAttribute.
    /// You need this to be able to dynamically set entries from a xsd:enumeration
    /// when you've used xsd.exe to generate a .cs from the xsd.
    /// https://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx
    /// </summary>
    /// <typeparam name="T">The xml enum type you want the mapping for</typeparam>
    /// <returns>Mapping dictionary from attribute values (key) to the actual enum values</returns>
    /// <exception cref="System.ArgumentException">T must be an enum</exception>
    private static Dictionary<string, T> GetEnumMap<T>() where T : struct, IConvertible
    {
            if (!typeof(T).IsEnum)
            {
                    throw new ArgumentException("T must be an enum");
            }
            var members = typeof(T).GetMembers();
            var map = new Dictionary<string, T>();
            foreach (var member in members)
            {
                    var enumAttrib = member.GetCustomAttributes(typeof(XmlEnumAttribute), false).FirstOrDefault() as XmlEnumAttribute;
                    if (enumAttrib == null)
                    {
                            continue;
                    }
                    var xmlEnumValue = enumAttrib.Name;
                    var enumVal = ((FieldInfo)member).GetRawConstantValue();
                    map.Add(xmlEnumValue, (T)enumVal);
            }
            return map;
    }
    

    usage:

    var map = GetEnumMap<Currency>();
    return map["02"]; // returns Currency.EUR
    
    0 讨论(0)
  • 2020-12-15 20:58

    A requirement to solve this exact same problem led me to this question and answer. As I develop in VB.NET, I rewrote CkH's solution into VB and modified it to use your GetXmlAttrNameFromEnumValue function.

    Public Shared Function GetCode(Of T)(ByVal value As String) As T
        For Each o As Object In System.Enum.GetValues(GetType(T))
            Dim enumValue As T = CType(o, T)
            If GetXmlAttrNameFromEnumValue(Of T)(enumValue).Equals(value, StringComparison.OrdinalIgnoreCase) Then
                Return CType(o, T)
            End If
        Next
    
        Throw New ArgumentException("No code exists for type " + GetType(T).ToString() + " corresponding to value of " + value)
    End Function
    

    C# Version:

    public static string GetXmlAttrNameFromEnumValue<T>(T pEnumVal)
    {
        // http://stackoverflow.com/q/3047125/194717
        Type type = pEnumVal.GetType();
        FieldInfo info = type.GetField(Enum.GetName(typeof(T), pEnumVal));
        XmlEnumAttribute att = (XmlEnumAttribute)info.GetCustomAttributes(typeof(XmlEnumAttribute), false)[0];
        //If there is an xmlattribute defined, return the name
    
        return att.Name;
    }
    public static T GetCode<T>(string value)
    {
        // http://stackoverflow.com/a/3073272/194717
        foreach (object o in System.Enum.GetValues(typeof(T)))
        {
            T enumValue = (T)o;
            if (GetXmlAttrNameFromEnumValue<T>(enumValue).Equals(value, StringComparison.OrdinalIgnoreCase))
            {
                return (T)o;
            }
        }
    
        throw new ArgumentException("No XmlEnumAttribute code exists for type " + typeof(T).ToString() + " corresponding to value of " + value);
    }
    
    0 讨论(0)
  • 2020-12-15 21:03

    I do something similar with custom attributes and I use this method to get the EnumValue based on the Attribute Value. GetStringValue is my custom method, similar to your example above.

    public static class Enums 
    { 
        public static T GetCode<T>(string value) 
        { 
            foreach (object o in System.Enum.GetValues(typeof(T))) 
            { 
                if (((Enum)o).GetStringValue().Equals(value, StringComparison.OrdinalIgnoreCase))
                    return (T)o; 
            } 
            throw new ArgumentException("No code exists for type " + typeof(T).ToString() + " corresponding to value of " + value); 
        } 
    }  
    

    For the whole process I use check this post and the answers: Extending Enums, Overkill?

    Sorry this is in C#, just realized you were using VB.NET above.

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