天天看點

c#中的序列化2.使用二進制序列化和反序列化3.使用SOAP方式序列化和反序列化4.使用XML方式序列化和反序列化5.XML序列化對象詳解6.自定義序列化(僅适用于二進制與SOAP)

1.對象的序列化

NET支援對象序列化有以下幾種方式:

二進制序列化:對象序列化之後是二進制形式的,通過BinaryFormatter類來實作的,這個類位于System.Runtime.Serialization.Formatters.Binary命名空間下。

SOAP序列化:對象序列化之後的結果符合SOAP協定,也就是可以通過SOAP 協定傳輸,通過System.Runtime.Serialization.Formatters.Soap命名空間下的SoapFormatter類來實作的。

XML序列化:對象序列化之後的結果是XML形式的,通過XmlSerializer 類來實作的,這個類位于System.Xml.Serialization命名空間下。XML序列化不能序列化私有資料。

差別

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

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

使用特性對序列化的控制

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

針對二進制情況的序列化嗎,将對象序列化,也就一位置是将對象(比如Person對象)轉換為二進制資料。反序列化是将二進制資料還原為對象。

對象是稍縱即逝的,不僅程式重新開機、作業系統重新開機會造成對象的消失,就是退出函數範圍等都可能造成對象的消失,序列化/反序列化就是為了保持對象的持久化。就像用DV錄像(序列化)和用播放器播放(反序列化)一樣。

BinaryFormatter類有兩個方法:

void Serialize(Stream stream, object graph)  對象graph序列化到stream中;

object Deserialize(Stream stream)               将對象從stream中反序列化,傳回值為反序列化得到的對象

例如,序列化:

<a></a>

反序列化:

不是所有對象都能序列化,隻有可序列化的對象才能序列化,在類聲明上添加[Serializable],對象的屬性、字段的類型也必須可序列化。

反序列的項目中必須有同樣的類,否則不能反序列化。

序列化的應用:

         ASP.Net、ViewState、WCF、.Net Remoting、ASP.Net Cache 、叢集等。

 二進制序列化與反序列化

使用二進制序列化,必須為每一個要序列化的的類和其關聯的類加上[Serializable]特性,對類中不需要序列化的成員可以使用[NonSerialized]特性。

二進制序列化對象時,能序列化類的所有成員(包括私有的),且不需要類有無參數的構造方法。

使 用二進制格式序列化時,它不僅是将對象的字段資料進行持久化,也持久化每個類型的完全限定名稱和定義程式集的完整名稱(包括包稱、版本、公鑰标記、區域 性),這些資料使得在進行二進制格式反序列化時亦會進行類型檢查。是以反序列化時的運作環境要與序列化時的運作環境要相同,否者可能會無法反序列化成功。

思考(面試題):深度拷貝。淺層拷貝。先手寫淺層拷貝、深層拷貝的代碼,了解了概念再談用MemberwiseClone 、DeepCopy。

見備注: 寫代碼拷貝,實作ICloneable方法,内部調用MemberwiseClone .

程式示例

SOAP序列化與反序列化

 SOAP序列化與反序列化

SOAP序列化與二進制序列化的差別是:SOAP序列化不能序列化泛型類型。與二進制序列化一樣在序列化時不需要向序列化器指定序列化對象的類型。而XML序列化需要向XML序列化器指定序列化對象的類型。

 XML序列化與反序列

使用XML序列化或反序列化時,需要對XML序列化器指定需要序列化對象的類型和其關聯的類型。

XML序列化隻能序列化對象的公有屬性,并且要求對象有一個無參的構造方法,否者無法反序列化。

[Serializable]和[NonSerialized]特性對XML序列化無效!是以使用XML序列化時不需要對對象增加[Serializable]特性。

(1)說明

本節主要介紹:使用特性控制對象序列化成XML檔案的格式。

(2)使用XmlElement(預設值)

類聲明:

1

2

3

4

5

6

7

<code>public</code> <code>class</code> <code>Person</code>

<code> </code><code>{</code>

<code>        </code><code>[XmlElement]</code>

<code>        </code><code>public</code> <code>string</code> <code>Name;</code><code>//使用[XmlElement]特性</code>

<code>        </code><code>public</code> <code>bool</code> <code>Sex;</code><code>//預設使用了[XmlElement]特性</code>

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

<code>}</code>

