首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 系列(四)深入解析 .NET 序列化機制(上):BinaryFormatter、SoapFormatter 與 XmlSerializer

     編輯:關於.NET

前言:為什麼需要序列化?

在分散式應用開發中,序列化是核心基礎設施之一。簡單來說,序列化是將物件的狀態轉換為可儲存或可傳輸的位元組序列,反序列化則是將位元組序列還原為物件。這主要服務於兩大場景:

  • 物件持久化:將物件寫入磁碟、資料庫或快取,以便後續重用。
  • 跨程序域/跨機器通訊:在 Remoting、WCF、Web Services 等分散式技術中,物件需透過網路傳輸,必須先序列化為位元組流。

.NET Framework 針對不同通訊協定與場景,提供了三大類序列化器。本文將逐一剖析 BinaryFormatter、SoapFormatter 以及 XmlSerializer 的運作原理、適用場景與程式碼實作。

一、Remoting 專用:BinaryFormatter 與 SoapFormatter

這兩個序列化器皆實作 IRemotingFormatter 介面,專為 .NET Remoting 設計。Remoting 支援 TCP 與 HTTP 通道,BinaryFormatter 用於 TCP(高效能、二進位),SoapFormatter 用於 HTTP(XML 格式、穿透防火牆)。兩者具有強烈的 .NET 平台特徵,序列化資料中包含完整型別資訊(完整型別名稱、版本、文化特性、公開金鑰 Token),並具備型別保真特性:所有欄位(含私有欄位)皆會序列化,除非標記 [NonSerialized];屬性不序列化(因屬性僅為存取器)。

1. SoapFormatter 實作範例

命名空間:System.Runtime.Serialization.Formatters.Soap
組件:system.runtime.serialization.formatters.soap.dll

步驟 1:定義可序列化類別

[Serializable]
public class Book
{
    private string name;
    private string address1;
    private string address2;
    [NonSerialized]
    private string address_invisible = "shenzhen";
    public string author;
    public string Name { get { return name; } set { name = value; } }
    public Book() { address1 = address2 = "shenzhen"; }
}

重點:類別必須標記 [Serializable],私有欄位預設會被序列化,[NonSerialized] 可排除特定欄位。

步驟 2:準備物件與串流

MemoryStream stream = new MemoryStream();
Book book = new Book { Name = "我的第一本書", author = "chnking" };

步驟 3:序列化


SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, book);
// 注意:Serialize 後 stream.Position 在尾端,讀取前需歸零
stream.Position = 0;
byte[] data = stream.GetBuffer();
string xml = Encoding.UTF8.GetString(data); // SoapFormatter 預設 UTF-8

步驟 4:觀察序列化結果

產生的 XML 包含完整型別資訊(組件名、版本、公開金鑰 Token)、所有欄位值,且同一物件參考(address1、address2 指向同一字串)會以 ID 參考方式保留,避免重複序列化。標記 [NonSerialized] 的欄位不會出現。

SoapFormatter 序列化結果

步驟 5:反序列化


stream.Position = 0;
SoapFormatter formatter = new SoapFormatter();
Book restored = (Book)formatter.Deserialize(stream);
// address_invisible 因未序列化,反序列化後為 null

2. BinaryFormatter 實作範例

命名空間:System.Runtime.Serialization.Formatters.Binary
組件:mscorlib.dll

用法與 SoapFormatter 幾乎相同,差異在於輸出為緊湊二進位格式,效能最高、體積最小,但不可讀、跨平台性差。序列化結果中同樣包含型別資訊與物件參考關係。


BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, book);
// 二進位資料夾雜字元,仍以 UTF-8 解碼檢視可見型別資訊

BinaryFormatter 反序列化結果

二、Web Services 標準:XmlSerializer

XmlSerializer 是 ASP.NET Web Services 預設序列化器,遵循 XML Schema 標準,輸出不含 .NET 型別資訊,僅序列化公有欄位與可讀寫屬性,不支援私有欄位、唯讀屬性、方法、索引子。這意味著它不具備型別保真,反序列化後的物件可能與原物件不同(私有狀態遺失),但適合異構系統整合。

命名空間:System.Xml.Serialization
組件:system.xml.dll

1. 使用屬性控制 XML 輸出格式

透過 XmlRootAttribute、XmlAttribute、XmlElementAttribute 等屬性,可精確控制根元素名稱、命名空間、成員呈現為屬性或元素、XML Schema 資料型別、Null 值處理等。


[XmlRoot(ElementName = "BOOK", Namespace = "https://www.chnking.com", IsNullable = true)]
public class Book
{
    private string name;
    public string address1;
    public string address2;
    [XmlAttribute(AttributeName = "Author", Namespace = "https://www.chnkingAttr.com", DataType = "NMTOKEN")]
    public string author;
    [XmlElement(ElementName = "NamePro", Namespace = "https://www.chnkingName.com", DataType = "NMTOKEN", IsNullable = true)]
    public string Name { get { return name; } set { name = value; } }
    public Book() { address1 = address2 = "shenzhen"; }
}

範例中 author 序列化為屬性,Name 為元素,DataType="NMTOKEN" 會將不合法字元(如 ^)轉為十六進位 ASCII(_x005E_)。

2. 序列化與反序列化


XmlSerializer serializer = new XmlSerializer(typeof(Book));
serializer.Serialize(stream, book); // 需傳入型別
// 反序列化
stream.Position = 0;
Book restored = (Book)serializer.Deserialize(stream);

XmlSerializer 序列化結果

觀察重點:address1、address2 皆完整輸出值(非參考),因 XmlSerializer 面向資料而非物件圖;author 屬性值 ^chnking 中的 ^ 被轉義。

3. 驗證 Web Services 一致性

建立同樣回傳 Book 的 Web Service,瀏覽器呼叫後輸出的 XML 與 XmlSerializer 直接序列化結果完全一致,證明兩者共用同一序列化引擎。

Web Service 回傳 XML

4. 從 XSD 產生類別

當雙方預先約定 Schema 時,可用 xsd.exe 由 XSD 產生符合該結構的 .NET 類別:

xsd test2.xsd test1.xsd test.xsd /c

產生的類別自動包含對應的序列化屬性,序列化後的 XML 符合原始 XSD 定義。

XSD 產生類別序列化結果

總結與選型建議

序列化器適用場景輸出格式型別保真跨平台
BinaryFormatter.NET Remoting (TCP)、高效能內部通訊二進位是否
SoapFormatter.NET Remoting (HTTP)、需 XML 可讀性SOAP XML是部分
XmlSerializerASP.NET Web Services、異構系統整合標準 XML否是

下一篇將繼續探討 WCF 中的 DataContractSerializer 與序列化進階主題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved