刚才看.net框架里面的自定义异常,发现里面用到了序列化,自己对于序列化有点模糊了,找本书看看(C#圣经呵呵);
使用对象序列化,可以持久化保存一个对象的状态到任何System.IO.Stream派生的类型中,或者从后者中获取对象的状态,当试图通过.NET远程处理层、XML Web服务或者WCF(不熟悉,关注Frank Xu Lei)这样的远程处理技术将一个对象复制到远程计算机时,具有对类型序列化的能力很关键。
序列化描述了持久化一个对象的状态到流的过程。被持久化的数据次序包括所有以后需要重建(反序列化)对象状态所必需的信息。假设对于一个窗体程序,需要保存用户的窗体偏好,可以定义UserPrefs来封装数据模块,可以对UserPrefs类标识[Serializable] 特性:
namespace SerializableStudy
{
class Program
{
static void Main( string [] args)
{
UserPrefs userData = new UserPrefs();
userData.WindowColor = " Yellow " ;
userData.FontSize = " 50 " ;
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream fStream = new FileStream( " user.dat " ,FileMode.Create,FileAccess.Write,FileShare.None))
{
binFormat.Serialize(fStream,userData);
}
}
}
[Serializable]
public class UserPrefs
{
private string windowColor;
public string WindowColor
{
get { return windowColor; }
set { windowColor = value; }
}
private string fontSize;
public string FontSize
{
get { return fontSize; }
set { fontSize = value; }
}
}
}
.NET的序列化非常的简单,但是幕后的调用却非常的复杂。当对象被持久化到流时,所有相关数据(基类,派生类)也会被自动序列化。对象可以持久化为任意的System .IO.Stream派生类型。
对象图的作用
当对象被序列化时,CLR将处理所有相关的对象,一组关联对象总称为一个对象图。小例子,基类Car,它配有Radio,另外一个JamesBondCar的类扩展Car基类。如下图:
当然CLR不会在内存中画图来表示相关对象。可以用下面公式表示之:
[Car 3,ref 2],[Radio 2],[JamesBondCar 1,ref 3,ref 2]
在各种情况下,序列化或反序列化JamesBondCar类的实例时,对象图确认Radio类型和Car类型也参与了这个过程。序列化过程的美妙之处在于表示各个对象之间的相互关系的图形是在幕后自动建立的。
定义可序列化的类型
为了让一个对象支持序列化服务,只需要在每一个关联的类上加上[Serializable]特性,非常的简单,如果给定类的一些数据成员不能参与序列化,可以在这些成员前面加上[NonSerialized]特性
[Serializable]
public class Radio
{
public bool hasTweeters;
public bool hasSubWoofers;
public double [] stationPresets;
[NonSerialized] // 不被持久化
public string radioID = " XF-552RR6 " ;
}
[Serializable]
public class Car
{
public Radio radio = new Radio();
public bool isHatchBack;
}
[Serializable]
public class JamesBondCar : Car
{
public bool canFly;
public bool canSubmerge;
}
[Serializable]属性不能被继承,因此,如果从被标记为[Serializable]的类派生一个类,子类也必须被标记为[Serializable],否则不能被持久化。如果试图对没有标记特性的对象序列化会爆出SerializationException的提示,下面的代码也会爆出异常:
class Program
{
static void Main( string [] args)
{
JamesBondCar car = new JamesBondCar();
car.canFly = true ;
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream fStream = new FileStream( " user.dat " ,FileMode.Create,FileAccess.Write,FileShare.None))
{
binFormat.Serialize(fStream, car);
}
}
}
public class Radio
{
public bool hasTweeters;
public bool hasSubWoofers;
public double [] stationPresets;
[NonSerialized] // 不被持久化
public string radioID = " XF-552RR6 " ;
}
[Serializable]
public class Car
{
public Radio radio = new Radio();
public bool isHatchBack;
}
Radio没有序列化特性,而Car却引用了Radio所以会异常,修改后:
class Program
{
static void Main( string [] args)
{
JamesBondCar car = new JamesBondCar();
car.canFly = true ;
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream fStream = new FileStream( " user.dat " ,FileMode.Create,FileAccess.Write,FileShare.None))
{
binFormat.Serialize(fStream, car);
}
}
}
public class Radio
{
public bool hasTweeters;
public bool hasSubWoofers;
public double [] stationPresets;
[NonSerialized] // 不被持久化
public string radioID = " XF-552RR6 " ;
}
[Serializable]
public class Car
{
[NonSerialized]
public Radio radio = new Radio();
public bool isHatchBack;
}
给car的Radio字段加[NoSerialized]属性即可。当然直接给Radio类加[Serializable]特性也可;
序列化格式
BinaryFormatter,SoapFormatter,XmlSerializer;
BinaryFormatter类型使用紧凑的二进制格式将对象序列化为一个流,SoapFormatter将对象表示为一个Soap消息,如果希望将对象持久化为一个XML文档,需要用到XmlSerializer类型。
namespace SerializableStudy
{
class Program
{
static void Main( string [] args)
{
JamesBondCar car = new JamesBondCar();
car.canFly = true ;
SaveAsBinaryFormat(car, " carBinaryData.dat " );
LoadFromBinaryFormat( " carBinaryData.dat " );
SaveAsSoapFormat(car, " carSoapData.dat " );
LoadFromSoapFormat( " carSoapData.dat " );
SaveAsXmlFormat(car, " carXmlData.dat " );
LoadFromXmlFormat( " carXmlData.dat " );
}
// binary序列化
static void SaveAsBinaryFormat( object objGraph, string fileName)
{
BinaryFormatter bf = new BinaryFormatter();
using (Stream fs = new FileStream
(fileName,FileMode.Create,FileAccess.Write,FileShare.None))
{
bf.Serialize(fs, objGraph);
}
Console.WriteLine( " =>Saved car in binary format " );
}
// binary反序列化
static void LoadFromBinaryFormat( string fileName)
{
BinaryFormatter bf = new BinaryFormatter();
using (Stream fs = File.OpenRead(fileName))
{
JamesBondCar car = (JamesBondCar)bf.Deserialize(fs);
Console.WriteLine( " Can Fly ? : {0} " , car.canFly);
}
}
// Soap 序列化
static void SaveAsSoapFormat( object objGraph, string fileName)
{
SoapFormatter sf = new SoapFormatter();
using (Stream fs = new FileStream
(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
sf.Serialize(fs, objGraph);
}
Console.WriteLine( " =>Saved car in Soap format " );
}
// Soap反序列化
static void LoadFromSoapFormat( string fileName)
{
SoapFormatter sf = new SoapFormatter();
using (Stream fs = File.OpenRead(fileName))
{
JamesBondCar car = (JamesBondCar) sf.Deserialize(fs);
Console.WriteLine( " Can Fly ? : {0} " , car.canFly);
}
}
// Xml序列化
static void SaveAsXmlFormat( object objGraph, string fileName)
{
XmlSerializer xs = new XmlSerializer( typeof (JamesBondCar), new Type[] { typeof (Radio), typeof (Car)});
using (Stream fs = new FileStream
(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
xs.Serialize(fs, objGraph);
}
Console.WriteLine( " =>Saved car in XML format " );
}
// Xml反序列化
static void LoadFromXmlFormat( string fileName)
{
XmlSerializer xs = new XmlSerializer( typeof (JamesBondCar), new Type[] { typeof (Radio), typeof (Car) });
using (Stream fs = File.OpenRead(fileName))
{
JamesBondCar car = (JamesBondCar)xs.Deserialize(fs);
Console.WriteLine( " Can Fly ? : {0} " , car.canFly);
}
}
}
[Serializable]
public class Radio
{
public bool hasTweeters;
public bool hasSubWoofers;
public double [] stationPresets;
public string radioID = " XF-552RR6 " ;
}
[Serializable]
public class Car
{
[NonSerialized]
public Radio radio = new Radio();
public bool isHatchBack;
}
[Serializable]
public class JamesBondCar : Car
{
public bool canFly;
public bool canSubmerge;
}
}