WCF 採用 資料合約 (Data Contract) 定義服務邊界傳遞的資料結構,序列化引擎為 DataContractSerializer (DCS),取代傳統 .NET 序列化器以滿足跨平台互通需求。
| 序列化器 | 特點 | 限制 |
|---|---|---|
| BinaryFormatter | 二進位、型別保真、效能高 | 強制 .NET 雙端、含組件版本、不跨平台 |
| SoapFormatter | SOAP XML、跨平台 | 效能差、仍含 .NET 型別資訊、已過時 |
| XmlSerializer | 純 XML、可控制輸出 | 僅公開屬性/欄位、不支援介面/泛型集合完整 |
DCS 設計目標:僅序列化資料、不含型別身分、產出標準 XML Infoset、支援版本容錯、效能優於 XmlSerializer。
[DataContract(Namespace = "https://myschema.org")]
public class UserProfile
{
[DataMember(Order = 1, Name = "UserName", IsRequired = true)]
public string Name { get; set; }
[DataMember(Order = 2, EmitDefaultValue = false)]
public string Email { get; set; }
[DataMember(Order = 3)]
public string Mobile { get; set; }
// 無 DataMember → 不序列化
public string InternalNote { get; set; }
}
Order:控制 XML 元素順序,利於版本演進 (新欄位加在最後)。Name:自訂 XML 元素名稱,實現別名。IsRequired:反序列化時必須存在,否則拋例外。EmitDefaultValue=false:預設值 (null/0/false) 不輸出 XML,減小封包。WriteObject → WriteStartObject → WriteObjectContent (依 Order 寫入 DataMember) → WriteEndObject。ReadObject → 驗證元素名/命名空間 → 依 Order 讀取 → 建立物件 → 設定屬性。IExtensibleDataObject 保留未知資料 (Round-tripping),升級後舊用戶端仍能保留新欄位資料。多型序列化需宣告 [KnownType(typeof(Derived))] 或設定 ServiceKnownType,否則衍生類別無法正確序列化/反序列化。
// 服務端
[ServiceContract]
public interface IUserService
{
[OperationContract] bool AddUser(UserProfile user);
[OperationContract] UserProfile GetUser(string name);
}
// 客戶端反序列化後的型別 (由 svcutil/Visual Studio 產生)
public partial class UserProfile : IExtensibleDataObject, INotifyPropertyChanged
{
[DataMember] public string UserName { get; set; }
[DataMember] public string UserEmail { get; set; }
[DataMember] public string Mobile { get; set; }
// 注意:屬性名稱依服務端 Name 別名調整
// 自動實作 INotifyPropertyChanged 支援 WPF/UI 繫結
}
null 集合,建議初始化為空集合避免客戶端 NullReference。DataContractSerializer 建構子預先載入已知型別,減少啟動反射開銷。binaryMessageEncoding) 可進一步縮減 30-50% 封包體積,需雙端支援。DataContract + DataContractSerializer 是 WCF 互通性的基石。明確定義合約、控制序列化細節 (Order/Name/Required/EmitDefaultValue)、善用版本容錯機制,能建構穩健、可演進的服務介面。