資料契約描述交換資料結構,是序列化/反序列化的依據。Client/Server 需擁有等效資料契約才能有效交換。隨時間演進,契約版本變更(成員增刪、改名、改命名空間)不可避免,如何確保版本演進不破壞現有相容性,是本文核心主題。
若兩個不同型別的資料契約物件序列化後產生相同 XML 結構,即視為等效。條件:
DataContractAttribute.Name)Namespace)DataMemberAttribute.Name)Order 屬性控制)範例: Customer 與 Contact 型別/成員命名不同、定義順序不同,但透過 Name、Order 屬性對齊,序列化結果完全一致,故等效。
Server 端契約 CustomerV2 新增 Address,Client 仍用 CustomerV1(無 Address)。反序列化時:
IsRequired=false:成功,缺失成員保留預設值(null)。XSD 中對應 minOccurs="0"。[DataMember(IsRequired=true)]:拋出 SerializationException。XSD 中 minOccurs 消失,XML 不符合結構定義。缺失成員賦預設值: 實作 [OnDeserializing] 回呼方法初始化。
Client 用 CustomerV1(含 Address),Server 用 CustomerV2(無 Address)。往返流程:
造成「資料無故消失」的不可接受行為。
[DataContract(...)]
public class CustomerV2 : IExtensibleDataObject
{
public ExtensionDataObject ExtensionData { get; set; }
// ...
}
DataContractSerializer 反序列化時,將未知 XML 元素反序列化存入 ExtensionData;序列化時將其寫回 XML。實測:CustomerV2 序列化輸出仍包含 <Address>,資料完整保全。
DataContractSerializer 建構函數參數 / 唯讀屬性ServiceBehaviorAttribute.IgnoreExtensionDataObject<dataContractSerializer ignoreExtensionDataObject="true" />設為 true 時忽略未知資料、不保全往返資料。