對象序列化
WCF是通過網絡實現遠程方法調用的,因此參數,返回值等都需要序列化才能在網絡間傳輸。例如,對於下面的一個服務:
[ServiceContract]
public interface IService1
{
[OperationContract]
Point GetRandomPoint();
}
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
public class Service1 : IService1
{
public Point GetRandomPoint()
{
var rnd = new Random();
return new Point() { X = rnd.Next(), Y = rnd.Next() };
}
}
可以通過WCF測試客戶端查看其數據是如何傳輸的。
從中我們可以看到,對於返回值Point,是將其序列化成了Xml格式后傳遞的,在WCF中,默認是通過DataContractSerializer序列化對象的,它可以將對象序列化成XML,我們也可以手動編碼實現這一過程。
var point = new Point(){X = 1,Y = 2};
var serializer = new DataContractSerializer(typeof(Point));
serializer.WriteObject(stream, point);
序列化控制
從前面的例子可以看到,即使什么都不干,只要定義了一個對象,DataContractSerializer就能將其序列化。但這個默認的序列化方式是直接根據字段名稱來序列化的,很多時候,為了實現更好的版本控制,往往需要我們控制序列化格式。
一個簡單的示例如下:
[DataContract]
public class Point
{
[DataMember(Name="PointX")] public int X { get; set; }
[DataMember(Name="PointY")] public int Y { get; set; }
}
實現這個序列化控制后,執行結果為:
從這個例子中可以看到,和傳統的XmlSerializer一樣,WCF是通過一些Attribute進行序列化控制的,基本方式為:
-
通過 DataContract 標志要序列化的對象
-
通過 DataMember 標志序列化成員,並通過參數控制序列化過程。
當然,其序列化控制手段遠遠不止這么點,更多信息可以參看MSDN:創建類或結構的基本數據協定。
將對象序列化成Json格式
XML雖然具有良好的可讀性,但開銷非常大,增大了網絡傳輸負擔,對於那些網速不夠快的場景則需要開銷更小的序列化格式,一種比較常用的開銷更小的序列化格式就是Json。
WCF是一個通用的網絡傳輸平台,在WCF中,可以借助DataContractJsonSerializer實現序列化對象為Json格式。例如,對於前面的那個Point結構,可以序列化為如下形式:
{"PointX":1,"PointY":2}
可以看到,DataContract的序列化控制對DataContractJsonSerializer也是生效的,這說明DataContract是一個通用的序列化控制手段,這也是它們叫DataMember這類比較抽象的名字,而不是叫XmlElement之類的具體名字的原因。
要把WCF服務配置成以Json方式傳輸數據格式,可以參考這篇文章Using WebHttpBinding & JSON Support in WCF。
注意事項
在WCF傳輸數據時,注意返回的對象類型不能是返回值類型的子類(Stream除外)。拿前面的例子來說,修改代碼為:返回一個Point的子類Point3D對象。
public class Point3D : Point
{
public int Z { get; set; }
}
public class Service1 : IService1
{
publicPointGetRandomPoint()
{
var rnd = new Random();
return newPoint3D() { X = rnd.Next(), Y = rnd.Next() };
}
}
這個時候是完全能通過編譯並運行的,但是調用函數的時候就會出現如下錯誤:
這個主要還是傳輸的數據格式不匹配造成的,WCF中可以使用KnownTypeAttribute標記解決這一問題,具體可以參看MSDN文章數據協定繼承,這里就不多介紹了。