对象序列化(笔记)

对象序列化,可以把一个对象序列化到一个文件上持久化保存,也可以从文件中读取对象.比如说我们要存储一个客户端程序,要根据用户的偏好(字体,界面风格之类的),需要一个有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];



posted on 2010-07-17 20:12  Ss_Andy  阅读(455)  评论(0编辑  收藏  举报