zoukankan      html  css  js  c++  java
  • .net中对象序列化技术浅谈

    http://blog.csdn.net/zhoufoxcn/article/details/3978874

    序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。反之,反序列化根据流重新构造对象。此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件中“恢复”对象到序列化之前的状态。
    在.net中有提供了几种序列化的方式:
    二进制序列化
    XML序列化
    SOAP序列化

    二进制序列化
    所谓二进制序列化,指的是对象序列化之后是二进制形式的。二进制序列化是通过BinaryFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Binary命名空间下。

    XML序列化
    所谓XML序列化,是指对象序列化之后的结果是XML形式的。保存XML序列化是通过XmlSerializer 类来实现的, 这个类位于System.Xml.Serialization命名空间下。

    SOAP序列化
    所谓SOAP序列化是指对象序列化之后的结果符合SOAP协议,也就是可以通过SOAP协议传输(不知道SOAP协议?百度一下吧)。SOAP序列化是通过SoapFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Soap命名空间下,并且需要注意需要手动添加对这个命名空间的引用,如下图所示:
     

    下面编写一个类用于序列化和反序列化,这个类的代码如下:

    [c-sharp] view plaincopy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4.   
    5. namespace MySerializeDemo  
    6. {  
    7.     [Serializable]  
    8.     /// <summary>  
    9.     /// 要序列化的对象  
    10.     /// 作者:周公  
    11.     /// 编写时间:2009-03-10  
    12.     /// </summary>  
    13.     public class MyObject  
    14.     {  
    15.         //[NonSerialized]  
    16.         private string name;  
    17.         private DateTime birthday;  
    18.         private string homePlace;  
    19.         /// <summary>  
    20.         /// 出生地  
    21.         /// </summary>  
    22.         public string HomePlace  
    23.         {  
    24.             get { return homePlace; }  
    25.             set { homePlace = value; }  
    26.         }  
    27.    
    28.         /// <summary>  
    29.         /// 生日  
    30.         /// </summary>  
    31.         public DateTime Birthday  
    32.         {  
    33.             get { return birthday; }  
    34.             set { birthday = value; }  
    35.         }  
    36.    
    37.         /// <summary>  
    38.         /// 姓名  
    39.         /// </summary>  
    40.         public string Name  
    41.         {  
    42.             get { return name; }  
    43.             set { name = value; }  
    44.         }  
    45.    
    46.         /// <summary>  
    47.         /// 年龄  
    48.         /// </summary>  
    49.         public int Age  
    50.         {  
    51.             get { return DateTime.Now.Year - birthday.Year; }  
    52.         }  
    53.         /// <summary>  
    54.         /// override了ToString()方法  
    55.         /// </summary>  
    56.         /// <returns></returns>  
    57.         public override string ToString()  
    58.         {  
    59.             return string.Format("姓名:{0},生日:{1},出生地:{2},年龄:{3}",name,birthday,homePlace,Age);  
    60.         }  
    61.    
    62.     }  
    63. }  


    下面是分别用上面的三个类进行序列化和反序列化的代码:

    [c-sharp] view plaincopy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4. using System.IO;  
    5. using System.Runtime.Serialization.Formatters;  
    6. using System.Runtime.Serialization.Formatters.Binary;  
    7. using System.Runtime.Serialization.Formatters.Soap;  
    8. using System.Xml.Serialization;  
    9.   
    10. namespace MySerializeDemo  
    11. {  
    12.     class Program  
    13.     {  
    14.         static void Main(string[] args)  
    15.         {  
    16.             MyObject obj = new MyObject();  
    17.             obj.Birthday = new DateTime(1979, 11, 7);  
    18.             obj.HomePlace = "湖北";  
    19.             obj.Name = "周公";  
    20.             Console.WriteLine("========使用BinaryFormatter类进行序列化和反序列化。====");  
    21.             BinarySerialize(obj);  
    22.             BinaryDeserialize("C://MyObject.dat");  
    23.             Console.WriteLine("========使用SoapFormatter类进行序列化和反序列化。====");  
    24.             SOAPSerialize(obj);  
    25.             SOAPDeserialize("C://MyObject.soap");  
    26.             Console.WriteLine("========使用XmlSerializer类进行序列化和反序列化。====");  
    27.             XMLSerialize(obj);  
    28.             XMLDeserialize("C://MyObject.xml");  
    29.         }  
    30.         /// <summary>  
    31.         /// 二进制序列化对象  
    32.         /// </summary>  
    33.         /// <param name="obj"></param>  
    34.         public static void BinarySerialize(MyObject obj)  
    35.         {  
    36.             using (FileStream stream = new FileStream("C://MyObject.dat", FileMode.Create, FileAccess.Write))  
    37.             {  
    38.                 BinaryFormatter formater = new BinaryFormatter();  
    39.                 formater.Serialize(stream, obj);  
    40.                 Console.WriteLine("对象已经被序列化。" + obj.ToString());  
    41.             }  
    42.         }  
    43.         /// <summary>  
    44.         /// 二进制反序列化  
    45.         /// </summary>  
    46.         /// <param name="fileName"></param>  
    47.         public static void BinaryDeserialize(string fileName)  
    48.         {  
    49.             using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))  
    50.             {  
    51.                 BinaryFormatter formater = new BinaryFormatter();  
    52.                 MyObject obj=(MyObject)formater.Deserialize(stream);  
    53.                 Console.WriteLine("对象已经被反序列化。" + obj.ToString());  
    54.             }  
    55.         }  
    56.   
    57.         /// <summary>  
    58.         /// 二进制序列化对象  
    59.         /// </summary>  
    60.         /// <param name="obj"></param>  
    61.         public static void SOAPSerialize(MyObject obj)  
    62.         {  
    63.             using (FileStream stream = new FileStream("C://MyObject.soap", FileMode.Create, FileAccess.Write))  
    64.             {  
    65.                 SoapFormatter formater = new SoapFormatter();  
    66.                 formater.Serialize(stream, obj);  
    67.                 Console.WriteLine("对象已经被序列化。" + obj.ToString());  
    68.             }  
    69.         }  
    70.         /// <summary>  
    71.         /// 二进制反序列化  
    72.         /// </summary>  
    73.         /// <param name="fileName"></param>  
    74.         public static void SOAPDeserialize(string fileName)  
    75.         {  
    76.             using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))  
    77.             {  
    78.                 SoapFormatter formater = new SoapFormatter();  
    79.                 MyObject obj = (MyObject)formater.Deserialize(stream);  
    80.                 Console.WriteLine("对象已经被反序列化。" + obj.ToString());  
    81.             }  
    82.         }  
    83.         /// <summary>  
    84.         /// XML序列化  
    85.         /// </summary>  
    86.         /// <param name="obj"></param>  
    87.         public static void XMLSerialize(MyObject obj)  
    88.         {  
    89.             using (FileStream stream = new FileStream("C://MyObject.xml", FileMode.Create, FileAccess.Write))  
    90.             {  
    91.                 XmlSerializer serializer = new XmlSerializer(typeof(MyObject));  
    92.                 serializer.Serialize(stream, obj);  
    93.                 Console.WriteLine("对象已经被序列化。" + obj.ToString());  
    94.             }  
    95.         }  
    96.         /// <summary>  
    97.         /// XML反序列化  
    98.         /// </summary>  
    99.         /// <param name="fileName"></param>  
    100.         public static void XMLDeserialize(string fileName)  
    101.         {  
    102.             using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))  
    103.             {  
    104.                 XmlSerializer serializer = new XmlSerializer(typeof(MyObject));  
    105.                 MyObject obj = (MyObject)serializer.Deserialize(stream);  
    106.                 Console.WriteLine("对象已经被反序列化。" + obj.ToString());  
    107.             }  
    108.         }  
    109.     }  
    110. }  


    这个程序的运行效果如下:
     
    可见通过上面三个类都能实现将对象序列化保存,并且都能反序列化还原到对象被序列化之前的状态(这正是序列化意义所在,能保存对象运行时的状态并且还能还原)。如果运行上面的代码会在C盘根目录下创建三个文件,分别是MyObject.dat、MyObject.soap和MyObject.xml文件,因为MyObject.dat是二进制文件,所以无法查看文件的内容,但是我们可以打开MyObject.soap和MyObject.xml这两个文件来比较一下有什么区别。
    MyObject.soap文件的后缀虽然是.soap,但是还是可以用记事本打开的,下面是MyObject.soap文件的内容:

    [xhtml] view plaincopy
    1. <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">  
    2. <SOAP-ENV:Body>  
    3. <a1:MyObject id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">  
    4. <name id="ref-3">周公</name>  
    5. <birthday>1979-11-07T00:00:00.0000000+08:00</birthday>  
    6. <homePlace id="ref-4">湖北</homePlace>  
    7. </a1:MyObject>  
    8. </SOAP-ENV:Body>  
    9. </SOAP-ENV:Envelope>  


    MyObject.xml文件也可以用记事本打开,它的内容如下:

    [xhtml] view plaincopy
    1. <?xml version="1.0"?>  
    2. <MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
    3.   <HomePlace>湖北</HomePlace>  
    4.   <Birthday>1979-11-07T00:00:00</Birthday>  
    5.   <Name>周公</Name>  
    6. </MyObject>  


    熟悉SOAP协议的朋友一看MyObject.soap文件的内容就知道它符合SOAP协议,MyObject.xml文件毫无疑问是一个符合XML规范的文件。

    对代码作几点说明:
    1、如果采用BinaryFormatter类或者SoapFormatter类来实现序列化,则一定要给类加上Serializable属性,如代码中所示:

    [c-sharp] view plaincopy
    1. [Serializable]  
    2.     /// <summary>  
    3.     /// 要序列化的对象  
    4.     /// 作者:周公  
    5.     /// 编写时间:2009-03-10  
    6.     /// </summary>  
    7.     public class MyObject  


    如果不给要序列化的对象加上这个属性,那么采用采用BinaryFormatter类或者SoapFormatter类来实现序列化时会报异常,但使用XmlSerializer 类序列化对象时可以不用这个属性。
    2、另外,如果不想序列化某个字段,可以给其加上NonSerialized属性,这样在序列化时就不会保存这个这个字段的值了,比如不想序列化name这个字段,可以如下写代码:

    [c-sharp] view plaincopy
    1. //其它代码  
    2. //[NonSerialized]  
    3. private string name;  
    4. //其它代码  


    再次运行刚才的程序会得到如下效果:
     
    看有黄色底线部分,因为name字段不被序列化,所以通过二进制序列化和SOAP序列化之后再反序化就得不到原来的值了。
    3、最后还需要说明一点的是,SoapFormatter类在.net3.5开始已经过时了,微软建议使用BinaryFormatter类来序列化和反序列化了。

    周公

  • 相关阅读:
    设计模式之结构型外观模式
    设计模式之结构型装饰者模式
    设计模式之结构型组合模式
    设计模式之创建型建造者模式
    设计模式之创建型原型模式
    设计模式之创建型单例模式
    设计模式之创建型抽象工厂模式
    设计模式之创建型工厂模式
    设计模式之创建型简单工厂模式
    找出数组出现最多的元素,并返回出现的下标
  • 原文地址:https://www.cnblogs.com/carl2380/p/3061570.html
Copyright © 2011-2022 走看看