一:为什么要序列化:
1:将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本(将类的属性字段值保存到磁盘中)
2:按值将对象从一个应用程序域发送至另一个应用程序域,通常地讲就是在网络上传送对象的字节序列
二:实现序列化的方式
.NET Framework 为序列化提供了三个格式化程序:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter类,
System.Runtime.Serialization.Formatters.Soap.SoapFormatter 类,
System.Xml.Serialization.XmlSerializer类。
这些类通过通常在内存中的“对象图”(对象在内存中的表示形式)并将其转换成数据流。正如它们各自的名称所表示的,Binary序列化将对象图转换成二进制流,序列化器的结果体积比较小,是二进制格式存储的(对桌面应用程序最有用),XML序列化将对象图转化为标准的XML文档,有利于跨平台(对 Internet 应用程序最有用).而SOAP序列化其实可以说是XML序列化的一种,但它的结果是特定的XML文档,遵从SOAP规范,SOAPFormatter 将对象图转换成简单对象访问协议 (SOAP) 格式(对 Internet 应用程序最有用)。
三:序列化对象和反序列化的实现方式
1.Binary序列化和反序列化:
要使一个类可序列化,最简单的方法是使用Serializable 属性对它进行标记,如下所示:
[Serializable]
public class MyObject {
public int n1 = 0;
public int n2 = 0; //如果不想对某个属性序列化的时候,可以设置成[NonSerialized] public int n2=0
public String str = null;
}
MyObject obj = new MyObject();
obj.n1= 1;
obj.n2= 24;
obj.str = "my first serializable program";
BinaryFormatter formatter = new BinaryFormatter(); //注意引进命名空间
Streamstream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
Binary的反序列化:
BinaryFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject)formatter.Deserialize(stream);
Console.WriteLine(obj.n1);
Console.WriteLine(obj.n2);
Console.WriteLine(obj.str);
stream.Close();
2:SOAP序列化和反序列化:
如果要求具有可移植性,请使用 SoapFormatter。所要做的更改只是将以上代码中的BinaryFormatter换 SoapFormatter,而 Serialize 和 Deserialize 调用不变。
3:XML序列化和反序列化:
XmlSerializer ser = new XmlSerializer(obj.GetType());
ser.Serialize(new FileStream(@"users.xml", FileMode.Create), obj);
反序列化
MyObject my;
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
Stream stream = new FileStream(@"users.xml", FileMode.Open,FileAccess.Read,FileShare.Read);
my = (MyObject)serializer.Deserialize(stream);
Console.WriteLine(my.str);
stream.Close();
四:自定义序列化
可以通过在对象上实现 ISerializable 接口来自定义序列化过程。这一功能在反序列化后成员变量的值失效时尤其有用,但是需要为变量提供值以重建对象的完整状态。要实现 ISerializable,需要实现 GetObjectData 方法以及一个特殊的构造函数,在反序列化对象时要用到此构造函数。
[Serializable]
public class MyObject : ISerializable
{
public int n1;
public int n2;
public String str;
public MyObject()
{
}
protected MyObject(SerializationInfo info, StreamingContext context)
{
n1 = info.GetInt32("i");
n2 = info.GetInt32("j");
str = info.GetString("k");
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("i", n1);
info.AddValue("j", n2);
info.AddValue("k", str);
}
}
//void GetObjectData(Serializationinfo info, StreamContext context ) 是用来处理要进行序列化的成员,其中info 参数提供各个成员字段信息,可在此时对对象中的成员赋值,调用AddValue()方法。
//如果从实现了 ISerializable 的类派生出一个新的类,则只要新的类中含有任何需要序列化的变量,就必须同时实现构造函数以及 GetObjectData 方法。以下代码片段显示了如何使用上文所示的 MyObject 类来完成此操作
[Serializable]
public class ObjectTwo : MyObject
{
public int num;
public ObjectTwo () : base()
{
}
protected ObjectTwo(SerializationInfo si, StreamingContext context) : base(si,context)
{
num = si.GetInt32("num");
}
//切记要在反序列化构造函数中调用基类,否则,将永远不会调用基类上的构造函数,并且在反序列化后也无法构建完整的对象
public override void GetObjectData(SerializationInfo si, StreamingContext context)
{
base.GetObjectData(si,context);
si.AddValue("num", num);
}
}
//自定义序列化的测试
Stream stream = new FileStream("file.xml", FileMode.Create, FileAccess.Write, FileShare.None);ObjectTwo obj = new ObjectTwo();
obj.n1 = 2;
obj.n2 = 3;
obj.num = 4;
obj.str = "xiongqinglin";
XmlSerializer xsl = new XmlSerializer(typeof(ObjectTwo));
xsl.Serialize(stream, obj);
stream.Close();
//反序列化
ObjectTwo my;
XmlSerializer serializer = new XmlSerializer(typeof(ObjectTwo));
Stream stream = new FileStream("file.xml", FileMode.Open, FileAccess.Read, FileShare.Read);
my = (ObjectTwo)serializer.Deserialize(stream);
Console.WriteLine(my.str);
stream.Close();
OK,就这些!