WCF 透過序列化將物件圖轉換為傳輸格式,支援多種序列化器,各有適用場景。本文詳細比較 DataContractSerializer、XmlSerializer、DataContractJsonSerializer、SoapFormatter、BinaryFormatter 五大序列化器的特性、輸出格式與效能特徵。
| 序列化器 | 命名空間 | 輸出格式 | 效能 | 版本容忍度 | 適用場景 |
|---|---|---|---|---|---|
| DataContractSerializer | System.Runtime.Serialization | XML (Infoset) | 高 | 優 (選擇性欄位) | WCF 預設、一般用途 |
| XmlSerializer | System.Xml.Serialization | XML (完整控制) | 中 | 良 | 需精確控制 XML 結構、相容舊 ASMX |
| DataContractJsonSerializer | System.Runtime.Serialization.Json | JSON | 高 | 優 | AJAX、REST API、Web 前端 |
| SoapFormatter | System.Runtime.Serialization.Formatters.Soap | SOAP XML | 低 | 差 | .NET Remoting、舊版相容 |
| BinaryFormatter | System.Runtime.Serialization.Formatters.Binary | 二進位 | 最高 | 差 | .NET 內部通訊、效能極致場景 |
[DataContract(Namespace = "https://webabcd.cnblogs.com/")]
public class DataContractSerializerObject {
[DataMember(Name = "UniqueID", Order = 0)] public Guid ID { get; set; }
[DataMember(Order = 1)] public string Name { get; set; }
[DataMember(Order = 2)] public int Age { get; set; }
[DataMember(Order = 3)] public DateTime Time { get; set; }
}
Namespace:XML 命名空間Name:序列化後的元素名稱Order:序列化順序 (字母序預設)IsRequired、EmitDefaultValue 等進階選項[XmlRoot(Namespace = "https://webabcd.cnblogs.com/")]
public class XmlSerializerObject {
[XmlElement(ElementName = "UniqueID", Order = 0)] public Guid ID { get; set; }
[XmlElement(Order = 1)] public string Name { get; set; }
[XmlElement(Order = 2)] public int Age { get; set; }
[XmlElement(Order = 3)] public DateTime Time { get; set; }
}
[DataContract(Namespace = "https://webabcd.cnblogs.com/")]
public class DataContractJsonSerializerObject {
[DataMember(Name = "UniqueID", Order = 0)] public Guid ID { get; set; }
[DataMember(Order = 1)] public string Name { get; set; }
[DataMember(Order = 2)] public int Age { get; set; }
[DataMember(Order = 3)] public DateTime Time { get; set; }
}
[Serializable]
public class SoapFormatterObject {
public Guid ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public DateTime Time { get; set; }
}
var obj = new DataContractSerializerObject {
ID = Guid.NewGuid(), Name = "DataContractSerializer", Age = 28, Time = DateTime.Now
};
var serializer = new DataContractSerializer(typeof(DataContractSerializerObject));
// 序列化
var ms = new MemoryStream();
serializer.WriteObject(ms, obj);
ms.Position = 0;
string xml = new StreamReader(ms).ReadToEnd();
// 反序列化
var buffer = Encoding.UTF8.GetBytes(xml);
var ms2 = new MemoryStream(buffer);
var obj2 = serializer.ReadObject(ms2) as DataContractSerializerObject;
var serializer = new XmlSerializer(typeof(XmlSerializerObject));
serializer.Serialize(ms, obj); // 序列化
var obj2 = serializer.Deserialize(ms2) as XmlSerializerObject; // 反序列化
var formatter = new SoapFormatter();
formatter.Serialize(ms, obj);
string soap = Encoding.UTF8.GetString(ms.GetBuffer());
var obj2 = formatter.Deserialize(ms2) as SoapFormatterObject;
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
byte[] binary = ms.GetBuffer(); // 二進位位元組陣列
var obj2 = formatter.Deserialize(ms2) as BinaryFormatterObject;
var serializer = new DataContractJsonSerializer(typeof(DataContractJsonSerializerObject));
serializer.WriteObject(ms, obj);
string json = new StreamReader(ms).ReadToEnd();
var obj2 = serializer.ReadObject(ms2) as DataContractJsonSerializerObject;
<DataContractSerializerObject xmlns="https://webabcd.cnblogs.com/" xmlns:i="https://www.w3.org/2001/XMLSchema-instance">
<UniqueID>86148742-ef08-4d78-acab-ce393ea8b885</UniqueID>
<Name>DataContractSerializer</Name>
<Age>28</Age>
<Time>2008-04-24T09:06:23.875+08:00</Time>
</DataContractSerializerObject>
<?xml version="1.0"?>
<XmlSerializerObject xmlns:xsi="..." xmlns:xsd="..." xmlns="https://webabcd.cnblogs.com/">
<UniqueID>15efa47f-9532-4e91-8c00-3097ea976106</UniqueID>
<Name>XmlSerializer</Name>
<Age>28</Age>
<Time>2008-04-24T09:06:24.109375+08:00</Time>
</XmlSerializerObject>
<SOAP-ENV:Envelope ...>
<SOAP-ENV:Body>
<a1:SoapFormatterObject id="ref-1" ...>
<_x003C_ID_x003E_k__BackingField>...</_x003C_ID_x003E_k__BackingField>
<_x003C_Name_x003E_k__BackingField>ShowSoapFormatter</_x003C_Name_x003E_k__BackingField>
...
</a1:SoapFormatterObject>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdDRi5TZXJ2aWNlTGliLCBWZXJzaW9uPTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUBAAAIQ1dGLlNlcnZpY2VMaWIuU2VyaWFsaXphdGlvbi5CaW5hcnlGb3JtYXR0ZXJPYmplY3QEAAAAHgQAAAAJAwAAAAcICQg=
{"UniqueID":"f4173d7d-9555-4dcb-8db7-62b85315d3f1","Name":"DataContractJsonSerializer","Age":28,"Time":"\/Date(1208999184531+0800)\/"}
IsRequired=false (預設) 允許缺少欄位;EmitDefaultValue=false 可省略預設值;支援 OnSerializing/OnDeserialized 回調XmlElement(IsNullable=true) 或使用 DefaultValue 屬性| 場景 | 推薦序列化器 |
|---|---|
| WCF 服務間通訊 (預設) | DataContractSerializer |
| REST API / AJAX 前端 | DataContractJsonSerializer / System.Text.Json |
| 需精確控制 XML 結構 (XSD 驗證) | XmlSerializer |
| 高效能 .NET 內部進程通訊 | BinaryFormatter (僅受信環境) / MessagePack / Protobuf |
| 舊版 .NET Remoting 遷移 | SoapFormatter (僅相容期使用) |
.NET Core / .NET 5+ 建議使用:
System.Text.Json:高效能 JSON,內建支援,取代 DataContractJsonSerializerMessagePack、Protobuf:二進位高效能,跨語言支援佳XmlSerializer 仍支援但不再是首選序列化器的選擇直接影響服務的互通性、效能、安全性與維護性,應根據傳輸協定、客戶端類型與版本演進策略綜合評估。