【转】net中对象序列化技术浅谈

it2022-05-09  31

本文转自:http://blog.csdn.net/zhoufoxcn/archive/2009/03/11/3978874.aspx

序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。例如,可以序列化一个对象,然后使用 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命名空间下,并且需要注意需要手动添加对这个命名空间的引用,如下图所示:  

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

using System;   using System.Collections.Generic;   using System.Text;     namespace MySerializeDemo   {       [Serializable]       /// <summary>       /// 要序列化的对象       /// 作者:周公       /// 编写时间:2009-03-10       /// </summary>       public class MyObject       {           //[NonSerialized]           private string name;           private DateTime birthday;           private string homePlace;           /// <summary>           /// 出生地           /// </summary>           public string HomePlace           {               get { return homePlace; }               set { homePlace = value; }           }               /// <summary>           /// 生日           /// </summary>           public DateTime Birthday           {               get { return birthday; }               set { birthday = value; }           }               /// <summary>           /// 姓名           /// </summary>           public string Name           {               get { return name; }               set { name = value; }           }               /// <summary>           /// 年龄           /// </summary>           public int Age           {               get { return DateTime.Now.Year - birthday.Year; }           }           /// <summary>           /// override了ToString()方法           /// </summary>           /// <returns></returns>           public override string ToString()           {               return string.Format("姓名:{0},生日:{1},出生地:{2},年龄:{3}",name,birthday,homePlace,Age);           }           }   }   下面是分别用上面的三个类进行序列化和反序列化的代码:

view plain copy to clipboard print ? using System;   using System.Collections.Generic;   using System.Text;   using System.IO;   using System.Runtime.Serialization.Formatters;   using System.Runtime.Serialization.Formatters.Binary;   using System.Runtime.Serialization.Formatters.Soap;   using System.Xml.Serialization;     namespace MySerializeDemo   {       class Program       {           static void Main(string[] args)           {               MyObject obj = new MyObject();               obj.Birthday = new DateTime(1979, 11, 7);               obj.HomePlace = "湖北";               obj.Name = "周公";               Console.WriteLine("========使用BinaryFormatter类进行序列化和反序列化。====");               BinarySerialize(obj);               BinaryDeserialize("C:""MyObject.dat");               Console.WriteLine("========使用SoapFormatter类进行序列化和反序列化。====");               SOAPSerialize(obj);               SOAPDeserialize("C:""MyObject.soap");               Console.WriteLine("========使用XmlSerializer类进行序列化和反序列化。====");               XMLSerialize(obj);               XMLDeserialize("C:""MyObject.xml");           }           /// <summary>           /// 二进制序列化对象           /// </summary>           /// <param name="obj"></param>           public static void BinarySerialize(MyObject obj)           {               using (FileStream stream = new FileStream("C:""MyObject.dat", FileMode.Create, FileAccess.Write))               {                   BinaryFormatter formater = new BinaryFormatter();                   formater.Serialize(stream, obj);                   Console.WriteLine("对象已经被序列化。" + obj.ToString());               }           }           /// <summary>           /// 二进制反序列化           /// </summary>           /// <param name="fileName"></param>           public static void BinaryDeserialize(string fileName)           {               using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))               {                   BinaryFormatter formater = new BinaryFormatter();                   MyObject obj=(MyObject)formater.Deserialize(stream);                   Console.WriteLine("对象已经被反序列化。" + obj.ToString());               }           }             /// <summary>           /// 二进制序列化对象           /// </summary>           /// <param name="obj"></param>           public static void SOAPSerialize(MyObject obj)           {               using (FileStream stream = new FileStream("C:""MyObject.soap", FileMode.Create, FileAccess.Write))               {                   SoapFormatter formater = new SoapFormatter();                   formater.Serialize(stream, obj);                   Console.WriteLine("对象已经被序列化。" + obj.ToString());               }           }           /// <summary>           /// 二进制反序列化           /// </summary>           /// <param name="fileName"></param>           public static void SOAPDeserialize(string fileName)           {               using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))               {                   SoapFormatter formater = new SoapFormatter();                   MyObject obj = (MyObject)formater.Deserialize(stream);                   Console.WriteLine("对象已经被反序列化。" + obj.ToString());               }           }           /// <summary>           /// XML序列化           /// </summary>           /// <param name="obj"></param>           public static void XMLSerialize(MyObject obj)           {               using (FileStream stream = new FileStream("C:""MyObject.xml", FileMode.Create, FileAccess.Write))               {                   XmlSerializer serializer = new XmlSerializer(typeof(MyObject));                   serializer.Serialize(stream, obj);                   Console.WriteLine("对象已经被序列化。" + obj.ToString());               }           }           /// <summary>           /// XML反序列化           /// </summary>           /// <param name="fileName"></param>           public static void XMLDeserialize(string fileName)           {               using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))               {                   XmlSerializer serializer = new XmlSerializer(typeof(MyObject));                   MyObject obj = (MyObject)serializer.Deserialize(stream);                   Console.WriteLine("对象已经被反序列化。" + obj.ToString());               }           }       }   }   这个程序的运行效果如下:   可见通过上面三个类都能实现将对象序列化保存,并且都能反序列化还原到对象被序列化之前的状态(这正是序列化意义所在,能保存对象运行时的状态并且还能还原)。如果运行上面的代码会在C盘根目录下创建三个文件,分别是MyObject.dat、MyObject.soap和MyObject.xml文件,因为MyObject.dat是二进制文件,所以无法查看文件的内容,但是我们可以打开MyObject.soap和MyObject.xml这两个文件来比较一下有什么区别。 MyObject.soap文件的后缀虽然是.soap,但是还是可以用记事本打开的,下面是MyObject.soap文件的内容: view plain copy to clipboard print ? <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/">  <SOAP-ENV:Body>  <a1:MyObject id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">  <name id="ref-3">周公</name>  <birthday>1979-11-07T00:00:00.0000000+08:00</birthday>  <homePlace id="ref-4">湖北</homePlace>  </a1:MyObject>  </SOAP-ENV:Body>  </SOAP-ENV:Envelope>   MyObject.xml文件也可以用记事本打开,它的内容如下:

view plain copy to clipboard print ? <?xml version="1.0"?>  <MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">    <HomePlace>湖北</HomePlace>    <Birthday>1979-11-07T00:00:00</Birthday>    <Name>周公</Name>  </MyObject>   熟悉SOAP协议的朋友一看MyObject.soap文件的内容就知道它符合SOAP协议,MyObject.xml文件毫无疑问是一个符合XML规范的文件。

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

view plain copy to clipboard print ? [Serializable]       /// <summary>       /// 要序列化的对象       /// 作者:周公       /// 编写时间:2009-03-10       /// </summary>       public class MyObject   如果不给要序列化的对象加上这个属性,那么采用采用BinaryFormatter类或者SoapFormatter类来实现序列化时会报异常,但使用XmlSerializer 类序列化对象时可以不用这个属性。 2、另外,如果不想序列化某个字段,可以给其加上NonSerialized属性,这样在序列化时就不会保存这个这个字段的值了,比如不想序列化name这个字段,可以如下写代码:

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

周公 2009-03-11 0:17

转载于:https://www.cnblogs.com/feima-lxl/archive/2009/03/29/1424250.html

相关资源:数据结构—成绩单生成器

最新回复(0)