2011-06-09 234 views
9

我需要解析从第三方获取的C#对象的XML文件。 我收到的一些XML具有枚举值,我想以enum类型存储。将xml值映射到枚举类型

举例来说,我已经得到了XML文件的XSD如下:

<xsd:simpleType name="brandstof"> 
    <xsd:restriction base="xsd:string"> 
    <!-- Benzine --> 
    <xsd:enumeration value="B" /> 
    <!-- Diesel --> 
    <xsd:enumeration value="D" /> 
    <!-- LPG/Gas --> 
    <xsd:enumeration value="L" /> 
    <!-- LPG G3 --> 
    <xsd:enumeration value="3" /> 
    <!-- Elektrisch --> 
    <xsd:enumeration value="E" /> 
    <!-- Hybride --> 
    <xsd:enumeration value="H" /> 
    <!-- Cryogeen --> 
    <xsd:enumeration value="C" /> 
    <!-- Overig --> 
    <xsd:enumeration value="O" /> 
    </xsd:restriction> 
</xsd:simpleType> 

我想这映射到一个枚举,我得到了这么远:

public enum Fuel 
{ 
    B, 
    D, 
    L, 
    E, 
    H, 
    C, 
    O 
} 

这个问题我有xml可以包含值我3,我似乎无法放入枚举类型。有没有解决方案将这个值放入枚举中。

我也可以在其中获得其他值,其中-/在其中并且我想将它们放在枚举类型中。
欢迎来到Anu的建议!

+0

我按照下面的链接,我觉得它有用。 [在C#中,从整数反序列化枚举。](http://stackoverflow.com/questions/9944421/c-sharp-deserializing-enums-from-integers/33387055#33387055) – 2015-10-28 09:26:51

回答

15

您可以解析XML属性值回枚举类型:

var value = Enum.Parse(typeof(Fuel), "B"); 

但我不认为你会得到真正的远与你的“特殊”的价值观(3a/等)。 你为什么不定义枚举为

enum Fuel 
{ 
    Benzine, 
    Diesel, 
    // ... 
    Three, 
    ASlash, 
    // ... 
} 

,写一个静态方法将字符串转换为一个枚举成员?

为了实现这样一种方法,你可以考虑一件事是向包含它们的字符串表示形式的枚举成员添加自定义属性 - 如果一个值在枚举中没有确切的对应关系,则查找带有属性。

创建这样的属性是很容易:

/// <summary> 
/// Simple attribute class for storing String Values 
/// </summary> 
public class StringValueAttribute : Attribute 
{ 
    public string Value { get; private set; } 

    public StringValueAttribute(string value) 
    { 
     Value = value; 
    } 
} 

然后你可以用它们在你的枚举:

enum Fuel 
{ 
    [StringValue("B")]   
    Benzine, 
    [StringValue("D")] 
    Diesel, 
    // ... 
    [StringValue("3")] 
    Three, 
    [StringValue("/")] 
    Slash, 
    // ... 
} 

这两种方法将帮助您解析字符串转换的枚举成员的您选择:

/// <summary> 
    /// Parses the supplied enum and string value to find an associated enum value (case sensitive). 
    /// </summary> 
    public static object Parse(Type type, string stringValue) 
    { 
     return Parse(type, stringValue, false); 
    } 

    /// <summary> 
    /// Parses the supplied enum and string value to find an associated enum value. 
    /// </summary> 
    public static object Parse(Type type, string stringValue, bool ignoreCase) 
    { 
     object output = null; 
     string enumStringValue = null; 

     if (!type.IsEnum) 
     { 
      throw new ArgumentException(String.Format("Supplied type must be an Enum. Type was {0}", type)); 
     } 

     //Look for our string value associated with fields in this enum 
     foreach (FieldInfo fi in type.GetFields()) 
     { 
      //Check for our custom attribute 
      var attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[]; 
      if (attrs != null && attrs.Length > 0) 
      { 
       enumStringValue = attrs[0].Value; 
      }      

      //Check for equality then select actual enum value. 
      if (string.Compare(enumStringValue, stringValue, ignoreCase) == 0) 
      { 
       output = Enum.Parse(type, fi.Name); 
       break; 
      } 
     } 

     return output; 
    } 

虽然我在这里:这是另一种方式;)

