C#對象序列化

要讓一個對象支持.Net序列化服務,用戶必須爲每一個關聯的類加上[Serializable]特性。如果類中有些成員不適合參與序列化(比如:密碼字段),可以在這些域前加上[NonSerialized]特性。

  C#支持三種序列化格式:二進制格式(使用BinaryFormatter序列化器)、SOAP格式(使用SoapFormatter序列化器)、XML格式(使用XmlSerializer序列化器)。這三種序列化器的區別如下:

  二進制格式可序列化一個類型的所有可序列化字段,不管它是公共字段還是私有字段。SOAP格式和XML格式僅能序列化公共字段或擁有公共屬性的私有字段,未通過屬性公開的私有字段將被忽略。

  使用二進制格式序列化時,它不僅是將對象的字段數據進行持久化,也持久化每個類型的完全限定名稱和定義程序集的完整名稱(包括包稱、版本、公鑰標記、區域性),這些數據使得在進行二進制格式反序列化時亦會進行類型檢查。SOAP格式序列化通過使用XML命名空間來持久化原始程序集信息。而XML格式序列化不會保存完整的類型名稱或程序集信息。這便利XML數據表現形式更有終端開放性。如果希望儘可能延伸持久化對象圖的使用範圍時,SOAP格式和XML格式是理想選擇。

  BinaryFormatter和SoapFormatter類型通過實現IFormatter和IRemotingFormatter接口實現序列化。

  IFormatter接口定義了核心的Serialize和Deserialize方法用於序列化和反序列化。

  IRemotingFormatter接口重載了Serialize和Deserialize方法,使風格更適合分佈式持久化。

  示例代碼:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.IO;
using System.Xml.Serialization;

namespace CollectionSerialize
{
    class Program
    {
        static void Main(string[] args)
        {
            //文件名稱
            string fileName = "Programmers.dat";

            //創建Programmer列表,並添加對象
            List<Programmer> list = new List<Programmer>();
            list.Add(new Programmer("Coder1", false, "C"));
            list.Add(new Programmer("Coder2", false, "C++"));
            list.Add(new Programmer("Coder3", false, "Java"));

            //創建文件流
            Stream fStream = null;
            fStream = FileReset(fStream, fileName);

            //使用二進制序列化器
            BinaryFormatter binFormat = new BinaryFormatter();
            //將list序列化到文件中
            binFormat.Serialize(fStream, list);
            //清空列表
            list.Clear();
            //重置流位置
            fStream.Position = 0;
            //反序列化,注意要將結果轉型
            list = (List<Programmer>)binFormat.Deserialize(fStream);

            //輸出
            Print(list);
            fStream = FileReset(fStream, fileName);

            //使用XML序列化
            //注意使用此構造器時必須在第一個參數傳入序列化的類型,第二個參數傳入序列化所涉及的相關類型
            XmlSerializer xmlFormat = 
                new XmlSerializer(typeof(List<Programmer>), 
                new Type[] { typeof(Programmer), typeof(Person) });
            //反序列化
            xmlFormat.Serialize(fStream, list);
            list.Clear();
            fStream.Position = 0;
            //反序列化,注意要將結果轉型
            list = (List<Programmer>)xmlFormat.Deserialize(fStream);

            Print(list);
            fStream = FileReset(fStream, fileName);

            //使用SOAP序列化
            SoapFormatter soapFormat = new SoapFormatter();
            //序列化,Soap不能序列化泛型對象,所以只能指定序列化一個Programmer對象
            soapFormat.Serialize(fStream, list[0]);
            list.Clear();
            fStream.Position = 0;
            //反序列化
            list.Add((Programmer)soapFormat.Deserialize(fStream));

            Print(list);
            fStream.Close();

            Console.ReadKey();
        }

        //輸出程序員列表
        static void Print(List<Programmer> list)
        {
            Console.WriteLine("程序員信息列表:");
            foreach (Programmer p in list)
            {
                Console.WriteLine("姓名:{0} 性別:{1} 編程語言:{2}", 
                    p.Name, p.Sex.ToString(), p.Language);
            }
        }

        //重置文件
        static FileStream FileReset(Stream fStream, string fileName)
        {
            //關閉文件流
            if (fStream != null)
            {
                fStream.Close();
            }
            
            //刪除文件
            File.Delete(fileName);
            //新建文件流
            return new FileStream(fileName, FileMode.OpenOrCreate, 
             FileAccess.ReadWrite, FileShare.None);
        }
    }

    [Serializable]  //必須添加序列化特性
    public class Person
    {
        //姓名
        public string Name;
        //性別
        public bool Sex;

        //必須提供無參構造器,否則XmlSerializer將出錯
        public Person() { }

        //構造函數
        public Person(string name, bool sex)
        {
            this.Name = name;
            this.Sex = sex;
        }
    }

    [Serializable]  //必須添加序列化特性
    public class Programmer : Person
    {
        //編程語言
        public string Language;

        //必須提供無參構造器,否則XmlSerializer將出錯
        public Programmer() { }

        //構造函數
        public Programmer(string name, bool sex, string language)
            : base(name, sex)
        {
            this.Language = language;
        }
    }
}


  程序運行結果如下:

  需要注意的是:

  1. SoapFormatter不能序列化泛型對象。

  2. XmlSerializer的構造器需要傳入序列化涉及的相關類型信息。

發佈了55 篇原創文章 · 獲贊 21 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章