XmlSerializer, DataContractSerializer 和 BinaryFormatter區別與用法分析

来源:http://www.cnblogs.com/shouce/archive/2016/06/02/5551760.html
-Advertisement-
Play Games

.NET提供了很多序列化對象的方法,瞭解他們之間的區別才能更好地確定使用哪一種序列化方式並正確地使用。本文從下麵幾個方面對標題中的三種序列化方法進行了分析。 範圍:Property Or Field Or Both 可見性:Public or Private Or All 可訪問性:Readonly ...


.NET提供了很多序列化對象的方法,瞭解他們之間的區別才能更好地確定使用哪一種序列化方式並正確地使用。本文從下麵幾個方面對標題中的三種序列化方法進行了分析。

  • 範圍:Property Or Field Or Both
  • 可見性:Public or Private Or All
  • 可訪問性:Readonly Property
  • 回調:指OnSerializing, OnSerialized, OnDeserializing, OnDeserialized這些回調。
  • 包含迴圈引用的對象
  • 包含Dictionary的對象
  • 亂序讀(XML)
  • 自定義序列化結果。
  • 對被序列化的類有沒有什麼Attribute要求。有時被序列化的對象位於第三方庫中,無法修改源代碼,如果要序列化這樣的對象,就不能使用一定要有Attribute的Serializer。

先把結果整理出來再分析:代碼可以從這裡下載,所寫測試可能並不全面,所以如果有什麼錯誤,歡迎大家指出,不然要誤人子弟了。不過有這篇更誤人子弟的文章殿底(Google top 1),我相信這個表不會更糟。

  XmlSerializer DataContractSerializer BinaryFormatter
範圍 Both Both Field Only
可見性 Public Only All All
只讀屬性 不支持 支持,但要加Attribute N/A
回調支持 不支持 支持 支持
迴圈引用 不支持 支持,但要加Attribute 支持
Dictionary 不支持 支持,專有格式 支持
亂序讀 支持 不支持 不支持
自定義格式 支持,要加Attribute 不支持Xml Attribute 通過介面
Attribute要求 不必要 不必要 必須有Serializable

有幾點需要解釋一下。

性能?大小?

在我寫的幾個測試用例中,無論對於簡單對象,還是嵌套對象,還是數組重覆引用對象,這幾個Serializer的性能和大小基本在一個數量級上。他們之間功能上的差異遠大於他們性能上的差異。這個時候,使用哪個方法的決策應該取決於功能及其約束,而不是性能。如果你在意性能,應該用第三方庫,如Google的protobuf-net。無論從性能、序列化結果的大小還是相容性上,protobuf-net比這三者都要優秀,當然,not human readable。

Attribute要求

不少同類文章都聲稱XmlSerializer和DataContractSerializer都要求在類上加相應的Attribute。但事實上並不是這樣。只有當你想要改變預設的序列化結果時,Attribute才是必要的。

最常見的一個錯誤就是,給XmlSerializer要用到的類加Serializable Attribute。這個Attribute其實是給BinaryFormatter和SoapFormatter用的,一般用在Remoting和Messaging上。

亂序讀

亂序讀的意思是,Deserialize的過程中,不對Xml節點的順序做要求。Xml本身就是一種標記性的,帶有聲明性的語言,多數基於Xml的網路協議都不會對Xml節點的順序做要求。比如常見的RSS,ATOM,OPDS等。

WCF使用的DataContractSerializer要求Xml節點順序要麼嚴格指定,要麼按字母順序排列,或許有性能上考慮,但是WCF的定位才是允許DataContractSerializer嚴格要求Xml節點順序的根本原因。WCF本身是用於通信的,其對序列化的定位,僅僅只是消息傳遞的手段,消息格式的嚴格定義並沒有什麼不好,而且調用方的代碼都可以通過WSDL來生成,自然也就更不會出現解析時的問題。所以不支持亂序讀完全是由其功能設定決定的。

XmlSerializer,在我看來可以做為Object Xml Mapping的工具,當然要儘可能支持所有Xml的標準。

自定義的支持

XmlSerializer和DataContractSerializer都支持IXmlSerializer介面。通過這個介面DataContractSerializer甚至可以支持Attribute,但是,這其實已經不是在使用DataContractSerializer的序列化機制了。而且在實際項目中也不具備可操作性。所以在上表中,還是把DataContractSerializer標記為不支持Xml Attribute。

還有一些常見的介面,如ISerializable和IDeserializationCallback是給BinaryFormatter用的,以支持自定義序列化的過程。這裡我很奇怪為了BinaryFormatter已經支持了OnDeserialized Attribute,為什麼還有這麼個介面來提供相似的功能。

一些小的細節

