序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。
.NET框架提供了两种串行化的方式:1、是使用BinaryFormatter进行串行化;2、使用SoapFormatter进行串行化;3、使用XmlSerializer进行串行化。第一种方式提供了一个简单的二进制数据流以及某些附加的类型信息,而第二种将数据流格式化为XML存储;第三种其实和第二种差不多也是XML的格式存储,只不过比第二种的XML格式要简化很多(去掉了SOAP特有的额外信息)。
可以使用
[Serializable]属性将类标志为可序列化的。如果某个类的元素不想被序列化,1、2可以使用
[NonSerialized]属性来标志,2、可以使用[XmlIgnore]来标志。
1、使用BinaryFormatter进行串行化
下面是一个可串行化的类:
using
System;
using
System.Data;
using
System.Configuration;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.WebControls.WebParts;
using
System.Web.UI.HtmlControls;
using
System.IO;
using
System.Runtime.Serialization.Formatters.Binary;
/// <summary>
///
ClassToSerialize 的摘要说明
/// </summary>
[Serializable]
public
class ClassToSerialize
{
public int id
= 100;
public string name =
"Name";
[NonSerialized]
public string Sex =
"男";
}

下面是串行化和反串行化的方法:
public
void SerializeNow()
{
ClassToSerialize c =
new ClassToSerialize();
FileStream fileStream =
new FileStream("c:\\temp.dat",
FileMode.Create);
BinaryFormatter b =
new BinaryFormatter();
b.Serialize(fileStream, c);
fileStream.Close();
}
public void DeSerializeNow()
{
ClassToSerialize c =
new ClassToSerialize();
c.Sex = "kkkk";
FileStream fileStream =
new FileStream("c:\\temp.dat",
FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryFormatter b =
new BinaryFormatter();
c = b.Deserialize(fileStream) as ClassToSerialize;
Response.Write(c.name);
Response.Write(c.Sex);
fileStream.Close();
}
调用上述两个方法就可以看到串行化的结果:Sex属性因为被标志为[NonSerialized],故其值总是为null。
2、使用SoapFormatter进行串行化
和BinaryFormatter类似,我们只需要做一下简单修改即可:
a.将using语句中的.Formatter.Binary改为.Formatter.Soap;
b.将所有的BinaryFormatter替换为SoapFormatter.
c.确保报存文件的扩展名为.xml
经过上面简单改动,即可实现SoapFormatter的串行化,这时候产生的文件就是一个xml格式的文件。
3、使用XmlSerializer进行串行化
关于格式化器还有一个问题,假设我们需要XML,但是不想要SOAP特有的额外信息,那么我们应该怎么办呢?有两中方案:要么编写一个实现IFormatter接口的类,采用的方式类似于SoapFormatter类,但是没有你不需要的信息;要么使用库类XmlSerializer,这个类不使用Serializable属性,但是它提供了类似的功能。
如果我们不想使用主流的串行化机制,而想使用XmlSeralizer进行串行化我们需要做一下修改:
a.添加System.Xml.Serialization命名空间。
b.Serializable和NoSerialized属性将被忽略,而是使用XmlIgnore属性,它的行为与NoSerialized类似。
c.XmlSeralizer要求类有个默认的构造器,这个条件可能已经满足了。
下面看示例:
要序列化的类:
using
System;
using
System.Data;
using
System.Configuration;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.WebControls.WebParts;
using
System.Web.UI.HtmlControls;
using
System.Xml.Serialization;
[Serializable]
public
class Person
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}


public string Sex;
public int Age
= 31;
public Course[] Courses;

public Person()
{
}
public Person(string Name)
{
name = Name;
Sex = "男";
}
}
[Serializable]
public
class Course
{
public string Name;
[XmlIgnore]
public string Description;
public Course()
{
}
public Course(string name, string description)
{
Name = name;
Description =
description;
}
}

序列化和反序列化方法:
public
void XMLSerialize()
{
Person c = new Person("cyj");
c.Courses = new Course[2];
c.Courses[0] =
new Course("英语",
"交流工具");
c.Courses[1] =
new Course("数学","自然科学");
XmlSerializer xs =
new XmlSerializer(typeof(Person));
Stream stream =
new FileStream("c:\\cyj.XML",FileMode.Create,FileAccess.Write,FileShare.Read);
xs.Serialize(stream,c);
stream.Close();
}
public void XMLDeserialize()
{
XmlSerializer xs =
new XmlSerializer(typeof(Person));
Stream stream =
new FileStream("C:\\cyj.XML",FileMode.Open,FileAccess.Read,FileShare.Read);
Person p = xs.Deserialize(stream) as Person;
Response.Write(p.Name);
Response.Write(p.Age.ToString());
Response.Write(p.Courses[0].Name);
Response.Write(p.Courses[0].Description);
Response.Write(p.Courses[1].Name);
Response.Write(p.Courses[1].Description);
stream.Close();
}
这里Course类的Description属性值将始终为null,生成的xml文档中也没有该节点,如下图:
<?xml
version="1.0"?>
<Person
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Sex>男</Sex>
<Age>31</Age>
<Courses>
<Course>
<Name>英语</Name>
<Description>交流工具</Description>
</Course>
<Course>
<Name>数学</Name>
<Description>自然科学</Description>
</Course>
</Courses>
<Name>cyj</Name>
</Person>
4、自定义序列化
如果你希望让用户对类进行串行化,但是对数据流的组织方式不完全满意,那么可以通过在自定义类中实现接口来自定义串行化行为。这个接口只有一个方法,GetObjectData.
这个方法用于将对类对象进行串行化所需要的数据填进SerializationInfo对象。你使用的格式化器将构造SerializationInfo对象,然后在串行化时调用GetObjectData.
如果类的父类也实现了ISerializable,那么应该调用GetObjectData的父类实现。
如果你实现了ISerializable,那么还必须提供一个具有特定原型的构造器,这个构造器的参数列表必须与GetObjectData相同。这个构造器应该被声明为私有的或受保护的,以防止粗心的开发人员直接使用它。
示例如下:
实现ISerializable的类:
序列化和反序列化方法:
public
void OtherEmployeeClassTest()
{
Employee mp =
new Employee();
mp.EmpId = 10;
mp.EmpName =
"邱枫";
mp.NoSerialString =
"你好呀";
Stream steam =
File.Open("c:\\temp3.dat",
FileMode.Create);
BinaryFormatter bf =
new BinaryFormatter();
Response.Write("Writing
Employee Info:");
bf.Serialize(steam,mp);
steam.Close();
mp = null;
//反序列化
Stream steam2 = File.Open("c:\\temp3.dat",
FileMode.Open);
BinaryFormatter bf2 =
new BinaryFormatter();
Response.Write("Reading
Employee Info:");
Employee mp2 =
(Employee)bf2.Deserialize(steam2);
steam2.Close();
Response.Write(mp2.EmpId);
Response.Write(mp2.EmpName);
Response.Write(mp2.NoSerialString);
}
PS:本文转自网络,序列化和反序列化使用的还是比较多的,这篇文章总结了C#
中序列化和反序列化的使用以及例子,我对BinaryFormatter实例有做测试,我是打算用序列化来保存程序的配置文件,因为有些配置参数是不希望用户来修改或者是看见,所以用二进制保存到DLL文件中,这是比较好的来解决了这个问题。对于软件升级来说这些参数的修改只要更新DLL就可以了,也比较方便和安全。