WCF學習(三):資料契約序列化
WCF能夠託管CLR型別,客戶端能傳遞和處理CLR型別的資料(如:string和int),但是如果我們自己定義的型別(如:宣告的Customer類)。其實WCF的傳遞CLR自己型別時,是因為已經把它序列化成了xml資訊集,而我們自己定義的型別則需要自己去顯示的宣告序列化。
序列化
.net的序列化。.net是通過反射機制(反射機制參考文件)自動實現物件的序列化與反序列化。首先.net能夠捕獲物件每個欄位的值,然後進行序列化,反序列化時,.net建立一個對應型別的新的物件,讀取持久化的值,然後設定欄位的值。.net物件狀態的序列化到Stream中。
我們自定義的類或者結構是不支援序列化的,因此如果我們的類是否要序列化是需要類的開發者來指定的。如果需要支援序列化的話,我們可以在類或者結構上新增Serializable屬性。
如:
[Serializable]
public class Customer
{
...
}
但是如果新增了Serializable就要求型別的成員也要支援序列化的,不然會丟擲異常,但是我們可以通過在成員上新增NonSerizlized屬性來說明這個成員不需要序列化。
格式器
.net為序列化和反序列化提供了兩種格式器:
1.BinaruFormatter:將型別序列化為二進位制格式。
2.SoapFormatter:格式成SOAP特定的XML格式。
但是這兩者都要將型別的程式集以及版本控制資訊持久化到Stream中,而面向服務要求參與者都能擁有型別程式集,所以如果用這兩種格式就必須要去共享Stream,這樣肯定不是我們理想的。從而有了WCF格式器。
WCF的格式器:DataContractSerializer,是能夠共享資料契約的。WCF資料進行序列化時,WCF一般會自己呼叫DataContractSerializer來序列的,不需要我們去指定的。同時我們也可以用DataContractSerializer進行Stream的序列化。
資料契約特性
Serializable要求型別的所有的成員都是可以序列化的,而且不支援型別名跟成員名的別名,這樣我們就沒法明確指定哪些成員是要放到資料契約中的。然而WCF資料契約特性DataContract很好的解決了這些問題。
DataContract Attribute 是在名稱空間System.Runtime.Serialization中的,是可以在Enum、Struct、Class上標識的。擁有成員Name,Namespace。而當我們在一個class或者struct上使用時,wcf是不會序列化型別的成員的。如:
[DataContract]
public class Emloyee
{
public string _firstName;
public string _lastName;
}
Employee裡面的成員_firstName,_lastName是不會去序列化的,所以我們還必須去顯示的指定需要序列化的成員。
DataMember Attribute是用來指定需要序列化型別的成員。DataMember的成員:
IsRequried:序列化時是否必須要賦值;
Name:指定成員的別名;
Order:指定序列化後的排列位置。
我們看一個例子Customer.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace HenllyeeDataContract
{
[DataContract(Name="Customer",Namespace="HenllyeeDataContract")]
public class Customer
{
Fileds#region Fileds
private string _firstName;
private string _lastName;
private int _age;
private decimal _salary;
#endregion
Attributes#region Attributes
[DataMember(Name="FirstName",IsRequired=false,Order=0)]
public string FirstName
{
get { return this._firstName; }
set { this._firstName = value; }
}
[DataMember(Name = "LastName", IsRequired = false, rder = 1)]
public string LastName
{
get { return this._lastName; }
set { this._lastName = value; }
}
[DataMember(Name = "Age", IsRequired = false, rder = 2)]
public int Age
{
get { return this._age; }
set { this._age = value; }
}
[DataMember(Name = "Salary", IsRequired = false, rder = 3)]
public decimal Salary
{
get { return this._salary; }
set { this._salary = value; }
}
#endregion
}
}
上面我們定義了一個資料契約,將DataMember屬性定義在幾個屬性上(建議定義在屬性上,不要定義在欄位上)。
服務契約為:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace HenllyeeServiceContract
{
[ServiceContract(Name="CustomerManagerService",Namespace="http://Henllyee.cnblogs.com/2008/06/29")]
public interface ICustomerManager
{
/**////
/// Save customer's info
///
/// the customer's object
[OperationContract(Name="SaveCustomerInfo",Action="http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/SaveCustomer",
ReplyAction = "http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/SaveCustomerResponse")]
void SaveCustomer(HenllyeeDataContract.Customer customer);
/**////
/// Get customer's info
///
///
[OperationContract(Name = "GetCustomerInfo", Action = "http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/GetCustomer",
ReplyAction = "http://Henllyee.cnblogs.com/2008/06/29/CustomerManagerService/GetCustomerResponse")]
HenllyeeDataContract.Customer GetCustomer();
}
}
服務契約裡面具體實現:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace HenllyeeServiceContract
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class CustomerManager:ICustomerManager
{
fileds#region fileds
private HenllyeeDataContract.Customer _customer;
#endregion
Members#region Members
public void SaveCustomer(HenllyeeDataContract.Customer customer)
{
_customer = customer;
}
public HenllyeeDataContract.Customer GetCustomer()
{
return this._customer;
}
#endregion
}
}
主機的實現就不在次給出了。
然後我們在客戶端新增服務引用,即可以了。我們在客戶端可以看到匯入的資料契約:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Customer", Namespace="HenllyeeDataContract")]
[System.SerializableAttribute()]
public partial class Customer : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string FirstNameField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string LastNameField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private int AgeField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private decimal SalaryField;
[global::System.ComponentModel.BrowsableAttribute(false)]
public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
get {
return this.extensionDataField;
}
set {
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string FirstName {
get {
return this.FirstNameField;
}
set {
if ((object.ReferenceEquals(this.FirstNameField, value) != true)) {
this.FirstNameField = value;
this.RaisePropertyChanged("FirstName");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string LastName {
get {
return this.LastNameField;
}
set {
if ((object.ReferenceEquals(this.LastNameField, value) != true)) {
this.LastNameField = value;
this.RaisePropertyChanged("LastName");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=2)]
public int Age {
get {
return this.AgeField;
}
set {
if ((this.AgeField.Equals(value) != true)) {
this.AgeField = value;
this.RaisePropertyChanged("Age");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=3)]
public decimal Salary {
get {
return this.SalaryField;
}
set {
if ((this.SalaryField.Equals(value) != true)) {
this.SalaryField = value;
this.RaisePropertyChanged("Salary");
}
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
我們可以看到欄位後面都加上了Field字尾。
要注意的一點是:即使我們將DataMember定義在私有的欄位或者私有屬性上面,匯入的定義中,原來的私有欄位或私有屬性都會被重新定義成了公有欄位跟公有屬性。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-600249/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- WCF學習(四):資料契約的事件事件
- Programming WCF Services:資料契約版本控制
- WCF技術剖析之十五:資料契約代理(DataContractSurrogate)在序列化中的作用
- WCF技術剖析之十八:訊息契約(Message Contract)和基於訊息契約的序列化
- WCF學習筆記(一):WCF簡介筆記
- 學習 WCF (3)--開發WCF客戶程式
- wcf學習總結《中》
- WCF分散式開發步步為贏(0):WCF學習經驗分享,如何更好地學習WCF?薦分散式
- 學習WCF之路,長期更新
- 資料庫學習(三)基本查詢資料庫
- 學習 JavaScript 資料結構(三)——集合JavaScript資料結構
- Constract 契約自定義
- 大資料的系統學習:大資料學習的三個階段概述大資料
- 契約測試Pact實踐
- 事件、契約設計與BDD事件
- 博弈學習 (二) 斐波那契博弈
- phar反序列化學習
- 資料庫學習(一)三正規化資料庫
- iOS學習資源(三)iOS
- Mysql資料庫學習(三):表的crud操作、完整性約束、select各種查詢MySql資料庫
- 學習資料
- mediasoup 學習筆記 【三】 Producer 資料生產者筆記
- URLDNS反序列化鏈學習DNS
- 反序列化底層學習
- Go學習【二】學習資料Go
- 大資料學習資料大資料
- 《學習》6約束
- 深度學習(一)深度學習學習資料深度學習
- 哲♂學三幻神帶你學習ConstraintLayout(約束佈局)AI
- 簽約獎金:IT世界的賣身契
- Solidity語言學習筆記————44、合約的後設資料Solid筆記
- orientDB學習筆記(三)資料庫 構架設計筆記資料庫
- 知識學習綜合三---分散式系統大資料分散式大資料
- Python爬蟲學習筆記(三、儲存資料)Python爬蟲筆記
- Hibernate學習(三)一對多資料的儲存
- Spring4學習(三)JdbcTemplate訪問資料庫SpringJDBC資料庫
- 十五天精通WCF——第十二天 說說wcf中的那幾種序列化
- 從原理學習Java反序列化Java