首先,我常规的想法是这样设计一个类型,采用父类,子类,在使用的地方,使用基类,动态的创建其子类使用多态。于是大概可以理解为这样的代码。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace XmlSerialize
{
public class Program
{
public static void Main(string[] args)
{
//创建一个包裹类
SomePackage package = new SomePackage();
//添加两个子类对象
package.Items.Add(new MyFirstItem());
package.Items.Add(new MySecondItem());
//序列化
string xml_text = GetXmlString(package);
Console.WriteLine(xml_text);
}
public static string GetXmlString<T>(T data)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
string sContent = string.Empty;
using (var ms = new MemoryStream())
{
using (var xw = XmlWriter.Create(ms, new XmlWriterSettings()
{
Encoding = new UTF8Encoding(false),
Indent = true,
NewLineOnAttributes = true,
}))
{
serializer.Serialize(xw, data);
sContent = Encoding.UTF8.GetString(ms.ToArray());
}
}
return sContent;
}
/// <summary>
/// 使用基类的多态list对象的类型
/// </summary>
public class SomePackage
{
public List<MyItemBase> Items { get; set; } = new List<MyItemBase>();
}
/// <summary>
/// 基类
/// </summary>
public class MyItemBase
{
public virtual string Name { get; set; }
}
/// <summary>
/// 子类1
/// </summary>
public class MyFirstItem : MyItemBase
{
public override string Name
{
get => base.Name;
set => base.Name = value;
}
}
/// <summary>
/// 子类2
/// </summary>
public class MySecondItem : MyItemBase
{
public override string Name
{
get => base.Name;
set => base.Name = value;
}
}
}
}
看似没什么问题,使用系统的序列化。可实际就无法序列化,还会提示这样一张图:
?一头雾水,尝试单独的序列化基类,子类均正常。
public static void Main(string[] args)
{
Console.WriteLine(GetXmlString<MyItemBase>(new MyItemBase(){Name="base"}));
Console.WriteLine(GetXmlString<MyFirstItem>(new MyFirstItem(){Name = "first"}));
Console.WriteLine(GetXmlString<MySecondItem>(new MySecondItem(){Name = "second"}));
Console.ReadKey();
}
运行结果如下,正常。
?所以,推断是使用基类的List,导致序列化时候没有反射到子类。
public class SomePackage
{
//就是这行引起的,因为序列化SomePackage类时,只知道MyItemBase
public List<MyItemBase> Items { get; set; } = new List<MyItemBase>();
}
修改方法,添加XmlInclude属性,描述出可能出现的子类:
[XmlInclude(typeof(MyFirstItem))]
[XmlInclude(typeof(MySecondItem))]
public class SomePackage
{
public List<MyItemBase> Items { get; set; } = new List<MyItemBase>();
}
执行结果正确,和预期一样了。
?那啥,也很久没写blog了,只是看了几篇文章,介绍的其实并非错,只是这个异常可能有多个错误的原因,仅仅做一个demo分享一下,提供个思路,希望遇到此问题困扰的朋友可以有所启发早点解决bug。
That's all. bye
|