序列化、反序列化的版本控制以及序列化、反序列化集合对象
当涉及到跨进程甚至是跨域传输数据的时候,我们需要把对象序列化和反序列化。
首先可以使用Serializable特性。
[Serializable]public class Person{public string _firstName;public string _secondName;//序列化[OnSerializing]internal void OnSerializing(StreamingContext context){_firstName = _firstName.ToUpper();_secondName = _secondName.ToUpper();}//反序列化[OnDeserialized]internal void OnDeserialized(StreamingContext context){_firstName = _firstName.ToLower();_secondName = _secondName.ToLower();}}
当然,也可以实现ISerializable接口。在接口方法GetObjectData完成序列化,把信息保存到SerializationInfo中,在构造函数中反序列化,把信息从SerializationInfo中读取出来。
[Serializable]public class Person : ISerializable{public string _firstName;public string _secondName;public Person(){}//反序列化public Person(SerializationInfo si, StreamingContext context){_firstName = si.GetString("first").ToLower();_secondName = si.GetString("second").ToLower();}//序列化public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("first", _firstName.ToUpper());info.AddValue("second",_secondName.ToUpper());}}
□ 对序列化和反序列化对象进行版本控制
下面的类,描述了对象的第一个版本。
[Serializable]public class SomeClass : ISerializable{private int a;public SomeClass(){}public SomeClass(SerializationInfo info, StreamingContext context){a = info.GetInt32("myval");}public void GetObjectData(SerializationInfo, StreamingContext context){info.AddValue("VERSION",1);info.AddValue("myval", a);}}
现在SomeClass要增加一个私有字段,成为版本二。
[Serializable]public class SomeClass : ISerializable{private int a;private string b;public SomeClass(){}public SomeClass(SerializationInfo info, StreamingContext context){int VERSION = info.GetInt32("VERSION");a = info.GetInt32("a");if(VERSION > 1){b = info.GetString("another");}else{b = "默认值";}}public void GetObjectData(SerializationInfo, StreamingContext context){info.AddValue("VERSION",2);info.AddValue("myval", a);info.AddValue("another", b);}}
□ 把集合对象序列化到文件并反序列化读出
如果一个集合对象需要实现序列化和反序列化,那么集合元素对象必须可以被序列化和反序列化,并且集合元素对象中的对象属性也必须可以被序列化和反序列化,依此类推。
[Serializable]public class Car : ISerializable{private string _model;private int _year;private Owner _owner;public Car(){}public Car(SerializationInfo info, StreamingContext context){this._model = (string) info.GetValue("Model", typeof (string));this._year = (int) info.GetValue("Year", typeof (int));this._owner = (Owner) info.GetValue("Owner", typeof (Owner));}public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("Model",this._model);info.AddValue("Year", this._year);info.AddValue("Owner", this._owner);}}[Serializable]public class Owner : ISerializable{private string _name;public Owner(){}public Owner(SerializationInfo info, StreamingContext context){this._name = (string) info.GetValue("Name", typeof (string));}public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("Name", this._name);}}
以上,我们想序列化Car的集合到文件中,再反序列化Cars的集合读取出来。那么,我们必须让Car可以被序列化和反序列化,Car的属性对象Owner也必须可以被序列化和反序列化。
接着,用来封装Car集合的一个类。
[Serializable]public class CarsList : ISerializable{private List<Car> _cars;public List<Car> Cars{get { return this._cars; }set { this._cars = value; }}public CarsList(){}public CarsList(SerializationInfo info, StreamingContext context){this._cars = (List<Car>) info.GetValue("Cars", typeof (List<Car>));}public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("Cars", this._cars);}}
针对CarsList写一个序列化和反序列化的帮助类。
public class SerializerHelper{public SerializerHelper(){}//序列化public void SerializeObject(string fileName, CarsList carsList){//根据文件名打开流Stream stream = File.Open(fileName, FileMode.Create);BinaryFormatter bFormatter = new BinaryFormatter();//把对象序列化到流中bFormatter.Serialize(stream,carsList);stream.Close();}//反序列化public CarsList DeserializeObject(string fileName){CarsList carsList;//根据文件名打开流Stream stream = File.Open(fileName, FileMode.Open);BinaryFormatter bfFormatter = new BinaryFormatter();carsList = (CarsList)bfFormatter.Deserialize(stream);stream.Close();return carsList;}}
在客户端按如下调用:
static void Main(string[] args){List<Car> cars = new List<Car>();CarsList carsList = new CarsList();carsList.Cars = cars;SerializerHelper serializerHelper = new SerializerHelper();serializerHelper.SerializeObject(@"temp.txt", carsList);carsList = serializerHelper.DeserializeObject(@"temp.txt");cars = carsList.Cars;}