2011-06-09 278 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