当使用子类时,我在反序列化由 XmlSerializer 生成的 XML 代码时遇到问题。 UnknownAttribute 和 UnknownNode 事件触发,我假设反序列化 XML 时出现错误。事实证明,不设置处理程序或忽略事件仍然可以让反序列化成功。
示例代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
namespace XmlTest
{
public class Program
{
public abstract class ParentClass
{
public int Prop1 { get; set; } = 1;
public int Prop2 { get; set; } = 2;
}
public class ChildClassA : ParentClass
{
public int PropA3 { get; set; } = 3;
public int PropA4 { get; set; } = 4;
}
public class ChildClassB : ParentClass
{
public int PropB5 { get; set; } = 5;
public int PropB6 { get; set; } = 6;
}
[XmlInclude(typeof(ChildClassA))]
[XmlInclude(typeof(ChildClassB))]
public class CollectionClass
{
public List<ParentClass> classList { get; set; }
}
static void Main(string[] args)
{
CollectionClass collectionClassWrite = new CollectionClass();
collectionClassWrite.classList = new List<ParentClass>();
collectionClassWrite.classList.Add(new ChildClassA());
collectionClassWrite.classList.Add(new ChildClassB());
// Serialize the class to a file
string filePath = Path.GetTempFileName() + ".xml";
XmlSerializer serializer = new XmlSerializer(typeof(CollectionClass));
TextWriter writer = new StreamWriter(filePath);
serializer.Serialize(writer, collectionClassWrite);
writer.Close();
XmlSerializer deserializer = new XmlSerializer(typeof(CollectionClass));
// Event handlers for unknown nodes and attributes -
serializer.UnknownNode += new
XmlNodeEventHandler(serializer_UnknownNode);
serializer.UnknownAttribute += new
XmlAttributeEventHandler(serializer_UnknownAttribute);
// Deserialize the class from the file
FileStream fs = new FileStream(filePath, FileMode.Open);
CollectionClass classCollectionOpen = (CollectionClass)serializer.Deserialize(fs);
fs.Close();
Console.ReadLine();
}
private static void serializer_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
Console.WriteLine($"Unknown Attribute at {e.LineNumber}:{e.LinePosition}");
}
private static void serializer_UnknownNode(object sender, XmlNodeEventArgs e)
{
Console.WriteLine($"Unknown Node at {e.LineNumber}:{e.LinePosition}");
}
}
}
生成的 XML 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<CollectionClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<classList>
<ParentClass xsi:type="ChildClassA">
<Prop1>1</Prop1>
<Prop2>2</Prop2>
<PropA3>3</PropA3>
<PropA4>4</PropA4>
</ParentClass>
<ParentClass xsi:type="ChildClassB">
<Prop1>1</Prop1>
<Prop2>2</Prop2>
<PropB5>5</PropB5>
<PropB6>6</PropB6>
</ParentClass>
</classList>
</CollectionClass>
UnknownAttribute 和 UnknownNode 事件在(行:列)4:28 和 10:28 触发,xsi:type="ChildClassA" 和 xsi:type="ChildClassB" 属性。
看来必须忽略这些事件才能使代码正常工作。 我的问题就变成了: 为什么当 XmlSerializer 清楚地知道如何处理 XML 代码时会引发事件?
因此 XmlSerializer 不知道什么将被序列化为 ParentClass。
解决方案是让它了解可能的类型。
问题是 Array 需要知道除了整个类之外将出现什么类型。
public record CollectionClass
{
[XmlArrayItem("ChildClassA", typeof(ChildClassA))]
[XmlArrayItem("ChildClassB", typeof(ChildClassB))]
public List<ParentClass> ClassList { get; set; } = new();
}