2011-06-09 39 views
9

Tôi cần phải phân tích cú pháp tệp XML mà tôi nhận được từ bên thứ ba thành đối tượng C#. Một số XML tôi nhận được có các giá trị liệt kê mà tôi muốn lưu trữ trong một loại enum.Ánh xạ giá trị xml vào loại enum

Ví dụ, tôi đã có xsd sau của tập tin xml:

<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> 

Tôi muốn bản đồ này để một enum và tôi đã nhận này cho đến nay:

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

Vấn đề tôi có là xml có thể chứa một giá trị của 3 mà tôi dường như không thể đặt vào loại enum. Có giải pháp nào để đặt giá trị này trong enum không.

Tôi cũng có thể nhận các giá trị khác với - hoặc / trong đó và tôi muốn đặt vào loại enum.
Đề xuất Anu được hoan nghênh!

+0

Tôi làm theo các liên kết dưới đây và tôi thấy nó hữu ích. [Trong C#, deserializing enums từ số nguyên.] (Http://stackoverflow.com/questions/9944421/c-sharp-deserializing-enums-from-integers/33387055#33387055) –

Trả lời

15

Bạn có thể phân tích các giá trị thuộc tính xml trở lại một kiểu enum với:

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

Nhưng tôi không nghĩ rằng bạn sẽ nhận được thực sự xa với các giá trị "đặc biệt" của bạn (3, a/ vv). Tại sao bạn không xác định enum của mình là

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

Và viết phương pháp tĩnh để chuyển đổi chuỗi thành thành viên enum? Một điều bạn có thể xem xét để thực hiện phương pháp như vậy là thêm thuộc tính tùy chỉnh vào các thành viên enum chứa biểu diễn chuỗi của chúng - nếu một giá trị không có đối tác chính xác trong điều tra, hãy tìm một thành viên với thuộc tính.

Tạo một thuộc tính như vậy là dễ dàng:

/// <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; 
    } 
} 

Và sau đó bạn có thể sử dụng chúng trong enum của bạn:

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

Hai phương pháp này sẽ giúp bạn phân tích một chuỗi thành một thành viên enum của bạn lựa chọn:

/// <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; 
    } 

Và trong khi tôi ở đó: đây là cách khác vòng;)

/// <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

Vấn đề là ánh xạ các giá trị enum không chuẩn (như "3"). –

+0

Cảm ơn câu trả lời. Tôi sẽ cố gắng này và lấy lại cho bạn! – Gerard

+1

Nó hoạt động, cảm ơn bạn đã phản hồi! – Gerard

0

Tôi tạo ra một lớp học mà xử lý này:

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; 
     } 
    } 

Bạn phải đọc file xml đầu tiên và đặt các giá trị trong một danh sách, bạn có thể làm điều này với đối tượng XElement ví dụ.

// Edit: Như thế này:

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

chờ đợi, đây không phải là vấn đề. Không @ làm việc? như @ 3, @ /, v.v. tôi biết nó hoạt động với các từ khóa như int và double. – hcb

3

Tại sao bạn không thể phân tích chuỗi

[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; } 
} 

Vì vậy, bạn thực sự serialize nó như là một chuỗi.

11

trang trí với các thuộc tính 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

Được xé toạc đầu để hiểu tại sao tôi không thể đánh dấu các lĩnh vực lớp học như [XmlEnum] cuối cùng đã tìm thấy câu trả lời của bạn và lưu lại phần còn lại của mái tóc của tôi. tất cả các lựa chọn thay thế khác là "bẩn" nếu bạn hỏi tôi –

Các vấn đề liên quan