2013-09-11 5 views
9

У меня есть перечисление:Получить XmlEnumAttribute от перечисления

public enum Operation { 
    /// <remarks/> 
    [System.Xml.Serialization.XmlEnumAttribute("01")] 
    Item01, 

    /// <remarks/> 
    [System.Xml.Serialization.XmlEnumAttribute("02")] 
    Item02, 

    /// <remarks/> 
    [System.Xml.Serialization.XmlEnumAttribute("03")] 
    Item03, 

    /// <remarks/> 
    [System.Xml.Serialization.XmlEnumAttribute("04")] 
    Item04, 
} 

Как я могу получить значение XmlEnumAttribute?

Я пытаюсь при этом:

var res = Operation.Item1; 
var result = (res.GetType().GetField("Item01").GetCustomAttributes(typeof(XmlEnumAttribute), true)[0] as XmlEnumAttribute).Name; 

Может быть, существует лучший метод?

ответ

7

Вы должны использовать Reflection, чтобы получить значение атрибута:

var value = Operation.Item02; 

var attributeValue = ((XmlEnumAttribute)typeof(Operation) 
         .GetMember(value.ToString())[0] 
         .GetCustomAttributes(typeof(XmlEnumAttribute), false)[0]) 
         .Name; 
+0

Благодаря всем членам – zrabzdn

16

Вы можете создать вспомогательный (статический) класс, с помощью этого метода расширения

public static string GetXmlEnumAttributeValueFromEnum<TEnum>(this TEnum value) where TEnum : struct, IConvertible 
     { 
      var enumType = typeof(TEnum); 
      if (!enumType.IsEnum) return null;//or string.Empty, or throw exception 

      var member = enumType.GetMember(value.ToString()).FirstOrDefault(); 
      if (member == null) return null;//or string.Empty, or throw exception 

      var attribute = member.GetCustomAttributes(false).OfType<XmlEnumAttribute>().FirstOrDefault(); 
      if (attribute == null) return null;//or string.Empty, or throw exception 
      return attribute.Name; 
     } 

использование

var res = Operation.Item1; 
var result = res.GetXmlAttributeValueFromEnum(); 
+0

Это может не работать, если перечисление содержит элемент «Равные», «GetHashCode», «GetType» или «ToString». Вы должны отфильтровать результат enumType.GetMember по MemberType = Поле. – Rauhotz

+0

@ Rauhotz Действительно. Но, я думаю, вы признаете, что это было бы действительно (действительно) конкретный случай (не сказать довольно плохую идею)! –

+0

Я написал этот комментарий, потому что у меня был только этот редкий случай для реляционного оператора перечисления коллеги. – Rauhotz

1

Thanks; это полезно для меня. Я хотел бы расширить ответ Рафаэля на несколько более общий сценарий. Если код перечисления генерируется из xsd с помощью xsd.exe, не каждый атрибут будет иметь атрибут. Это может произойти, если вы используете xsd enums для ограничения строк определенным списком значений, некоторые из которых имеют пробелы, а некоторые из них - нет. Например:

<xs:simpleType name="fooEnum"> 
<xs:restriction base="xs:string"> 
    <xs:enumeration value="Foo Bar" /> 
    <xs:enumeration value="Bar Foo" /> 
    <xs:enumeration value="JustPlainFoo" /> 
</xs:restriction> 
</xs:simpleType> 

испустит C# код сериализации:

public enum fooEnum { 

    /// <remarks/> 
    [System.Xml.Serialization.XmlEnumAttribute("Foo Bar")] 
    FooBar, 

    /// <remarks/> 
    [System.Xml.Serialization.XmlEnumAttribute("Bar Foo")] 
    BarFoo, 

    /// <remarks/> 
    JustPlainFoo, 
} 

В этом случае, код клиента ожидает "JustPlainFoo" потерпит неудачу. Моя версия ответа Рафаэля тогда следующим образом:

public static string XmlEnumToString<TEnum>(TEnum value) where TEnum : struct, IConvertible 
    { 
     Type enumType = typeof(TEnum); 
     if (!enumType.IsEnum) 
      return null; 

     MemberInfo member = enumType.GetMember(value.ToString()).FirstOrDefault(); 
     if (member == null) 
      return null; 

     XmlEnumAttribute attribute = member.GetCustomAttributes(false).OfType<XmlEnumAttribute>().FirstOrDefault(); 
     if (attribute == null) 
      return member.Name; // Fallback to the member name when there's no attribute 

     return attribute.Name; 
    } 

Наконец, отмечу, что commment Rauhotz не будет применяться к этому случаю; XmlEnumAttribute не будет присутствовать в сгенерированном коде C#, и вы просто ударите резервный код.

Смежные вопросы