序列化生成的XML檔案:

<code>&lt;</code><code>Personxmlns:xsi</code><code>="..."xmlns:xsd="..."&gt;</code>

<code>  </code><code>&lt;</code><code>Name</code><code>&gt;李志偉&lt;/</code><code>Name</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>Sex</code><code>&gt;true&lt;/</code><code>Sex</code><code>&gt;</code>

<code>&lt;/</code><code>Person</code><code>&gt;</code>

(3)使用XmlAttribute

8

<code>        </code><code>public</code> <code>string</code> <code>Name;</code>

<code>        </code><code>[XmlAttribute]</code>

<code>        </code><code>public</code> <code>bool</code> <code>Sex;</code>

<code> </code><code>}</code>

<code>&lt;</code><code>Personxmlns:xsi</code><code>="..."xmlns:xsd="..."Sex="true"&gt;</code>

(4)使用XmlText

<code>    </code><code>{</code>

<code>        </code><code>[XmlText]</code>

<code>    </code><code>}</code>

<code>&lt;</code><code>Personxmlns:xsi</code><code>="..."xmlns:xsd="..."Sex="true"&gt;李志偉&lt;/</code><code>Person</code><code>&gt;</code>

(5)使用XmlType和XmlAttribute(重命名節點名稱)

9

<code>[XmlType(</code><code>"個人資訊"</code><code>)]</code>

<code>    </code><code>public</code> <code>class</code> <code>Person</code>

<code>        </code><code>[XmlAttribute(</code><code>"姓名"</code><code>)]</code>

<code>        </code><code>[XmlAttribute(</code><code>"性别"</code><code>)]</code>

<code>&lt;個人資訊xmlns:xsi="..."xmlns:xsd="..."姓名="李志偉"性别="true" /&gt;</code>

(6)清單和數組的序列化

 清單和數組的序列化,類聲明

<code>&lt;</code><code>ArrayOf</code><code>個人資訊xmlns:xsi="..."xmlns:xsd="..."&gt;</code>

<code>  </code><code>&lt;個人資訊姓名="李志偉"性别="true" /&gt;</code>

<code>&lt;/</code><code>ArrayOf</code><code>個人資訊&gt;</code>

注意:發現此時的XML檔案的根節點名稱變了。此時要重命名根節點應使用如下方式:

 View Code

<code>&lt;人員資訊xmlns:xsi="..."xmlns:xsd="..."&gt;</code>

<code>&lt;/人員資訊&gt;</code>

(7)清單和數組的作為資料成員的序列化

 清單和數組的作為資料成員的序列化

<code>&lt;</code><code>PersonArrayxmlns:xsi</code><code>="..."xmlns:xsd="..."&gt;</code>

<code>  </code><code>&lt;</code><code>Array</code><code>&gt;</code>

<code>    </code><code>&lt;個人資訊姓名="李志偉"性别="true" /&gt;</code>

<code>  </code><code>&lt;/</code><code>Array</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>Person</code><code>姓名="李志偉"性别="true" /&gt;</code>

<code>&lt;/</code><code>PersonArray</code><code>&gt;</code>

注意:假設這裡需要為Array和Person的節點重命名,代碼如下:

<code>  </code><code>&lt;人員資訊&gt;</code>

<code>  </code><code>&lt;/人員資訊&gt;</code>

注意:把“人員資訊”節點去掉呢(直接出現“個人資訊”節點)

&lt;PersonArrayxmlns:xsi="..."xmlns:xsd="..."&gt;

  &lt;個人資訊姓名="李志偉"性别="true" /&gt;

  &lt;Person姓名="李志偉"性别="true" /&gt;

&lt;/PersonArray&gt;

(8)類型繼承與反序列化

 類型繼承與反序列化

注意:同時為清單成員指定多個[XmlArrayItem(typeof(XXX))]可實作多種派生類型混在一起輸出。

(9)排除不需要序列化的成員

    public class Person

    {

        public string Name;

        [XmlIgnore]// 這個屬性将不會參與序列化

        public bool Sex;

        public Person() { }

    }

