在 C# 中使用派生类从 XML 反序列化对象

Posted

技术标签:

【中文标题】在 C# 中使用派生类从 XML 反序列化对象【英文标题】:Deserializing an object from XML in C# with derived classes 【发布时间】:2020-06-12 08:25:15 【问题描述】:

我在下面有一个非常简单的 XML 文件:

<Job Name="test">
    <Pages>
        <MainPage Name="page1"/>
    </Pages>
</Job>

'MainPage'是PageBase的派生类,我的类结构如下

public class Job

    [XmlAttribute]
    public string Name  get; set; 

    [XmlElement]
    public List<PageBase> Pages  get; set; 


[XmlInclude(typeof(MainPage))]
[XmlInclude(typeof(SubPage))]
public abstract class PageBase

    [XmlAttribute]
    public string Name  get; set;         


public class MainPage : PageBase




public class SubPage : PageBase



这是我用来反序列化的示例代码:

var xml = "<Job Name=\"test\"><Pages><MainPage Name=\"page1\"></MainPage></Pages></Job>";
MemoryStream str = new MemoryStream();
StreamWriter writer = new StreamWriter(str);
writer.Write(xml);
writer.Flush();
str.Position = 0;

var serializer = new XmlSerializer(typeof(Job));
var job = (Job)serializer.Deserialize(str);

但是,我收到以下错误 - 尽管在 PageBase 类型中包含了我的 XmlInclude。我究竟做错了什么? DotNetFiddle:https://dotnetfiddle.net/UucVmX

运行时异常(第 18 行):XML 文档中存在错误(1, 19).

堆栈跟踪:

[System.InvalidOperationException:指定的类型是抽象的: name='PageBase', namespace='', at .] at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderJob.Read4_PageBase(布尔 isNullable, Boolean checkType) 在 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderJob.Read5_Job(布尔 isNullable, Boolean checkType) 在 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderJob.Read6_Job()

[System.InvalidOperationException: XML 文档中存在错误 (1, 19).] 在 System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader、字符串 encodingStyle、XmlDeserializationEvents 事件) 在 System.Xml.Serialization.XmlSerializer.Deserialize(Stream 流) 在 Program.Main() :第 18 行

【问题讨论】:

这能回答你的问题吗? XML Serialization and Inherited Types 这个thread 也会有帮助 很遗憾没有,因为我已经有 XmlInclude,但它们不起作用 你应该为抽象类型实现IXmlSerializable,就像在提到的线程中解释的那样 XmlInclude 的目的不是让这个场景“正常工作”,而不必实现这个接口吗? 在您的类中创建一些测试数据,然后序列化以查看 xml 输出和您的代码生成的内容。 include 需要 type 属性。 【参考方案1】:

将您的 XML 更改为:

<Job Name="test">
    <Pages>
        <PageBase xsi:type="MainPage" Name="page1"/>
    </Pages>
</Job>

首先尝试序列化您的对象并检查它生成的 XML。您应该看到 XML-Element 将是 PageBase 和 xsi:type="MainPage"。

【讨论】:

以上是关于在 C# 中使用派生类从 XML 反序列化对象的主要内容,如果未能解决你的问题,请参考以下文章

C#反序列化Json字符串

如何反序列化 C# 对象中复杂的 XML 格式并读取它以使用其值?

C# XML对象序列化反序列化 - PEPE YU

如何将 XML 反序列化为 C# 中的对象? [复制]

在C#中序列化和反序列化之间保留xml元素的顺序

需要帮助将 XML 文件反序列化为对象 C#