对象序列化(笔记)
对象序列化,可以把一个对象序列化到一个文件上持久化保存,也可以从文件中读取对象.比如说我们要存储一个客户端程序,要根据用户的偏好(字体,界面风格之类的),需要一个有100个属性的对象,如果我们按平常一样!存在一个数据库里面或者别的,那需要读取数据,然后为这个对象的100个属性一一赋值,这将是一件多么麻烦的事呀.然后,对象序列化却是可以很好的帮你解决这个问题!
具体可以看下面的代码,先定义一个要进行序列化的对象
[Serializable]
public class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
}
PS:如果想某个字段不想给序列化(不保存),可以在在字段上添加[NonSerialized]特性;
接下来,我们编写两个方法,一个是用于将对象序列化到一个二进制文件中,一个是将对象从二进制文件中读取出来.
/// <summary>
/// 保存对象到二进制文件中
/// </summary>
/// <param name="obj"></param>
/// <param name="fileName"></param>
public static void SaveObjectAsBinaryFormat(object obj, string fileName)
{
BinaryFormatter binformat = new BinaryFormatter();
using (Stream st = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
binformat.Serialize(st, obj);
}
}
/// <summary>
/// 将对象从二进制文件中读取出来
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static object LoadObjectAsinaryFormat(string fileName)
{
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream st = File.OpenRead(fileName))
{
return binFormat.Deserialize(st);
}
}
使用就很简单拉!简单调用而以.
static void Main(string[] args)
{
Person person = new Person();
person.Age = 100;
person.Name = "Andy";
SaveObjectAsBinaryFormat(person, "Person.dat");
Person objP = LoadObjectAsinaryFormat("Person.dat") as Person;
Console.WriteLine(objP.Name);
Console.WriteLine(objP.Age);
Console.Read();
}
注意:如果你序列化的对象里面又包含了另一个类型的话,要确实另一个类型也要序列化,否则您将收到异常.
例:序列A对象,但A对象的基类是B,那么B也需要序列化.
除了以上使用BinaryFormatter将对象序列化成二进制文件外,还可以将对象序列化成soap文件,SoapFormatter类型将把对象图持久化为一个SOAP消息,当希望在不同的环境下进行远程分派对象时,这个方式是一个可靠的选择.如果不熟悉SOAP规范,现在也不需要在细节上花费时间,简而言之,SOAP定义了一个标准的过程,在这个过程中可以用与平吧和操作系统无关的方式调用方法.
使用SOAP需要手动添加引用(System.Runtime.Serialization.Formatter.Soap.dll),具体做法和BinaryFormatter极度相似,只需要把BinaryFormatter换成SoapFormatter就可以了!保存和加载都是一样!
例:
public static void SaveObjectAsBinaryFormat(object obj, string fileName)
{
SoapFormatter soapformat = new SoapFormatter();
using (Stream st = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
binformat.Serialize(st, obj);
}
}
注意,生成的文件將是以soap結尾的!还有,文件的大小会比dat大好几倍.
除了以上两种外,还可以使用XmlSerializer序列化对象,不过不熟,就不写出来了!不过想知道实现的朋友可以与我交流:)
看了上面的代码,我们知道,在序列化的时候,方法只提供了一个参数,如果我们想同时序列化多个对象,应如何解决呢?
好在大多数在System.Collections和System,Collections.Generic命名空间内的类型已经被标记为[Serializable],因为如果你希望对一组对象进行持久化,只需要添加这组对象到容器(List<T>,ArrayList)里面即可,然后再把你的容器传入序列化的方法里面即可了!具体代码就不演示,反正都是很简单的.
大多数时候序列化对象使用上面的代码就行了!但有时候我们有特殊的要求,比如说我想把序列化的对象里面的所有字段变成大写.这就需要使用到自定义序列化过程了!
为更多地人为干预,system,runtime,serialization命名空间提供了一些特性,比如在对象序列化前就会自动调用指定了[OnSerialized]特性的方法
例:
我们在上面的Person类里面添加一个这样的方法
[OnSerialized]
public void OnSerialized(StreamingContext context)
{
Name = Name.ToUpper();
}
下面列出常用的一些特性(更多特性请参考MSDN)
[OnDeserialized] 对象在被反序列化后立即被调用
[OnDeserializing] 对象在反序列化之前被调用
[OnSerialized] 对象在序列化后被调用
[OnSerializing] 对象在序列化前被调用
其实看上去都是很简单的!一般只要标记[Serializable]特性,数据就可以通过选择的格式(二进制,Soap,XML)来进行持久化.
asp.net页面的viewstate也是使用序列化来保存对象的!如果对象想存放在ViewState里面,再供别的地方进行读取操作,就需要将对象标识为可序列化[Serializable];