(10)強制指定成員的序列化順序

public class Person

{

[XmlElement(Order = 2)]

public string Name;

[XmlElement(Order = 1)]

public bool Sex;

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

}

(11)自定義序列化行為

 自定義序列化

&lt;Person姓名="李志偉"性别="男" /&gt;

(12)序列化設定XML命名空間

[XmlRoot(Namespace = "http://msdn.microsoft.com/vsdh.xsd")]

public Person() { }

<code>&lt;</code><code>Personxmlns:xsi</code><code>="..."xmlns:xsd="..."xmlns="http://msdn.microsoft.com/vsdh.xsd"&gt;</code>

<code>  </code><code>&lt;</code><code>Name</code><code>&gt;李志偉A&lt;/</code><code>Name</code><code>&gt;</code>

(13)XML的使用建議

在服務端,C#代碼中:

1. 建議不用使用低級别的XML API來使用XML,除非你是在設計架構或者通用類庫。

2. 建議使用序列化、反序列化的方法來生成或者讀取XML

3. 當需要考慮使用XML時,先不要想着XML結構,先應該定義好資料類型。

4. 清單節點不要使用[XmlElement],它會讓所有子節點【更新】,顯得結構混亂。

5. 如果希望序列化的XML長度小一點,可以采用[XmlAttribute],或者指定一個更短小的别名。

6. 不要在一個清單中輸出不同的資料類型,這樣的XML結構的可讀性不好。

7. 盡量使用UTF-8編碼,不要使用GB2312編碼。

在用戶端,JavaScript代碼中,我不建議使用XML,而是建議使用JSON來代替XML,因為:

1. XML文本的長度比JSON要長,會占用更多的網絡傳輸時間(畢竟資料儲存在服務端,是以傳輸是免不了的)。

2. 在JavaScritp中使用XML比較麻煩(還有浏覽器的相容問題),反而各種浏覽器對JSON有非常好的支援。

(14)反序列化的使用總結

如果XML是由類型序列化得到那的,那麼反序列化的調用代碼是很簡單的,反之,如果要面對一個沒有類型的XML,就需要我們先設計一個(或者一些)類型出來,這是一個逆向推導的過程,請參考以下步驟:

1. 首先要分析整個XML結構,定義與之比對的類型,

2. 如果XML結構有嵌套層次,則需要定義多個類型與之比對,

3. 定義具體類型(一個層級下的XML結構)時,請參考以下表格。

(1)自定義序列化的實作方式

可 以通過在對象上實作 ISerializable 接口來自定義序列化過程。這一功能在反序列化後成員變量的值失效時尤其有用,但是需要為變量提供值以重建對象的完整狀态。要實作 ISerializable,需要實作 GetObjectData()方法以及一個特殊的構造函數,在反序列化對象時要用到此構造函數。

(2)示例程式

注 意:在序列化過程中調用 GetObjectData()時,需要填充方法調用中提供的 SerializationInfo對象。隻需按名稱/值對的形式添加将要序列化的變量。其名稱可以是任何文本。隻要已序列化的資料足以在反序列化過程中 還原對象,便可以自由選擇添加至 SerializationInfo 的成員變量。如果基對象實作了 ISerializable,則派生類應調用其基對象的 GetObjectData()方法。同樣,在反序列化時也會調用含有(SerializationInfo info, StreamingContext context)參數的特殊的夠着方法!否者将無法反序列化!!!

參考文章:

<a href="http://www.jb51.net/article/48470.htm" target="_blank">1. c#對象反序列化與對象序列化示例詳解</a>

沒有整理與歸納的知識,一文不值!高度概括與梳理的知識,才是自己真正的知識與技能。 永遠不要讓自己的自由、好奇、充滿創造力的想法被現實的架構所束縛,讓創造力自由成長吧! 多花時間,關心他(她)人,正如别人所關心你的。理想的騰飛與實作,沒有别人的支援與幫助,是萬萬不能的。

    本文轉自wenglabs部落格園部落格,原文連結:http://www.cnblogs.com/arxive/p/5709864.html,如需轉載請自行聯系原作者