根据XmlEnumAttribute名称值检索枚举值

我需要一个Generic函数来根据枚举的XmlEnumAttribute“Name”属性检索枚举的名称或值。 例如,我定义了以下枚举:

Public Enum Currency  CDN = 1  USA= 2  EUR= 3  JPN= 4 End Enum 

第一个Currency枚举值为1; 枚举名称是“CDN”; 并且XMLEnumAttribute Name属性值为“00”。

如果我有枚举值,我可以使用以下通用函数检索XmlEnumAttribute“Name”值:

 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 

因此,使用上面的函数,我可以指定Currency枚举类型,传递值1,返回值将为“00”。

我需要的是一个相反的function。 如果我有XmlEnumAttribute Name值“00”,我需要一个函数来返回值为1的Currency枚举。同样有用的是一个返回枚举名称“CDN”的函数。 然后我可以简单地解析它以获得枚举值。

任何援助将不胜感激。

解决这个完全相同问题的要求使我得到了这个问题和答案。 当我在VB.NET中开发时,我将CkH的解决方案重写为VB并将其修改为使用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 

C#版本:

 public static string GetXmlAttrNameFromEnumValue(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(string value) { // http://stackoverflow.com/a/3073272/194717 foreach (object o in System.Enum.GetValues(typeof(T))) { T enumValue = (T)o; if (GetXmlAttrNameFromEnumValue(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); } 

我使用自定义属性执行类似操作,并使用此方法根据属性值获取EnumValue。 GetStringValue是我的自定义方法,类似于上面的示例。

 public static class Enums { public static T GetCode(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); } } 

对于整个过程,我使用检查这篇文章和答案: 扩展枚举,矫枉过正?

对不起,这是在C#中,只是意识到你上面使用的是VB.NET。

略有修改自: 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; } 

这是一个从枚举中生成字典的变体,如果您需要大量使用它,可以使用它来隐藏它的reflection部分。

 ///  /// 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 ///  /// The xml enum type you want the mapping for /// Mapping dictionary from attribute values (key) to the actual enum values /// T must be an enum private static Dictionary GetEnumMap() 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(); 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(); return map["02"]; // returns Currency.EUR 

@Dean,@ Jason和@Camron,感谢您的解决方案。 您的解决方案帮助我解决了我的问题,在给定XmlEnumAttribute名称的情况下,需要实际的枚举值。

我的变体在这里提到。

我也按照我们的一位主持人的要求将其包括在内:

实际问题是如何获取Item10,当给定值为10.从上面提到的朋友引用的解决方案中提取一个提示时,我提出了以下方法,当传递XmlEnumAttribute中包含的值时,将返回枚举值:

 private static T GetEnumValueFromXmlAttrName(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; }