You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OOP多态性实现两类XML反序列化时隐藏基类异常的解决

解决XML多态反序列化中基类属性隐藏的异常问题

我明白你遇到的头疼问题——想用virtual+new的多态思路处理两类结构相似的XML反序列化,结果却因为基类属性的冲突抛出了异常。咱们一步步来把这个问题解决掉:

问题场景回顾

你手头有两类XML,核心差异集中在<MSGDATA>节点的内部结构:

TYPE 1 XML

<MESSAGE>
 <DOCUMENT>
 <MSGHDR>
 <TIME_STAMP>2020010100:00:00.000</TIME_STAMP>
 <MESSAGE_NAME>1</MESSAGE_NAME>
 </MSGHDR>
 <MSGDATA>
 <ITEMSTYPE_1>
 <ITEMTYPE_1>
 <NAME_OF_TYPE_1>TYPE1_AAAA</NAME_OF_TYPE_1>
 </ITEMTYPE_1>
 <ITEMTYPE_1>
 <NAME_OF_TYPE_1>TYPE1_BBBB</NAME_OF_TYPE_1>
 </ITEMTYPE_1>
 </ITEMSTYPE_1>
 </MSGDATA>
 </DOCUMENT>
 <DOCUMENT>
 <MSGHDR>
 <TIME_STAMP>2020010100:00:00.000</TIME_STAMP>
 <MESSAGE_NAME>2</MESSAGE_NAME>
 </MSGHDR>
 <MSGDATA>
 <ITEMSTYPE_1>
 <ITEMTYPE_1>
 <NAME_OF_TYPE_1>TYPE1_EEEEEE</NAME_OF_TYPE_1>
 </ITEMTYPE_1>
 <ITEMTYPE_1>
 <NAME_OF_TYPE_1>TYPE1_FFFFF</NAME_OF_TYPE_1>
 </ITEMTYPE_1>
 </ITEMSTYPE_1>
 </MSGDATA>
 </DOCUMENT>
</MESSAGE>

TYPE 2 XML

<MESSAGE>
 <DOCUMENT>
 <MSGHDR>
 <TIME_STAMP>2020010100:00:00.000</TIME_STAMP>
 <MESSAGE_NAME>1</MESSAGE_NAME>
 </MSGHDR>
 <MSGDATA>
 <ITEMSTYPE_2>
 <ITEMTYPE_2>
 <NAME_OF_TYPE_2>TYPE2_CCCC</NAME_OF_TYPE_2>
 </ITEMTYPE_2>
 <ITEMTYPE_2>
 <NAME_OF_TYPE_2>TYPE2_DDDD</NAME_OF_TYPE_2>
 </ITEMTYPE_2>
 </ITEMSTYPE_2>
 </MSGDATA>
 </DOCUMENT>
</MESSAGE>

你的核心思路是通过抽象基类+子类继承,用new关键字覆盖基类的Documents属性来适配不同的DOCUMENT类型,但反序列化时直接触发了隐藏基类的异常。

问题根源

XmlSerializer会扫描类的所有继承层级属性,哪怕你用new关键字“隐藏”了基类属性,只要基类的属性没标记[XmlIgnore],序列化器就会同时识别基类和子类的Documents属性,直接导致属性重复的冲突。

解决方案

在抽象基类的虚拟属性上添加[XmlIgnore],明确告诉序列化器忽略基类的这个属性,只处理子类中用new重新定义的属性。这样既保留了多态的结构,又能让序列化器正常工作。

修正后的完整代码

基类与TYPE1相关实现

[XmlRoot("MESSAGE")]
public abstract class ItemMessage {
    [XmlIgnore] // 关键:标记为XmlIgnore,避免序列化器识别该属性
    public virtual List<ItemDocument> Documents { get; set; }
}

[XmlRoot("MESSAGE")]
public class Item_1_Message : ItemMessage {
    [XmlElement("DOCUMENT")] // 子类重新定义属性,绑定XML元素名
    public new List<Type_1_ItemDocument> Documents { get; set; }
}

[XmlRoot(ElementName="MSGHDR")]
public class MsgHeader {
    [XmlElement("TIME_STAMP")]
    public string strTimeStamp { get; set; }
    [XmlElement("MESSAGE_NAME")]
    public string MessageName { get; set; }
}

[XmlRoot("DOCUMENT")]
public abstract class ItemDocument {
    [XmlElement("MSGHDR")]
    public MsgHeader MsgHeader { get; set; }
}

// TYPE1 专属数据类
public class Type_1_ItemDocument : ItemDocument {
    [XmlElement("MSGDATA")]
    public Type_1_ItemData itemData { get; set; }
}

[XmlRoot(ElementName = "MSGDATA")]
public class Type_1_ItemData {
    [XmlElement(ElementName = "ITEMSTYPE_1")]
    public ItemsType_1 itemstype1 { get; set; }
}

[XmlRoot(ElementName = "ITEMSTYPE_1")]
public class ItemsType_1 {
    [XmlElement("ITEMTYPE_1")]
    public List<Item1> items { get; set; }
}

[XmlRoot(ElementName = "ITEMTYPE_1")]
public class Item1 {
    [XmlElement(ElementName = "NAME_OF_TYPE_1")]
    [JsonProperty("Name")]
    public string name { get; set; }
}

TYPE2相关实现(补充完整供参考)

[XmlRoot("MESSAGE")]
public class Item_2_Message : ItemMessage {
    [XmlElement("DOCUMENT")]
    public new List<Type_2_ItemDocument> Documents { get; set; }
}

public class Type_2_ItemDocument : ItemDocument {
    [XmlElement("MSGDATA")]
    public Type_2_ItemData itemData { get; set; }
}

[XmlRoot(ElementName = "MSGDATA")]
public class Type_2_ItemData {
    [XmlElement(ElementName = "ITEMSTYPE_2")]
    public ItemsType_2 itemstype2 { get; set; }
}

[XmlRoot(ElementName = "ITEMSTYPE_2")]
public class ItemsType_2 {
    [XmlElement("ITEMTYPE_2")]
    public List<Item2> items { get; set; }
}

[XmlRoot(ElementName = "ITEMTYPE_2")]
public class Item2 {
    [XmlElement(ElementName = "NAME_OF_TYPE_2")]
    [JsonProperty("Name")]
    public string name { get; set; }
}

反序列化验证

现在你可以正常执行以下代码反序列化TYPE1 XML:

XmlSerializer xmls = new XmlSerializer(typeof(Item_1_Message));
var result = xmls.Deserialize(new StringReader(xmlText));

处理TYPE2 XML时,只需要把typeof(Item_1_Message)替换为typeof(Item_2_Message)即可。

额外说明

这种方案既保留了OOP多态的优势(你可以用ItemMessage作为统一基类处理不同消息),又完美解决了XmlSerializer的属性冲突问题。后续如果新增其他类型的XML,只需要继承ItemMessage和ItemDocument,重新定义对应的属性和数据类即可,扩展性拉满。

内容的提问来源于stack exchange,提问作者Guy E

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:07:28