兩個Xml序列化方法還有一些小的挺有意思的差別,我試圖猜測產生這種差異的原因,卻沒想出來,或許是一些微軟員工不為人知的設計理念,也許只是寫代碼時的順心而為罷了。

  1. XmlSerializer不序列化Null值,DataContractSerializer預設會序列化Null值。
  2. DataContractSerializer與Attribute:對沒有任何Attribute的類,序列化所有Public的可讀可寫Property和Field;對僅僅加了Serializable Attribute的類,序列化所有可見性的Field(為了和BinaryFormatter行為一致嗎);如果僅僅加了DataContract Attribute,則什麼都不會序列化出來,一定要加DataMember。
  3. DataContract支持序列只讀屬性,但是屬性上要加DataMember.
  4. DataContractSerializer,僅僅加DataMember而不加DataContract會出異常。
  5. DataContractSerializer與ISerializable介面不相容,直接拋異常。
  6. DataContractSerializer支持IXmlSerializer介面,但是實現了這個介面,就不能加DataContract了。否則拋異常。這是什麼道理?
  7. XmlSerializer支持亂序讀的代價是,你不能控制你自己的生成的Xml的節點的順序。也就是說ElementName Attribute中不能指定Order。
  8. BinaryFormatter要求被序列化的類必須“滿城盡帶Serializable”。所以如果你改不了源代碼,序列化不了就是序列化不了。而XmlSerializable,你盡可以通過繼承的方式,把Internal和Protected的Property序列化出來。

小結

基於上面的客觀結果,相信你已經有了自己的判斷。我個人意見,DataContractSerializable就用在它應該用的地方吧,如果不是用WCF,還是不要用它了,它的序列化結果有一些微軟專屬的東西。對於來自網路的鬆散Xml介面數據,XmlSerializer是不二之選。如果想把對象完整地保存下來(數據與狀態),同時又不需要被人看。那就用BinaryFormatter吧。如果對性能或是數據大小要求比較高,那這三個就都能用,用protobuff吧。

補充

這些信息算是一種經驗,但是絕對不適合作面試或是筆試題用。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ApiView是.net api的介面文檔查看網站,用於解決分散式開發過程中的Api介面管理和溝通問題。 自動生成api文檔; 方便調試及第三方開發人員對接,可以應用在asp.net mvc,wcf,webservice 中使用; 代碼及原理都很簡單,方便修改和完善。 ...
  • 各級省份代碼: 各級市代碼: ...
  • 上次分享了控制器向視圖傳遞數據的4種方式,今天再來給大家講講MVC視圖中的數據如何提交到控制器。 我們可以通過以下幾種方式提交數據到控制器: 1、通過Request.Form讀取表單數據 在 控制器動作方法(Action)中,POST方法提交的表單可以使用Request.Form讀取其中的數據: < ...
  • 過濾器 過濾器(Filter)把附加邏輯註入到MVC框的請求處理,實現了交叉關註。所謂交叉關註(Cross-Cutting Concerns),是指可以用於整個應用程式,而又不適合放置在某個局部位置的功能,否則會打破關註分離模式。典型的例子有:登錄、授權、緩存等等。 使用過濾器 如果希望動作方法只能 ...
  • 一 什麼是LINQ? 二 簡單的Linq例子。(簡單形式我就不介紹了,主要以Lambda形式介紹)。 1 首先創建一個實體對象類並賦值。 public class Person { public int PId { get; set; } // 自增Id public string Name { g ...
  • 到達應用程式的每一個請求都是由控制器處理的。但要註意,不要把事務或數據存儲邏輯放到控制器中,也不要生成用戶界面。 在ASP.NET MVC框架中,控制器是含有請求處理邏輯的.NET類。其作用是封裝應用程式邏輯。也就是說,控制器要負責處理輸入請求、執行域模型上的操作,並選擇渲染給用戶的視圖。 控制器的 ...
  • 最近有客戶反饋系統導入EXECL進行數據處理超時了,我當時的第一反應,不可能啊我明明是做過性能優化的啊,怎麼還會超時呢,這是要有多少條數據才可能發生啊!於是找客戶要來了EXECL,發現有7500多條數據,備份完客戶資料庫進行代碼調試找出性能差的地方。都是一些平時老生常談的東西,可是又是很容易忽略的地 ...
  • Table中合併相同內容列的方法比較好辦,網上代碼也很多,參照了一些把它封裝成jquery 插件,調用起來還是蠻好用的。 這個地方稍微修改了下,有的時候td中內容雖然一樣,但是資料庫中的value卻是不一樣的,比如不同的公司,都有人事部,財務部, 公司A的財務部和公司B的財務部不能合併起來,所以我就 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...