zl程序教程

您现在的位置是:首页 >  后端

当前栏目

序列化、反序列化的版本控制以及序列化、反序列化集合对象

集合对象 以及 序列化 版本控制
2023-09-11 14:16:44 时间

当涉及到跨进程甚至是跨域传输数据的时候,我们需要把对象序列化和反序列化。

首先可以使用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;

        }