支持派生类型的序列化和反序列化。以下属性控制 Xml 序列化:
[XmlElement]
[XmlAttribute]
[XmlIgnore]
我们需要指示 Xml 序列化程序忽略我们希望在具体派生类型中使用的基类成员。
见->https://docs.microsoft.com/en-us/dotnet/standard/serialization/attributes-that-control-xml-serialization
另外,请注意构造函数中的虚拟成员调用
见->https://msdn.microsoft.com/en-us/library/ms182331.aspx
试一试:
解决方案 1
使用派生类 MyRoot 作为 XmlSerializer
的
type 参数
抽象基类:
[Serializable]
public abstract class RootElementBase<TEelment>
{
[XmlIgnore]
public virtual List<TEelment> SubElements { get; set; }
protected RootElementBase()
{
SubElements = new List<TEelment>();
}
}
具体类:
[XmlRoot(ElementName = "myroot")]
public class MyRoot : RootElementBase<ItemType>
{
[XmlElement("item")]
public override List<ItemType> SubElements { get; set; }
}
虚拟ItemType类:
public class ItemType
{
public string Name { get; set; }
}
这将输出以下内容:
<?xml version="1.0"?>
<myroot xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item>
<Name>Jim</Name>
</item>
<item>
<Name>Ben</Name>
</item>
<item>
<Name>Tom</Name>
</item>
</myroot>
测试控制台应用程序:
class Program
{
static void Main(string[] args)
{
MyRoot root = new MyRoot();
root.SubElements.Add(new ItemType() { Name = "Jim"});
root.SubElements.Add(new ItemType() { Name = "Ben" });
root.SubElements.Add(new ItemType() { Name = "Tom" });
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyRoot));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, root);
Console.WriteLine(stringWriter);
Console.ReadKey();
}
}
解决方案 2
使用抽象基类 RootElementBase 作为带有XmlRoot 覆盖参数的 XmlSerializer 的 type 参数
每个 MSDN:
XML 文档的根元素包含所有其他元素。
默认情况下,type参数指定的对象是序列化的
作为根元素。属性,例如 XML 元素名称
根元素取自类型对象。然而,根
参数允许您将默认对象的信息替换为
指定 XmlRootAttribute;该对象允许您设置一个
不同的命名空间、元素名称等。
https://msdn.microsoft.com/en-us/library/65k4wece(v=vs.110).aspx
抽象基类:
[Serializable]
[XmlInclude(typeof(MyRoot))]
public abstract class RootElementBase<TEelment>
{
[XmlIgnore]
public virtual List<TEelment> SubElements { get; set; }
protected RootElementBase()
{
SubElements = new List<TEelment>();
}
}
具体类:
[XmlRoot(ElementName = "myroot")]
public class MyRoot : RootElementBase<ItemType>
{
[XmlElement("item")]
public override List<ItemType> SubElements { get; set; }
}
虚拟ItemType类:
public class ItemType
{
public string Name { get; set; }
}
具有通用序列化的示例控制台应用程序
class Program
{
static void Main(string[] args)
{
MyRoot root = new MyRoot();
root.SubElements.Add(new ItemType() { Name = "Jim"});
root.SubElements.Add(new ItemType() { Name = "Ben" });
root.SubElements.Add(new ItemType() { Name = "Tom" });
string xml = Serialize(root, "myNewRoot");
Console.WriteLine(xml);
Console.ReadKey();
}
static string Serialize<TElement>(RootElementBase<TElement> tElement, string rootElementName)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(RootElementBase<TElement>),
new XmlRootAttribute(rootElementName));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, tElement);
return stringWriter.ToString();
}
}
注意 - 使用此解决方案您需要了解动态生成的程序集
动态生成的程序集
为了提高性能,XML 序列化基础结构动态生成程序集以序列化和反序列化指定类型。基础结构查找并重用这些程序集。此行为仅在使用以下构造函数时发生:
XmlSerializer.XmlSerializer(Type)
XmlSerializer.XmlSerializer(Type, String)
如果您使用任何其他构造函数,则会生成同一程序集的多个版本并且永远不会卸载,这会导致内存泄漏和性能下降。最简单的解决方案是使用前面提到的两个构造函数之一。否则,您必须将程序集缓存在 Hashtable 中,如下例所示。
备注见MSDN:https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=vs.110).aspx