对象序列化 BinaryFormatter、XmlSerializer、SoapFormatter

来源:互联网 发布:平面美工设计 编辑:程序博客网 时间:2024/05/21 21:46

序列化:持久化(可能还包括传输)一个对象的状态到流(如文件流和内存流)的过程。        用最小花费来保存海量的(各种格式的)数据就变的轻而易举。序列化是用来通信的,服务端把数据序列化,发送到客户端,客户端把接收到的数据反序列化后对数据进行操作,完成后再序列化发送到服务端,服务端再反序列化数据后对数据进行操作。
 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据

序列化    :将对象状态转换为可保持或传输的格式的过程。
反序列化:它将流转换为对象。


    这两个过程结合起来,可以轻松地存储和传输数据。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。反之,反序列化根据流重新构造对象。此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件中“恢复”对象到序列化之前的状态。

    在.net中有提供了几种序列化的方式:
      1、二进制序列化
      2、XML序列化
      3、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.Linq;using System.Text;using System.IO;using System.Runtime.Serialization.Formatters.Binary;//二进制序列化using System.Xml.Serialization;//XML序列化using System.Runtime.Serialization.Formatters.Soap;//soap序列化namespace ConsoleApplication2{    [Serializable]    public class MyObject    {        private string name;        public string Name        {            get { return name; }            set { name = value; }        }        public override string ToString()        {            return String.Format("姓名:{0}", name);        }    }    class Program    {        static void Main(string[] args)        {            MyObject obj = new MyObject();               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");              Console.ReadKey();        }        /// <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>        /// soap序列化对象        /// </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>        /// soap反序列化        /// </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());            }        }    }    }


 

 

效果:

 

序列化意义所在,能保存对象运行时的状态并且还能还原。

 

二、序列化【传输】

