序列化將物件狀態轉為可儲存/傳輸格式(位元組流、XML、JSON),反序列化則還原物件。.NET 提供多種序列化器,各有適用場景。本文系統比較 `BinaryFormatter`、`SoapFormatter`、`XmlSerializer`、`DataContractSerializer`、`DataContractJsonSerializer`,並提供通用輔助類。
| 序列化器 | 輸出格式 | 特點 | 適用場景 |
|---|---|---|---|
| BinaryFormatter | 二進位 | 保留型別保真度、私有欄位、物件圖參考;版本容錯弱 | .NET 內部通訊、剪貼板、Remoting |
| SoapFormatter | SOAP XML | 開放標準、支援 RPC;較冗長 | Web Service 舊版、跨平台舊系統 |
| XmlSerializer | XML | 僅公開屬性/欄位、可控制 XML 結構、不保留型別 | Web API、設定檔、跨平台資料交換 |
| DataContractSerializer | XML/JSON | WCF 預設、支援版本容錯、需標記 DataContract/DataMember | WCF 服務、現代 .NET 應用 |
| DataContractJsonSerializer | JSON | 輕量、適合 AJAX/前端互動 | Web API、前後端分離 |
類別標記 `[Serializable]`。`[NonSerialized]` 排除欄位。`[OnSerializing]` 等屬性掛鉤序列化前後邏輯。實作 `ISerializable` 完全控制。
僅序列化 public 讀寫屬性/欄位。`[XmlIgnore]` 忽略。`[XmlAttribute]`、`[XmlElement]` 控制輸出。可用 `XmlAttributeOverrides` 覆蓋預設映射。
類別加 `[DataContract]`,成員加 `[DataMember]`(不限存取修飾詞)。已知型別集合處理多型。支援 `IExtensibleDataObject` 實現版本容錯(往返未知資料保留)。
用法同 `DataContractSerializer`,輸出 JSON。注意日期格式 (`/Date(1234567890)/`)。
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Xml.Serialization;
using System.Text;
public sealed class SerializeHelper {
#region DataContract (XML)
public static string SerializeDataContract(object value, List knownTypes = null) {
var ser = new DataContractSerializer(value.GetType(), knownTypes);
using (var ms = new MemoryStream()) {
ser.WriteObject(ms, value);
ms.Position = 0;
using (var sr = new StreamReader(ms)) return sr.ReadToEnd();
}
}
public static T DeserializeDataContract(string xml) {
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml))) {
var ser = new DataContractSerializer(typeof(T));
return (T)ser.ReadObject(ms);
}
}
#endregion
#region DataContract JSON
public static string SerializeDataContractJson(object value) {
var ser = new DataContractJsonSerializer(value.GetType());
using (var ms = new MemoryStream()) {
ser.WriteObject(ms, value);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public static T DeserializeDataContractJson(string json) {
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json))) {
var ser = new DataContractJsonSerializer(typeof(T));
return (T)ser.ReadObject(ms);
}
}
#endregion
#region XmlSerializer
public static string SerializeXml(object value) {
var ser = new XmlSerializer(value.GetType());
using (var ms = new MemoryStream()) {
ser.Serialize(ms, value);
ms.Position = 0;
using (var sr = new StreamReader(ms)) return sr.ReadToEnd();
}
}
public static object DeserializeXml(Type type, string xml) {
var ser = new XmlSerializer(type);
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml))) {
return ser.Deserialize(ms);
}
}
#endregion
#region BinaryFormatter
public static string SerializeBinaryFormatter(object obj) {
var fmt = new BinaryFormatter();
using (var ms = new MemoryStream()) {
fmt.Serialize(ms, obj);
return Encoding.Default.GetString(ms.ToArray()); // 二進位轉字串僅為展示,實際傳輸建議用 byte[]
}
}
public static T DeserializeBinaryFormatter(string str) {
var fmt = new BinaryFormatter();
using (var ms = new MemoryStream(Encoding.Default.GetBytes(str))) {
return (T)fmt.Deserialize(ms);
}
}
#endregion
#region SoapFormatter
public static string SerializeSoapFormatter(object obj) {
var fmt = new SoapFormatter();
using (var ms = new MemoryStream()) {
fmt.Serialize(ms, obj);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public static T DeserializeSoapFormatter(string str) {
var fmt = new SoapFormatter();
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(str))) {
return (T)fmt.Deserialize(ms);
}
}
#endregion
}
[DataContract(Name="Customer", Namespace="https://contoso.com")]
class Person : IExtensibleDataObject {
[DataMember] public string FirstName;
[DataMember] public string LastName;
[DataMember] public int ID;
public ExtensionDataObject ExtensionData { get; set; } // 版本容錯
}
// 序列化
Person p = new Person { FirstName="Zighetti", LastName="Barbara", ID=101 };
var ser = new DataContractSerializer(typeof(Person));
ser.WriteObject(fileStream, p);
// 反序列化
Person p2 = (Person)ser.ReadObject(xmlReader);
完整原始碼下載:SerializerSample.rar