この問題を解決する方法はいくつかあります。
まず、あなたは、それがこの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
これは役に立ちますか? https://stackoverflow.com/q/18737950/3744182 – dbc
この例では、enum要素の説明を取得しようとしていますが、取得する必要があるのは要素の値ですが、必要ですそれは自己です。手伝って頂けますか? – user3357141