using System;using System.Collections.Generic;using System.Linq;using System.Web;/// <summary>/// ObjModel 的摘要说明/// </summary>[Serializable]public class ObjModel{    public String Name { get; set; }    public String Value { get; set; }}

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Xml;using System.Xml.Serialization;public partial class _Default : System.Web.UI.Page{    protected void Page_Load(object sender, EventArgs e)    {        ObjModel obj = new ObjModel();        obj.Name = "姓名";        Deserialize(Serialiaze(obj),typeof(ObjModel));    }      /// <summary>    /// 序列化成字符串    /// </summary>    /// <param name="obj"></param>    /// <returns>序列化后的字符串</returns>    public static string Serialiaze(object obj)    {        XmlSerializer xs = new XmlSerializer(obj.GetType());        MemoryStream ms = new MemoryStream();        XmlTextWriter xtw = new XmlTextWriter(ms, System.Text.Encoding.UTF8);        xtw.Formatting = Formatting.Indented;        xs.Serialize(xtw, obj);        ms.Seek(0, SeekOrigin.Begin);        StreamReader sr = new StreamReader(ms);        string str = sr.ReadToEnd();        xtw.Close();        ms.Close();        return str;    }    /// <summary>    /// 反序列化 从字符串    /// </summary>    /// <param name="xml">xml字符串</param>    /// <param name="type">要生成的对象类型</param>    /// <returns>反序列化后的对象</returns>    public static object Deserialize(string xml, Type type)    {        XmlSerializer xs = new XmlSerializer(type);        StringReader sr = new StringReader(xml);        object obj = xs.Deserialize(sr);        return obj;    }}


三、控制生成的XML数据


1、MODEL

        [Serializable]        public class Radio //音乐        {            //高音扬声器            public bool hasTweeters;            //低音炮            public bool hasSubWoofers;            //配置设置            public double[] stationPresets;            [NonSerialized]            public string radioID = "XF-552RR6";        }        [Serializable]        public class Car        {            public Radio theRadio = new Radio();            public bool isHatchBack;//掀背车        }        [Serializable,        XmlRoot(Namespace="http://www.MyCompany.com")]        public class JamesBondCar : Car//007中德邦的车        {            [XmlAttribute]            public bool canFly;            [XmlAttribute]            public bool canSubmerge;        }

        [Serializable,
        XmlRoot(Namespace="http://www.MyCompany.com")]
        public class JamesBondCar : Car//007中德邦的车
        {
            [XmlAttribute]
            public bool canFly;
            [XmlAttribute]
            public bool canSubmerge;
        }

 2、序列化XML

            JamesBondCar jbc = new JamesBondCar();            jbc.canFly = true;            jbc.canSubmerge = false;            jbc.theRadio.stationPresets = new double[] { 89.3,105.1,97.1};            jbc.theRadio.hasTweeters = true;            using (FileStream fs = new FileStream("JamesBondCar.xml", FileMode.Create, FileAccess.Write))           {               XmlSerializer formatter = new XmlSerializer(typeof(JamesBondCar));               formatter.Serialize(fs, jbc);           }

3、JamesBondCar.xml

<?xml version="1.0"?>
<JamesBondCar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
canFly="true"
canSubmerge="false"
xmlns="http://www.MyCompany.com"
>
  <theRadio>
    <hasTweeters>true</hasTweeters>
    <hasSubWoofers>false</hasSubWoofers>
    <stationPresets>
      <double>89.3</double>
      <double>105.1</double>
      <double>97.1</double>
    </stationPresets>
    <radioID>XF-552RR6</radioID>
  </theRadio>
  <isHatchBack>false</isHatchBack>
</JamesBondCar>



四、序列化对象集合

        序列化对象集合:对一组对象进行持久化。
        只需要添加这组对象到容器(比如ArrayList或List<T>)中并序列化对象为你选择的流。


1、Model

        [Serializable]
        public class Radio //音乐
        {
            //高音扬声器
            public bool hasTweeters;
            //低音炮
            public bool hasSubWoofers;
            //配置设置
            public double[] stationPresets;

            [NonSerialized]
            public string radioID = "XF-552RR6";
        }
        [Serializable]
        public class Car
        {
            public Radio theRadio = new Radio();
            public bool isHatchBack;//掀背车
        }
        [Serializable,
        XmlRoot(Namespace="http://www.MyCompany.com")]
        public class JamesBondCar : Car//007中德邦的车
        {
            public JamesBondCar(bool skyWorthy,bool seaWorthy)
            {
                canFly = skyWorthy;
                canSubmerge = seaWorthy;
            }
            //XmlSerializer 需要一个默认构造函数
            public JamesBondCar() { }


            [XmlAttribute]
            public bool canFly;
            [XmlAttribute]
            public bool canSubmerge;
        }


2、对象集合序列化 XML

            List<JamesBondCar> myCars = new List<JamesBondCar>();            myCars.Add(new JamesBondCar(true,true));            myCars.Add(new JamesBondCar(true, false));            myCars.Add(new JamesBondCar(false,true));            myCars.Add(new JamesBondCar(false,false));            using (FileStream fs = new FileStream("JamesBondCar.xml", FileMode.Create, FileAccess.Write))           {               XmlSerializer formatter = new XmlSerializer(typeof(List<JamesBondCar>));               formatter.Serialize(fs, myCars);           }


3、JamesBondCar.sml

<?xml version="1.0"?><ArrayOfJamesBondCar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  <JamesBondCar canFly="true" canSubmerge="true">    <theRadio xmlns="http://www.MyCompany.com">      <hasTweeters>false</hasTweeters>      <hasSubWoofers>false</hasSubWoofers>      <radioID>XF-552RR6</radioID>    </theRadio>    <isHatchBack xmlns="http://www.MyCompany.com">false</isHatchBack>  </JamesBondCar>  <JamesBondCar canFly="true" canSubmerge="false">    <theRadio xmlns="http://www.MyCompany.com">      <hasTweeters>false</hasTweeters>      <hasSubWoofers>false</hasSubWoofers>      <radioID>XF-552RR6</radioID>    </theRadio>    <isHatchBack xmlns="http://www.MyCompany.com">false</isHatchBack>  </JamesBondCar>  <JamesBondCar canFly="false" canSubmerge="true">    <theRadio xmlns="http://www.MyCompany.com">      <hasTweeters>false</hasTweeters>      <hasSubWoofers>false</hasSubWoofers>      <radioID>XF-552RR6</radioID>    </theRadio>    <isHatchBack xmlns="http://www.MyCompany.com">false</isHatchBack>  </JamesBondCar>  <JamesBondCar canFly="false" canSubmerge="false">    <theRadio xmlns="http://www.MyCompany.com">      <hasTweeters>false</hasTweeters>      <hasSubWoofers>false</hasSubWoofers>      <radioID>XF-552RR6</radioID>    </theRadio>    <isHatchBack xmlns="http://www.MyCompany.com">false</isHatchBack>  </JamesBondCar></ArrayOfJamesBondCar>


五、自定义Soap/Binary序列化(推荐 特性定制序列化)

            序列化过程中更多的 干预构造处理目录树的过程

           参与对象序列化的过程,System.Runtime.Serialization 命名空间提供以下几种类型:


1、使用 ISerializable 自定义序列化

      被标记了[Serializable]的对象,拥有了实现ISerializable接口选项,序列化过程前序列化后 数据格式

        [Serializable]        class StringData : ISerializable        {            private string dataItemOne = "First data block";            private string dataItemTwo = "More data";            public StringData() { }            protected StringData(SerializationInfo si, StreamingContext ctx)            {                //从流中得到合并的成员变量                dataItemOne = si.GetString("First_Item").ToLower();                dataItemTwo = si.GetString("dataItemTwo").ToLower();            }            //实现ISerializable接口方法(字段数据必须持久化为大写格式)            void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)            {                //用格式化数据填充 SerializationInfo                info.AddValue("First_Item", dataItemOne.ToUpper());                info.AddValue("dataItemTwo", dataItemTwo.ToUpper());            }        }


序列化soap

            StringData MyDate = new StringData();            using (FileStream fs = new FileStream("StringData.soap", FileMode.Create, FileAccess.Write))            {                SoapFormatter formatter = new SoapFormatter();                formatter.Serialize(fs, MyDate);            }


2、使用特性定制序列化

            自.net 2.0 发布以来,定制序列化过程首选是【特性】不需要手动与输入的SerializationInfo参数交互
            如 

                  [OnSerializing] 允许指定方法在对象被序列化之前调用
                  [OnSerialized]  允许指定方法在对象被序列化之后立即被调用
                  [OnDeserializing] ............对象被反序列化之前调用
                  [OnDeserialized]  ............对象被反序列化之后立即被调用


   应用这个特性,必须定义方法接收一个 StreamingContext 参数并返回空

        [Serializable]        class StringData        {            private string dataItemOne = "First data block";            private string dataItemTwo = "More data";            [OnSerializing]            private void OnSerializing(StreamingContext context)            {                //序列化过程中,就得调用                dataItemOne = dataItemOne.ToUpper();                dataItemTwo = dataItemTwo.ToUpper();            }            [OnDeserialized]            private void OnDeserialized(StreamingContext context)            {                //一但反序列化过程结束,就得调用                dataItemOne = dataItemOne.ToLower();                dataItemTwo = dataItemTwo.ToLower();            }        }




转载自:http://blog.csdn.net/zhoufoxcn/article/details/3978874