WCF序列化流程
序列化
默認用戶自定義類型(類和結構)並不支持序列化,因為.NET無法判斷對象狀態是否需要反射到流。 用戶自定義類的實例支持序列化 需要添加[Serialazable]。若要允許可序列化類型包含非序列化的成員變量可使用[NonSerializad]
.Net格式器
BinaryFormatter 序列化為二進制格式
SoapFormatter 使用.NET 特定的SOAP XMl格式
兩者格式器都實現IFormatter接口
兩種格式器都要將類型的程序集及版本控制器信息持久化到流中,以保證序列化的對象能夠被反序列化為正確的類型。
WCF格式器
使用[DataContract]進行標記類,使用[DataMember]標記成員
DataContractSerializer格式器繼承XmlObjectSerializer。
在未曾標記DataContract特性,WCF就會自動推斷,認為DataContract特性被應用到該類型上,且它的所有僅有成員(字段或屬性)均被應用了DataMember特性。
組合數據契約:定義數據契約,對那些本身就是數據契約的成員也可以使用DataMember特性。-數據契約具有遞歸性質
數據契約事件 serializing發生成在序列化之前,serialized事件發生在序列化后,desrializing發生在反序列化之前,desreialized發生在反序列化之后
每個序列化事件處理方法都必須遵循如下的方法簽名
void <Method Name>(StreamingContext context)
![]()
WCF在反序列化前必須創建一個對象,但是,WCF不會調用數據契約類的默認構造函數。
數據契約層級
WCF要求類層級的每一級數據契約都必須標記DataContract特性,該特性不可繼承。WCF可以在類層級混合使用Serializable和DataContract特性
WCF不能接收子類型數據,只能使用[KnownType(typeof(subclass))] 或[ServiceKnownType(typeof(SubClass))]
配置文件方法
<add type="Contact,MyClassLibrary">
<knownType type="Customer,MyOtherClassLibrary"/>
</add>
使用配置文件主要解決的問題是:當添加一個新的子類時必須修改代碼、重新編譯和重新部署。
序列化順序
在類型內部,默認的序列化順序是按照字母的排序的,至於整個類層級的順序,則是自上而下的。在序列化順序不匹配的情況下,成員則以它們的值進行初始化。 自定義順序可以使用[DataMember]的Order屬性值進行調整,該屬性的默認值為-1,也就是它默認WCF順序
成員的Order屬性設置了相同的值,WCF會按照成員的字母順序排序
版本控制
- 新增成員;
任何一端添加新的成員,然后將新的契約發送到舊的客戶端或服務。在反序列化這樣的數據契約類型時,DataContractSerializer會忽略新增成員。 - 缺失成員;
客戶端是針對舊的數據契約定義編寫的,而與之交互的服務則是根據定義了新成員的契約定義編寫的。當接收端的DataContractSerializer在消息中無法找到所需信息去反序列化的這些成員時,會根據成員的值進行反序列化。也就是說,將引用類型設置為null,將值類型設置為0。 -
雙向傳遞,即新的數據契約與舊版本的數據契約之間相互傳遞,它同時需要向后與向前的兼容性。
枚舉
枚舉類型總是支持序列化的。不必應用DataContract特性,如果要將確定的枚舉值排除於數據契約之外,就需要在枚舉類型標記DataContract特性,並在枚舉值明確標記為[EnumMember]特性,沒有標記EnumMember毛發的枚舉值不屬於該枚舉的數據契約。同時可以使用該特性的Value屬性對枚舉值設置別名。
泛型
不能定義包含了泛型類型參數的數據契約。便可以在數據契約中使用限定的泛型數據,只要在服務契約中指定了類型參數。
數據契約被重命名的格式為:<原有名>Of<類型參數><散列值>
同時也可以使用[DataContract(Name=”ClassNameOf{0}{1}”)]表示。標識符中的數字就是類型參數的序數,可以用{#}表示為散列值集合
在使用集合接口IEnumberable,IList和ICollection,它他的傳輸型表示形式都使用了數組
如果契約中的集合為具體集合類型,而且屬於可序列化集合(標記為Serializable特性而不是DataContract特性),那么,只要提供的集合包含Add()方法,WCF就能夠自動地將集合規范為數組類型。
CollectionDataContract特性:該特性會檢驗Add()方法及檢查IEumerable或IEnumerable接口是否存在。如果不存在,就會導致InvlidDataContractException異常。注:DataContract不能和CollectionDataContract一起使用