如何利用多态反序列化两种仅消息值类型不同的XML?数据结构设计及问题解决
解决相似结构XML的反序列化问题:基于抽象类的多类型消息处理
问题背景
我最近在处理两种结构几乎完全一致的XML,唯一区别是消息节点里的MessageValue_Type_X字段类型不同(一个是数值型,一个是字符串型)。XML示例如下:
<DOCUMENTS> <DOCUMENT> <DOC_NAME>1</DOC_NAME> <messages> <message> <ID>1</ID> <MessageValue_Type_1>22222</MessageValue_Type_1> </message> <message> <ID>2</ID> <MessageValue_Type_1>3333</MessageValue_Type_1> </message> </messages> </DOCUMENT> <DOCUMENT> <DOC_NAME>3</DOC_NAME> <messages> <message> <ID>1</ID> <MessageValue_Type_2>AAAAAAA</MessageValue_Type_2> </message> <message> <ID>2</ID> <MessageValue_Type_2>BBBBB</MessageValue_Type_2> </message> </messages> </DOCUMENT> </DOCUMENTS>
我的目标是用Type_1_Document和Type_2_Document分别反序列化对应的<DOCUMENT>节点,最初设计了基于抽象类的结构,但一直无法完成反序列化,后来调整XML特性配置后解决了问题。
最初的尝试代码
一开始的代码结构试图用抽象基类+子类重写属性的方式实现,但因XML特性配置错误导致反序列化失败:
[XmlRoot("DOCUMENT")] public abstract class Document { [XmlElement("DOC_NAME")] public string DocName { get; set; } [XmlIgnore] public virtual List<GeneralMessage> messages { get; set; } } public class Type_1_Document : Document { [XmlElement("messages")] public new List<Message_Type_1> messages { get; set; } } public class Type_2_Document : Document { [XmlElement("messages")] public new List<Message_Type_2> messages { get; set; } } [XmlRoot("message")] public abstract class GeneralMessage { [XmlElement("ID")] public int ID { get; set; } } [XmlRoot("message")] public class Message_Type_1 : GeneralMessage { [XmlElement("MessageValue_Type_1")] public int valueType_1 { get; set; } } [XmlRoot("message")] public class Message_Type_2 : GeneralMessage { [XmlElement("MessageValue_Type_2")] public int valueType_2 { get; set; } }
问题解决后的正确配置
经过调整,我找到了两个关键修改点,现在可以正常完成反序列化:
- 移除抽象基类上的
[XmlRoot]特性:Document和GeneralMessage是抽象基类,不需要标记[XmlRoot],这个特性应该只作用于实际作为序列化根节点的子类(比如Type_1_Document)。 - 优化属性的XML特性配置:基类
Document的messages用[XmlIgnore]+virtual修饰,子类用new关键字重新定义属性并标记[XmlElement("messages")],确保序列化器能正确识别子类的消息列表类型。
调整后的完整代码:
public abstract class Document { [XmlElement("DOC_NAME")] public string DocName { get; set; } [XmlIgnore] public virtual List<GeneralMessage> Messages { get; set; } } [XmlRoot("DOCUMENT")] public class Type_1_Document : Document { [XmlElement("messages")] public new List<Message_Type_1> Messages { get; set; } } [XmlRoot("DOCUMENT")] public class Type_2_Document : Document { [XmlElement("messages")] public new List<Message_Type_2> Messages { get; set; } } public abstract class GeneralMessage { [XmlElement("ID")] public int ID { get; set; } } public class Message_Type_1 : GeneralMessage { [XmlElement("MessageValue_Type_1")] public int ValueType1 { get; set; } } public class Message_Type_2 : GeneralMessage { [XmlElement("MessageValue_Type_2")] public string ValueType2 { get; set; } }
现在可以正常使用XmlSerializer完成反序列化:
// 反序列化Type_1类型的XML XmlSerializer xmls1 = new XmlSerializer(typeof(Type_1_Document)); var result1 = xmls1.Deserialize(new StringReader(type1XmlText)); // 反序列化Type_2类型的XML XmlSerializer xmls2 = new XmlSerializer(typeof(Type_2_Document)); var result2 = xmls2.Deserialize(new StringReader(type2XmlText));
内容的提问来源于stack exchange,提问作者Guy E
相关产品推荐
相关产品推荐

