2010-06-15 6 views
17

पर आधारित enum मान पुनर्प्राप्त करें मुझे enum की XmlEnumAttribute "Name" प्रॉपर्टी के आधार पर एनम के नाम या मान को पुनर्प्राप्त करने के लिए जेनेरिक फ़ंक्शन की आवश्यकता है। उदाहरण के लिए मेरे पास निम्न enum परिभाषित है:XmlEnumAttribute नाम मान

Public Enum Currency 
    <XmlEnum("00")> CDN = 1 
    <XmlEnum("01")> USA= 2 
    <XmlEnum("02")> EUR= 3 
    <XmlEnum("03")> JPN= 4 
End Enum 

पहला मुद्रा एनम मान 1 है; enum नाम "सीडीएन" है; और XMLEnumAttribute नाम संपत्ति मान "00" है।

अगर मैं enum मूल्य है, मैं XmlEnumAttribute "नाम" मूल्य निम्नलिखित सामान्य समारोह का उपयोग कर प्राप्त कर सकते हैं:

Public Function GetXmlAttrNameFromEnumValue(Of T)(ByVal pEnumVal As T) As String 

     Dim type As Type = pEnumVal.GetType 
     Dim info As FieldInfo = type.GetField([Enum].GetName(GetType(T), pEnumVal)) 
     Dim att As XmlEnumAttribute = CType(info.GetCustomAttributes(GetType(XmlEnumAttribute), False)(0), XmlEnumAttribute) 'If there is an xmlattribute defined, return the name 

     Return att.Name 
    End Function 

तो ऊपर समारोह का उपयोग कर, मैं मुद्रा enum प्रकार निर्दिष्ट कर सकते हैं, एक मूल्य के पारित 1 का, और वापसी मूल्य "00" होगा।

मुझे जो चाहिए वह विपरीत है यदि प्रदर्शन करने के लिए एक फ़ंक्शन है। यदि मेरे पास XmlEnumAttribute नाम मान "00" है, तो मुझे 1 के मान के साथ एक मुद्रा enum वापस करने के लिए एक फ़ंक्शन की आवश्यकता है। जैसे ही उपयोगी एक ऐसा फ़ंक्शन होगा जो enum name "सीडीएन" वापस कर देगा। मैं enum मूल्य प्राप्त करने के लिए बस इसे पार्स कर सकता था।

किसी भी सहायता की सराहना की जाएगी।

उत्तर

17

इस सटीक समस्या को हल करने की आवश्यकता ने मुझे इस प्रश्न और उत्तर का नेतृत्व किया। जैसा कि मैं वीबीएनईटी में विकसित करता हूं, मैं वीबी में सीकेएच के समाधान को फिर से लिखता हूं और इसे आपके GetXmlAttrNameFromEnumValue फ़ंक्शन का उपयोग करने के लिए संशोधित करता हूं।

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 

सी # संस्करण:

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

आपकी प्रतिक्रिया के लिए धन्यवाद। – Dean

+0

आप 'टी टी: स्ट्रक्चर' को 'गेटकोड ' -method के लिए बाधा के रूप में जोड़ने पर विचार कर सकते हैं, क्योंकि जब तक मेरा ज्ञान नहीं जाता है, तब तक एक enum कभी संदर्भ प्रकार नहीं होगा।(Enums के अलावा अन्य स्ट्रक्चर पारित करने में सक्षम हो जाएगा, लेकिन यह अभी भी एक अच्छा थोड़ा सुधार IMHO है) –

7

मैं कस्टम विशेषताओं के साथ कुछ करता हूं और मैं विशेषता मूल्य के आधार पर EnumValue प्राप्त करने के लिए इस विधि का उपयोग करता हूं। GetStringValue उपरोक्त आपके उदाहरण के समान, मेरी कस्टम विधि है।

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

पूरी प्रक्रिया मैं इस पोस्ट और जवाब की जाँच का उपयोग करें: Extending Enums, Overkill?

क्षमा करें यह सी # में है, बस एहसास हुआ कि आप ऊपर VB.NET का उपयोग कर रहे थे।

+0

आपकी प्रतिक्रिया के लिए धन्यवाद। – Dean

1

@Dean, @Jason और @Camron, अपने समाधान के लिए धन्यवाद। आपके समाधान ने मेरी समस्या को हल करने में मेरी मदद की, जहां, XmlEnumAttribute नाम दिया गया, वास्तविक enum मान की आवश्यकता थी।

मेरा संस्करण here का उल्लेख किया गया है।

3

थोड़ा से संशोधित: 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; 
} 
1

यहाँ विभिन्नता कि enum से एक शब्दकोश उत्पन्न करता है, होना चाहिए कि आप इसे एक बहुत उपयोग करने की आवश्यकता संभवतः इसके बारे में प्रतिबिंब हिस्सा कैश करने के लिए आप की अनुमति देता है है।

/// <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; 
} 

उपयोग:

var map = GetEnumMap<Currency>(); 
return map["02"]; // returns Currency.EUR 
संबंधित मुद्दे