C# 通过发送XmlEnumAttribute c获取枚举的元素?

C# 通过发送XmlEnumAttribute c获取枚举的元素?,c#,xml,enums,C#,Xml,Enums,我通常不必问问题,因为大多数时候我都在网上找到我需要的东西,但现在我还没有找到一种方法来获得: 假设我在这个枚举中有50000个枚举元素: public enum myEnum { [System.Xml.Serialization.XmlEnumAttribute("01010101")] Item01010101, [System.Xml.Serialization.XmlEnumAttribute("10101500")] Item10101500 } 例如,我试

我通常不必问问题,因为大多数时候我都在网上找到我需要的东西,但现在我还没有找到一种方法来获得:

假设我在这个枚举中有50000个枚举元素:

public enum myEnum
{
   [System.Xml.Serialization.XmlEnumAttribute("01010101")]
   Item01010101,
   [System.Xml.Serialization.XmlEnumAttribute("10101500")]
   Item10101500
}
例如,我试图通过传递元素的XmlEnumAttribute的字符串值来获取元素值

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;
}
有没有一种不用switch语句就可以实现的方法?
我希望你能帮助我,谢谢。

你有几种方法可以解决这个问题

首先,您可以使用反射,使用typeofTEnum.GetFieldsBindingFlags.Public | BindingFlags.Static循环遍历所有枚举值,其操作方式与此类似:

XmlSerializer将从值myFlagsEnum.Zero | myFlagsEnum.One生成以下组合字符串,该字符串不能完全通过反射找到:Flag0 Flag1。当多个XmlEnumAttribute属性应用于给定的枚举值时,或者只有一些枚举值应用了XmlEnumAttribute时,应该发生什么也不清楚

要处理所有可能的边缘情况,包括上述情况,我建议使用以下第二种方法直接反序列化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; }
}

示例。

谢谢dbc第一个方法非常适合我需要做的事情:我非常感谢你的帮助,我创建了这个类:

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);
        }
    }
}
然后我从reflectedXMLValue调用方法,如下所示:

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

这有用吗?我在那个例子中看到的是,他们试图获取enum元素的描述,我需要获取元素的值,但我需要元素本身。你能帮助我吗?
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; }
}
obj.ItsEnumValue = "01010101".FromXmlValue<myEnum>();
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);
        }
    }
}
var obj4 = XmlEnumExtensions.FromReflectedXmlValue<myEnum>("theXmlAtributeValue");