C#反序列化含派生类的XML时出现异常,求排查解决
解决XML反序列化抽象基类的异常问题
你遇到的这个运行时异常,核心问题出在Job类中Pages属性的XML序列化特性配置和你的XML结构不匹配,具体来说:
你的Job类里给Pages属性标记了[XmlElement],这个特性会告诉XmlSerializer:把List中的每个PageBase派生类实例,直接作为<Job>节点的直接子元素来处理。但你的XML结构却是把<MainPage>放在<Pages>这个容器节点内部,两者的结构对应关系对不上,哪怕你已经在PageBase上添加了[XmlInclude],序列化器也无法正确解析节点关系,最终抛出抽象类无法实例化的错误。
修复方案
把Job类中Pages属性的[XmlElement]特性替换为[XmlArray](用来指定容器节点),配合[XmlArrayItem]明确允许的派生类型(和[XmlInclude]功能互补,也可以只保留[XmlArray],因为已经有XmlInclude了)。
修改后的Job类代码如下:
public class Job { [XmlAttribute] public string Name { get; set; } // 用XmlArray指定容器节点名为Pages,对应XML中的<Pages>标签 [XmlArray("Pages")] // 可选:明确声明允许的派生类型,和XmlInclude效果一致,二选一或并存都可 [XmlArrayItem(typeof(MainPage))] [XmlArrayItem(typeof(SubPage))] public List<PageBase> Pages { get; set; } }
补充说明
- 你在
PageBase上添加的[XmlInclude(typeof(MainPage))]和[XmlInclude(typeof(SubPage))]是完全正确的,这部分不需要修改,它负责告诉序列化器抽象基类PageBase有哪些具体的派生类型需要被识别。 - 如果你不想修改C#代码,也可以调整XML结构,去掉
<Pages>容器节点,让<MainPage>直接作为<Job>的子元素,这样原有的[XmlElement]特性就能正常工作,调整后的XML如下:<Job Name="test"> <MainPage Name="page1"></MainPage> </Job>
按照第一种方案修改后,再运行你的反序列化代码,就能正确解析XML并得到预期的Job实例了。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

