2017-03-24 13 views
1

私はいつもインターネットで必要なものを見つけるために質問をする必要はありませんが、今私はこれを得る方法を見つけることができません:XmlEnumAttribute C#を送信して列挙の要素を取得しますか?

この列挙体に50000列挙型の要素があるとします:

public enum myEnum 
{ 
    [System.Xml.Serialization.XmlEnumAttribute("01010101")] 
    Item01010101, 
    [System.Xml.Serialization.XmlEnumAttribute("10101500")] 
    Item10101500 
} 

私は何をしようとしていますが例

object.ItsEnumValue = getEnumElement("01010101"); 

// Function which will return the element of the enum. 
public myEnum getEnumElement(string xmlAttributeValue) 
{ 
    // The function should return the enum element, not using a switch statement 
    return myEnum.Item01010101; 
} 

のために、要素のXmlEnumAttributeの文字列値を渡すことで、要素の値を取得することでスイッチせずにこれを行う方法はありますステートメント? おかげさまで助けてくれれば幸いです。

+0

これは役に立ちますか? https://stackoverflow.com/q/18737950/3744182 – dbc

+0

この例では、enum要素の説明を取得しようとしていますが、取得する必要があるのは要素の値ですが、必要ですそれは自己です。手伝って頂けますか? – user3357141

答えて

2

この問題を解決する方法はいくつかあります。

まず、あなたは、それがこのthis answerで行う方法と同様にtypeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static)を使用して、すべての列挙型の値を循環にリフレクションを使用することができます。

public static partial class XmlEnumExtensions 
{ 
    public static TEnum FromReflectedXmlValue<TEnum>(this string xml) where TEnum : struct, IConvertible, IFormattable 
    { 
     // Adapted from https://stackoverflow.com/questions/35294530/c-sharp-getting-all-enums-value-by-attribute 
     var obj = (from field in typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static) 
        from attr in field.GetCustomAttributes<XmlEnumAttribute>() 
        where attr != null && attr.Name == xml 
        select field.GetValue(null)).SingleOrDefault(); 
     if (obj != null) 
      return (TEnum)obj; 

     // OK, maybe there is no XmlEnumAttribute override so match on the name. 
     return (TEnum)Enum.Parse(typeof(TEnum), xml, false); 
    } 
} 

次にようにそれを使用します、しかし

obj.ItsEnumValue = "01010101".FromReflectedXmlValue<myEnum>(); 

[Flags]属性が適用されている場合、これは機能しません。例えば、次の列挙所与:Flag0 Flag1:値myFlagsEnum.Zero | myFlagsEnum.Oneから

[Flags] 
public enum myFlagsEnum 
{ 
    [System.Xml.Serialization.XmlEnumAttribute("Flag0")] 
    Zero = (1 << 0), 
    [System.Xml.Serialization.XmlEnumAttribute("Flag1")] 
    One = (1 << 1), 
} 

XmlSerializer反射によって純粋に見つけることができない、次の組み合わせの文字列を、生成します。また、複数のXmlEnumAttribute属性が特定の列挙型の値に適用された場合、または列挙型の値の一部だけがXmlEnumAttributeが適用された場合に何が起こるべきかは明確ではありません。

上記を含め、すべての可能なエッジケースを扱うために、私は単にには、次の第2の方法を使用して、直接 XMLをデシリアライズを示唆している:

public static partial class XmlExtensions 
{ 
    static XmlExtensions() 
    { 
     noStandardNamespaces = new XmlSerializerNamespaces(); 
     noStandardNamespaces.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd attributes. 
    } 

    readonly static XmlSerializerNamespaces noStandardNamespaces; 
    internal const string RootNamespace = "XmlExtensions"; 
    internal const string RootName = "Root"; 

    public static TEnum FromXmlValue<TEnum>(this string xml) where TEnum : struct, IConvertible, IFormattable 
    { 
     var element = new XElement(XName.Get(RootName, RootNamespace), xml); 
     return element.Deserialize<XmlExtensionsEnumWrapper<TEnum>>().Value; 
    } 

    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null) 
    { 
     using (var reader = element.CreateReader()) 
     { 
      object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); 
      if (result is T) 
       return (T)result; 
     } 
     return default(T); 
    } 

    public static string ToXmlValue<TEnum>(this TEnum value) where TEnum : struct, IConvertible, IFormattable 
    { 
     var root = new XmlExtensionsEnumWrapper<TEnum> { Value = value }; 
     return root.SerializeToXElement().Value; 
    } 

    public static XElement SerializeToXElement<T>(this T obj) 
    { 
     return obj.SerializeToXElement(null, noStandardNamespaces); // Disable the xmlns:xsi and xmlns:xsd attributes by default. 
    } 

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer, XmlSerializerNamespaces ns) 
    { 
     var doc = new XDocument(); 
     using (var writer = doc.CreateWriter()) 
      (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj, ns); 
     var element = doc.Root; 
     if (element != null) 
      element.Remove(); 
     return element; 
    } 
} 

[XmlRoot(XmlExtensions.RootName, Namespace = XmlExtensions.RootNamespace)] 
[XmlType(IncludeInSchema = false)] 
public class XmlExtensionsEnumWrapper<TEnum> 
{ 
    [XmlText] 
    public TEnum Value { get; set; } 
} 

これは、すべての場合においてXmlSerializerとの互換性を保証して - 実際に使用してそれ。その後、同様の操作を行います。

obj.ItsEnumValue = "01010101".FromXmlValue<myEnum>(); 

サンプルfiddleを。

public static partial class XmlEnumExtensions 
{ 
    public static Nullable<TEnum> FromReflectedXmlValue<TEnum>(this string xml) where TEnum : struct, IConvertible, IFormattable 
    { 
     try 
     { 
      var obj = (from field in typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static) 
         from attr in field.GetCustomAttributes<XmlEnumAttribute>() 
         where attr != null && attr.Name == xml 
         select field.GetValue(null)).SingleOrDefault(); 
      if (obj != null) 
       return (TEnum)obj; 
      // OK, maybe there is no XmlEnumAttribute override so match on the name. 
      return (TEnum)Enum.Parse(typeof(TEnum), xml, false); 

     } 
     catch (ArgumentException ex) 
     { 
      throw new ApplicationException("Error: " + ex.Message); 
     } 
    } 
} 

そして私はちょうどこのような方法FromReflectedXmlValue呼び出す:第1の方法は、私は本当にあなたの助けに感謝:)、私は何をする必要があるかのために完璧に動作DBC

0

おかげで、私はこのクラスを作成し

var obj4 = XmlEnumExtensions.FromReflectedXmlValue<myEnum>("theXmlAtributeValue"); 
+0

完了:).... – user3357141

関連する問題