使用变体子代反序列化XML

时间:2015-05-21 01:49:01

标签: c# xml class object deserialization

我有一个设备可以随机通过TCP生成6种不同类型的XML通知。我已经成功地将通知反序列化了;但是,1个特定的通知,事件,我需要一些关于如何更有效地处理它的建议。

以下是3/36事件通知示例:

Example 1
<event>
  <property1>721695632</property1>
  <property2>266</property2>
  <class1>
   <property31>dirk</property31>
   <property32>192.168.1.110</property32>
   <property33>fx</property33>
  </class1>
</event>  

Example 2
<event>
  <property1>721555130</property1>
  <property2>263</property2>
  <class2>
    <property41>00-00-00-00-00-00-00-00</property41>
    <property42>569</property42>
  </class2>
</event>

Example 3
<event>
 <property1>724342931</property1>
 <property2>326</property2>
 <class3>
  <property51>23</property51>
  <property52>00-00-00-00-00-00-00-02</property52>
  <property53>100.00</property53>
  <property54>0000AF72B7C12094EE833326234</property54>
 </class3>
</event>

事件通知之间唯一的共同点是根节点以及property1和property2节点。其余节点在不同事件之间变化。为了反序列化事件通知,我创建了以下类:

public class Event
{
    public ulong Property1 {get; set;}
    public int Property2 {get; set;}

    public class1 Property3 {get; set;}
    public class2 Property4 {get; set;}
    public class3 Property5 {get; set;}

}

public class1 
{   
    public string Property31 {get; set;}
    public string Property32 {get; set;}
    public string Property32 {get; set;}
}

public class2 
{   
    public string Property41 {get; set;}
    public int Property42 {get; set;}
}

public class3
{   
    public int Property51 {get; set;}
    public string Property52 {get; set;}
    public double Property53 {get; set;}
    public string Property54 {get; set;}
}

我使用事件类反序列化事件通知。反序列化后,我遍历事件类中的所有属性以搜索属性!= null。总共有3个非null属性。 Property1和Property2总是保证不为null,并且属性3,4或5不为null。非null属性将传递给此新类:

public class EventResult
{
    public ulong Property1 {get; set;}
    public int Property2 {get; set;}
    public Object EventType {get; set;}
}

现在我有一个漂亮而又整洁的类,只有有效的属性。

这是我正在努力改进的。我想摆脱循环部分,并将事件通知反序列化为只有有效属性的正确对应类。

public class Event1
{
    public ulong Property1 {get; set;}
    public int Property2 {get; set;}
    public class1 Event {get; set;}
}

public class Event2
{
    public ulong Property1 {get; set;}
    public int Property2 {get; set;}
    public class2 Event {get; set;}
}

public class Event3
{
    public ulong Property1 {get; set;}
    public int Property2 {get; set;}
    public class3 Event {get; set;}
}

我以为我可以使用EventResult类反序列化事件通知;但是,我认为这不会起作用,因为对于class1,class2和class3,XMLElement属性是不同的。

感谢您对此主题的任何帮助或讨论。

提前致谢。

2 个答案:

答案 0 :(得分:0)

您可以通过使用多个[XmlElement(String, Type)]属性修饰EventResult属性,直接反序列化到public Object EventType { get; set; }类,而不需要任何中间类,每个属性对应object的每个属性一个可能会遇到属性值,给出要用于每个的元素名称:

[XmlRoot("event")]
public class EventResult
{
    [XmlElement("property1")]
    public ulong Property1 { get; set; }
    [XmlElement("property2")]
    public int Property2 { get; set; }

    [XmlElement("class1", typeof(class1))]
    [XmlElement("class2", typeof(class2))]
    [XmlElement("class3", typeof(class3))]
    public Object EventType { get; set; }
}

然后可以一步反序化所有三个示例XML文件。

为安全起见,我建议

  1. 使所有EventType类继承自某个基类或接口,或
  2. EventType的设置器中,确保传入的value是已知类型之一。如果没有,请抛出ArgumentException

答案 1 :(得分:0)

让类继承Event类

    [XmlInclude(typeof(class1))]
    [XmlInclude(typeof(class2))]
    [XmlInclude(typeof(class3))]
    [Serializable]
    [XmlRoot(ElementName = "event")]
    public class Event
    {
        [XmlElement("property1")]
        public ulong Property1 {get; set;}
        [XmlElement("property2")]
        public int Property2 { get; set; }
    }

    [Serializable]
    [XmlRoot(ElementName = "class1")]
    public class class1 : Event 
    {
        [XmlElement("property31")]
        public string Property31 { get; set; }
        [XmlElement("property32")]
        public string Property32 { get; set; }
        [XmlElement("property33")]
        public string Property33 { get; set; }
    }

    [Serializable]
    [XmlRoot(ElementName = "class2")]
    public class class2 : Event 
    {
        [XmlElement("property41")]
        public string Property41 { get; set; }
        [XmlElement("property42")]
        public int Property42 { get; set; }
    }

    [Serializable]
    [XmlRoot(ElementName = "class3")]
    public class class3 : Event
    {
        [XmlElement("property51")]
        public int Property51 { get; set; }
        [XmlElement("property52")]
        public string Property52 { get; set; }
        [XmlElement("property53")]
        public double Property53 { get; set; }
        [XmlElement("property54")]
        public string Property54 { get; set; }
    }​