使用XmlSerializer将对象序列化时,遇到的三个问题:
1. 如何对List序列化?
2. 对被序列化对象的构造函数有什么要求?
3. 如何对实现了抽象类的具体类序列化?
1. 问题背景:
写了一个类(嵌套了很多其它类)来保存UI(可编辑)的现场数据。现在有一个需求,就是在UI程序关闭时将这些数据保存起来,等下次UI打开时自动加载这些保存的数据,即恢复UI上次关闭时的状态。即需要一个序列化和反序列化的工具,至于序列化成什么格式不关注,只要反序列化时能恢复当初被序列化对象的所有数据即可。于是考虑用System.Xml.Serialization.XmlSerializer来做这件事情。在使用过程这中遇到一些问题,特将这些问题的解决过程记录下来,以备以后再用时参考。
2. 问题描述:
1) 假设想要序列化的类想要序列化的类A包含一个B类对象,和一个C类对象List。其中C是抽象类,有C1和C2两个具体类实现了它。如下图所示:
2) 代码如下:

Code
using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Collections.Generic;
namespace Spacer_Robot
{
public class XmlSerilizeTest
{
static void Main(string[] args)
{
A a = new A();
B b = new B(3);
a.B = b;
List<C> cList = new List<C>();
C1 c1 = new C1();
c1.CInt = 1;
cList.Add(c1);
C2 c2 = new C2();
c2.CInt = 2;
cList.Add(c2);
a.CList = cList;
SerilizeAnObject(a, "test.xml");
}
private static void SerilizeAnObject(object obj, string path)
{
System.IO.FileStream stream = new FileStream(path, FileMode.Create);
try
{
System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(obj.GetType());
serializer.Serialize(stream, obj);
}
catch (Exception ex)
{
Console.WriteLine("SerilizeAnObject Exception: {0}", ex.Message);
}
finally
{
stream.Close();
stream.Dispose();
}
}
private static object DeserilizeAnObject(Type type, string path)
{
object obj = null;
System.IO.FileStream stream = new FileStream(path, FileMode.Open);
try
{
System.Xml.XmlReader reader = new XmlTextReader(stream);
System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(type);
obj = serializer.Deserialize(reader);
}
catch (Exception ex)
{
Console.WriteLine("DeserilizeAnObject Exception: {0}", ex.Message);
}
finally
{
stream.Close();
stream.Dispose();
}
return obj;
}
}
public class A
{
public B B
{
get;
set;
}
public List<C> CList
{
get;
set;
}
}
public class B
{
public B(int value)
{
bInt = value;
}
int bInt;
public int BInt
{
get { return bInt; }
set { bInt = value; }
}
}
public abstract class C
{
}
public class C1 : C
{
public int CInt
{
get;
set;
}
}
public class C2 : C
{
public int CInt
{
get;
set;
}
}
}
3) 上述代码存在三个问题:
a) 类A的CList成员无法被序列化。
b) 类B无法被序列化。
c) 类C1和C2无法被序列化。
3. 原因分析和解决办法:
1) CList成员无法被序列化:System.Xml.Serialization.XmlSerializer无法序列化List<>,改用数组。
2) 类B无法被无法被序列化:对每个需要被序列化的类,要么没有提供构造函数,如果提供了,就必须同时提供一个无参构造函数。所以需要类B提供无参构造函数。
3) 类C1和C2无法被序列化:要想序列化以其抽象类的形式出现的具体类,必须在抽象类定义的地方用Attribute:System.Xml.Serialization.XmlInclude来指明该具体类。
4) 修改后的代码如下:

Code
using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Collections.Generic;
namespace Spacer_Robot
{
public class XmlSerilizeTest
{
static void Main(string[] args)
{
A a = new A();
B b = new B(3);
a.B = b;
List<C> cList = new List<C>();
C1 c1 = new C1();
c1.CInt = 1;
cList.Add(c1);
C2 c2 = new C2();
c2.CInt = 2;
cList.Add(c2);
a.CArray = cList.ToArray();
SerilizeAnObject(a, "test.xml");
A a1 = new A();
a1 = (A)DeserilizeAnObject(a1.GetType(), "test.xml");
Console.WriteLine("A.B.BInt = {0}", a1.B.BInt);
Console.WriteLine("A.CArray.C1.CInt = {0}", ((C1)a1.CArray[0]).CInt);
Console.WriteLine("A.CArray.C2.CInt = {0}", ((C2)a1.CArray[1]).CInt);
}
private static void SerilizeAnObject(object obj, string path)
{
System.IO.FileStream stream = new FileStream(path, FileMode.Create);
try
{
System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(obj.GetType());
serializer.Serialize(stream, obj);
}
catch (Exception ex)
{
Console.WriteLine("SerilizeAnObject Exception: {0}", ex.Message);
}
finally
{
stream.Close();
stream.Dispose();
}
}
private static object DeserilizeAnObject(Type type, string path)
{
object obj = null;
System.IO.FileStream stream = new FileStream(path, FileMode.Open);
try
{
System.Xml.XmlReader reader = new XmlTextReader(stream);
System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(type);
obj = serializer.Deserialize(reader);
}
catch (Exception ex)
{
Console.WriteLine("DeserilizeAnObject Exception: {0}", ex.Message);
}
finally
{
stream.Close();
stream.Dispose();
}
return obj;
}
}
public class A
{
public B B
{
get;
set;
}
public C[] CArray
{
get;
set;
}
}
public class B
{
public B()
{
}
public B(int value)
{
bInt = value;
}
int bInt;
public int BInt
{
get { return bInt; }
set { bInt = value; }
}
}
[System.Xml.Serialization.XmlInclude(typeof(C1)),
System.Xml.Serialization.XmlInclude(typeof(C2))]
public abstract class C
{
}
public class C1 : C
{
public int CInt
{
get;
set;
}
}
public class C2 : C
{
public int CInt
{
get;
set;
}
}
}
4. 其它:
MSDN中对XmlSerializer使用的帮助链接为:
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App