C#中对象的系列化与反系列化
序列化也称为串行化,它能将对象备份到磁盘文件或转换为标准Xml文件通过网络实现跨平台传输。通过系列化的结果,反过来得到相应对象的过程,称为反系列化。在C#里,可以使用.Net FrameWork提供的类方面的进行系列化和反系列化。本文将介绍两种方法。在介绍具体实现之前,先给出要被系列化/反系列化的示例类型:
[System.Serializable()]
public class TypeA //要被系列化的类型1
{
private int m_nIndex;
private string m_strName = "unset";
private List<TypeB> m_listSubs = new List<TypeB>();//嵌套自定义类型TypeB
#region 属性
public int Index
{
set { m_nIndex = value; }
get { return m_nIndex; }
}
public string Name
{
set { m_strName = value; }
get { return m_strName; }
}
public List<TypeB> ListSubs
{
get { return m_listSubs; } //集合类型属性且对象建立后总不为空,只需包含get方法
}
#endregion
}
[System.Serializable()]
public class TypeB //要被系列化的类型2
{
private string m_strDescription;
public string Description
{
get { return m_strDescription; }
set { m_strDescription = value; }
}
}
以上定义了两个类型TypeA和TypeB,TypeA的列表属性ListSubs嵌套了类型TypeB,我们希望TypeA 的对象被系列化后,反系列化时得到的对象所有的属性恢复到系列化前的值。注意到两个类型的定义上都加了[System.Serializable()]属性,这是C#里实现对某种类型的对象进行系列化前的准备工作里的最简单的一种。自定义类型上有System.Serializable属性就代表该类型支持自动系列化了。要进行对象的系列化/反系列化操作,可用下面两种方法之一。
方法一:使用 System.Xml.Serialization.XmlSerializer类进行Xml系列化。实现代码如下:
public void SerializerXml(TypeA obj)//系列化
{
try
{
string strPath = @"C:/TypeA.xml";//文件名可随意指定
System.IO.FileStream writer = new System.IO.FileStream(strPath, System.IO.FileMode.Create);//以创建方式打开一个文档
System.Xml.Serialization.XmlSerializer xmlSerializer
= new System.Xml.Serialization.XmlSerializer(typeof(TypeA));//实例化Xml系列化对象时,要指定类型。
xmlSerializer.Serialize(writer, obj);//对obj执行系列化
writer.Close ();
writer.Dispose();
}
catch (System.Exception e)
{
}
}
public TypeA DeserializerXml()//反系列化
{
try
{
string strPath = @"C:/TypeA.xml";//系列化产生的文件
System.IO.FileStream reader = new System.IO.FileStream(strPath, System.IO.FileMode.Open);//以读取方式打开一个文档
System.Xml.Serialization.XmlSerializer xmlSerializer
= new System.Xml.Serialization.XmlSerializer(typeof(TypeA));//实例化Xml系列化对象时,仍然要指定类型。
object obj = xmlSerializer.Deserialize(reader);//执行反系列化
reader.Close();
reader.Dispose();
System.Diagnostics.Debug.Assert(obj != null && obj is TypeA);
return (obj as TypeA);//返回反系列化得到的对象
}
catch (System.Exception e)
{
}
}
从上面的代码可以看出,系列化和反系列化的过程都很简单,并且将其用到系列化其它类型的对象上,只需修改较少代码即可实现。
方法二:使用 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter进行二进制系列化。实现与上面同样的功能,代码如下:
public void SerializerBin(object obj)//系列化
{
try
{
string strPath = @"C:/TypeA.txt";//文件名可随意指定
System.IO.FileStream writer = new System.IO.FileStream(strPath, System.IO.FileMode.Create);//以创建方式打开一个文档
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
= new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();//直接构造,不须指定类型!
formatter.Serialize(writer, obj);//对obj执行系列化
writer.Close();
writer.Dispose ();
}
catch (System.Exception e)
{
}
}
public object DeserializerBin()//反系列化
{
try
{
string strPath = @"C:/TypeA.txt";//系列化产生的文件
System.IO.FileStream reader = new System.IO.FileStream(strPath, System.IO.FileMode.Open);//以读取方式打开一个文档
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
= new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();//直接构造,不须指定类型!
object obj = formatter.Deserialize(reader);//执行反系列化
reader.Close();
reader.Dispose();
System.Diagnostics.Debug.Assert(obj != null && obj is TypeA);
return (obj as TypeA);//返回反系列化得到的对象
}
catch (System.Exception e)
{
}
}
系列化/反系列化同一个类型的对象,方法一和方法二有一个明显的不同是,方法二完全不需知道被系列化/反系列化的对象的信息。这是因为XML 序列化仅将对象的公共字段和属性值序列化为 XML 流。XML 序列化不包括类型信息;二进制系列化则包含类型信息,它提供了更为强大的功能。
另外还值得一提的是,如果要被系列化的类型中包含IDictionary<T1,T2>类型的属性,使用上面例子中的Xml 系列化将会出现异常,而二进制系列化方法能正常进行。
[System.Serializable()]
public class TypeA //要被系列化的类型1
{
private int m_nIndex;
private string m_strName = "unset";
private List<TypeB> m_listSubs = new List<TypeB>();//嵌套自定义类型TypeB
#region 属性
public int Index
{
set { m_nIndex = value; }
get { return m_nIndex; }
}
public string Name
{
set { m_strName = value; }
get { return m_strName; }
}
public List<TypeB> ListSubs
{
get { return m_listSubs; } //集合类型属性且对象建立后总不为空,只需包含get方法
}
#endregion
}
[System.Serializable()]
public class TypeB //要被系列化的类型2
{
private string m_strDescription;
public string Description
{
get { return m_strDescription; }
set { m_strDescription = value; }
}
}
以上定义了两个类型TypeA和TypeB,TypeA的列表属性ListSubs嵌套了类型TypeB,我们希望TypeA 的对象被系列化后,反系列化时得到的对象所有的属性恢复到系列化前的值。注意到两个类型的定义上都加了[System.Serializable()]属性,这是C#里实现对某种类型的对象进行系列化前的准备工作里的最简单的一种。自定义类型上有System.Serializable属性就代表该类型支持自动系列化了。要进行对象的系列化/反系列化操作,可用下面两种方法之一。
方法一:使用 System.Xml.Serialization.XmlSerializer类进行Xml系列化。实现代码如下:
public void SerializerXml(TypeA obj)//系列化
{
try
{
string strPath = @"C:/TypeA.xml";//文件名可随意指定
System.IO.FileStream writer = new System.IO.FileStream(strPath, System.IO.FileMode.Create);//以创建方式打开一个文档
System.Xml.Serialization.XmlSerializer xmlSerializer
= new System.Xml.Serialization.XmlSerializer(typeof(TypeA));//实例化Xml系列化对象时,要指定类型。
xmlSerializer.Serialize(writer, obj);//对obj执行系列化
writer.Close ();
writer.Dispose();
}
catch (System.Exception e)
{
}
}
public TypeA DeserializerXml()//反系列化
{
try
{
string strPath = @"C:/TypeA.xml";//系列化产生的文件
System.IO.FileStream reader = new System.IO.FileStream(strPath, System.IO.FileMode.Open);//以读取方式打开一个文档
System.Xml.Serialization.XmlSerializer xmlSerializer
= new System.Xml.Serialization.XmlSerializer(typeof(TypeA));//实例化Xml系列化对象时,仍然要指定类型。
object obj = xmlSerializer.Deserialize(reader);//执行反系列化
reader.Close();
reader.Dispose();
System.Diagnostics.Debug.Assert(obj != null && obj is TypeA);
return (obj as TypeA);//返回反系列化得到的对象
}
catch (System.Exception e)
{
}
}
从上面的代码可以看出,系列化和反系列化的过程都很简单,并且将其用到系列化其它类型的对象上,只需修改较少代码即可实现。
方法二:使用 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter进行二进制系列化。实现与上面同样的功能,代码如下:
public void SerializerBin(object obj)//系列化
{
try
{
string strPath = @"C:/TypeA.txt";//文件名可随意指定
System.IO.FileStream writer = new System.IO.FileStream(strPath, System.IO.FileMode.Create);//以创建方式打开一个文档
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
= new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();//直接构造,不须指定类型!
formatter.Serialize(writer, obj);//对obj执行系列化
writer.Close();
writer.Dispose ();
}
catch (System.Exception e)
{
}
}
public object DeserializerBin()//反系列化
{
try
{
string strPath = @"C:/TypeA.txt";//系列化产生的文件
System.IO.FileStream reader = new System.IO.FileStream(strPath, System.IO.FileMode.Open);//以读取方式打开一个文档
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter
= new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();//直接构造,不须指定类型!
object obj = formatter.Deserialize(reader);//执行反系列化
reader.Close();
reader.Dispose();
System.Diagnostics.Debug.Assert(obj != null && obj is TypeA);
return (obj as TypeA);//返回反系列化得到的对象
}
catch (System.Exception e)
{
}
}
系列化/反系列化同一个类型的对象,方法一和方法二有一个明显的不同是,方法二完全不需知道被系列化/反系列化的对象的信息。这是因为XML 序列化仅将对象的公共字段和属性值序列化为 XML 流。XML 序列化不包括类型信息;二进制系列化则包含类型信息,它提供了更为强大的功能。
另外还值得一提的是,如果要被系列化的类型中包含IDictionary<T1,T2>类型的属性,使用上面例子中的Xml 系列化将会出现异常,而二进制系列化方法能正常进行。