中斷式改變
在已有的數據契約(舊版本)的基礎上修改了某一方(服務和客戶端)的數據契約(新版本)之後
服務和客戶端之間不能正常通訊(單向或雙向)
我們稱這種改變為中斷式改變
否則為非中斷式改變
例如
以下改變全部是中斷式改變
修改數據契約的名稱或者命名空間
更改數據契約成員的順序
修改數據契約成員的名稱
修改數據契約成員的類型
增加或刪除枚舉成員
修改枚舉成員的名稱(除了使用EnumMemberAttribute來使得和舊版本一致的情況)
非中斷式改變
任何對不影響傳輸和接收數據的類型的改變都是非中斷式改變
在大多數情況下
增加或刪除數據契約成員都是非中斷式改變
增加新的數據契約成員最常見的改變就是在一方增加新的數據契約成員
然後將新的契約發送給舊版本契約的服務或客戶端
當反序列化這個類型的時候
DataContractSerializer將會簡單的忽略新增加的成員
如果新增的是必須成員
那麼這種更改就是中斷式改變
因為新版本到舊版本沒有問題
但反方向(請參照缺失成員的情況)將不能正常通訊
否則這種更改就是非中斷式改變
版本往返旅行這是一種針對新增加數據契約成員的特殊情況
是指數據傳輸的路徑是從新版數據契約到舊版的數據契約
然後又回到新版的數據契約的情況
例如
Client
àService A
àService B(Client和Service B都使用的新版數據契約
而Service A使用的是舊版的數據契約
這是常見的調用服務鏈的情況)Client
àService
àClient(Client使用的是新版數據契約
Service使用的是舊版的數據契約
這是服務操作的輸入參數和輸出參數或返回值都使用相同的數據契約的情況
)
按照
的規則
在數據從新版本到舊版本時
DataContractSerializer將會忽略新增加的數據
那麼Service B和Client將都接收到沒有新增數據契約成員的數據
那有沒有辦法讓它們接收到包含新增數據契約成員的數據呢?答案是肯定的
WCF中提供了IExtensibleDataObject接口來實現這個目的
在反序列化時
將新增數據放在ExtensionDataObject中
以保證在後續的其他傳輸過程中
新增數據可用
public interface IExtensibleDataObject
{
ExtensionDataObject ExtensionData
{get;set;}
}
當然
即使數據契約的類型實現了IExtensibleDataObject接口
你也可以通過ServiceBehaviorAttribute的IgnoreExtensionDataObject屬性來強制DataContractSerializer來忽略新增成員
缺失數據成員
如果對舊數據契約的更改是刪除數據契約成員的話
存在以下情況
◆缺失的數據成員在數據契約中不是必須的
該數據成員(DataMemberAttriubte)的IsRequired屬性值沒有設置或者是false
針對這種缺失數據成員
在反序列化時
這個缺失成員將使用缺省值
或者null
你也可以使用OnDeserializingAttribute或者OnDeserizlizedAttribute來設置你所希望的缺省值
這屬於非中斷式改變
◆缺失的數據成員在數據契約中是必須的
如果缺失的數據成員在數據契約中是必須的
在反序列化時
將會拋出異常
這種情況屬於中斷式改變
其他如果將DataMemberAttribute的EmitDefaultValue屬性設置成false(缺省值為true)
而且在序列化時該值就是缺省值
那麼此數據成員將不會被序列化
在另外一端將會形成缺失數據成員的情況
也就是說如果該成員是必須的
那麼在反序列化時將會拋出異常
如果將DataMemberAttribute的EmitDefaultValue屬性設置成false(缺省值為true)
在反序列化時將不能接受缺省值
此時如果該成員是必須的話
同樣會拋出異常
From:http://tw.wingwit.com/Article/program/net/201311/11668.html