/// <summary> 
    /// Gets a string value for a particular enum value. 
    /// </summary> 
    public static string GetStringValue(Enum value) 
    { 
     string output = null; 
     Type type = value.GetType(); 

     if (StringValues.ContainsKey(value)) 
     { 
      output = ((StringValueAttribute) StringValues[value]).Value; 
     } 
     else 
     { 
      //Look for our 'StringValueAttribute' in the field's custom attributes 
      FieldInfo fi = type.GetField(value.ToString()); 
      var attributes = fi.GetCustomAttributes(typeof(StringValueAttribute), false); 
      if (attributes.Length > 0) 
      { 
       var attribute = (StringValueAttribute) attributes[0]; 
       StringValues.Add(value, attribute); 
       output = attribute.Value; 
      } 

     } 
     return output; 

    } 
+2

问题是映射非标准枚举值(如“3”)。 – 2011-06-09 13:24:43

+0

感谢您的回答。我会试试看,并回复你! – Gerard 2011-06-09 13:46:44

+1

它工作,谢谢你的详细回应! – Gerard 2011-06-10 07:18:20

0

我创建了一个类来处理它:

class EnumCreator 
    { 
     public static Type CreateEnum(List<string> AValues) 
     { 
      // Get the current application domain for the current thread. 
      AppDomain currentDomain = AppDomain.CurrentDomain; 

      // Create a dynamic assembly in the current application domain, 
      // and allow it to be executed and saved to disk. 
      AssemblyName aName = new AssemblyName("TempAssembly"); 
      AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
       aName, AssemblyBuilderAccess.RunAndSave); 

      // Define a dynamic module in "TempAssembly" assembly. For a single- 
      // module assembly, the module has the same name as the assembly. 
      ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");  

      // Define a public enumeration with the name "Elevation" and an 
      // underlying type of Integer. 
      EnumBuilder eb = mb.DefineEnum("EnumValues", TypeAttributes.Public, typeof(int)); 

      // Define two members, "High" and "Low". 
      foreach (string v in AValues) 
      { 
       eb.DefineLiteral(v, AValues.IndexOf(v)); 
      } 

      // Create the type and save the assembly. 
      Type finished = eb.CreateType(); 

      return finished; 
     } 
    } 

你必须先读取XML文件,并把该值在列表中,你可以使用的XElement对象例如做到这一点。

//编辑: 像这样:

XElement xml = XElement.parse("file.xml"); 
List<string> enumItems = new List<string>(); 

foreach(XElement row in xml.Element("xsd:simpleType").Element("xsd:restriction").Elements()) 
{ 
    enumItems.Add(row.Attribute("value").Value); 
} 

Type Fuel = EnumCreator.CreatEnum(enumItems); 
+0

等,这不是问题。不@工作?像@ 3,@ /等,我知道它适用于像int和double这样的关键字。 – hcb 2011-06-09 13:34:23

3

你为什么不能解析字符串

[XmlAttribute("brandstof")] 
public string FuelTypeString 
{ 
    get { return fuel.ToString(); } 
    set 
    { 
     fuel = (Fuel)System.Enum.Parse(typeof(Fuel), value); 
    } 
} 
[XmlIgnore()] 
public Fuel FuelType 
{ 
    get { return fuel; } 
    set { fuel = value; } 
} 

让您真正序列化作为一个字符串。

11

装饰与XmlEnum属性:http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlenumattribute.aspx

public enum Fuel 
{ 
    [XmlEnum("B")] 
    Benzine, 
    [XmlEnum("D")] 
    Diesel, 
    [XmlEnum("L")] 
    LpgGas, 
    [XmlEnum("3")] 
    LpgG3, 
    [XmlEnum("E")] 
    Elektrisch, 
    [XmlEnum("H")] 
    Hybride, 
    [XmlEnum("C")] 
    Cryogeen, 
    [XmlEnum("O")] 
    Overig 
} 
+2

一直在撕裂我的头脑,理解为什么我无法将班级字段标记为[XmlEnum],最终找到了答案并为我自己留下了余下的头发。如果你问我,所有其他的选择都是“脏”的 – 2016-04-19 14:27:50