WCF入門(三)——對象序列化


對象序列化

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進行序列化控制的,基本方式為:

  1. 通過 DataContract 標志要序列化的對象
  2. 通過 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
    {
        public
PointGetRandomPoint()
        {
            var rnd = new Random();
            return new
Point3D() { X = rnd.Next(), Y = rnd.Next() };
        }
    }

這個時候是完全能通過編譯並運行的,但是調用函數的時候就會出現如下錯誤:

這個主要還是傳輸的數據格式不匹配造成的,WCF中可以使用KnownTypeAttribute標記解決這一問題,具體可以參看MSDN文章數據協定繼承,這里就不多介紹了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM