天天看點

WCF技術剖析之十九:深度剖析消息編碼(Encoding)實作(下篇)

一、消息編碼器(MessageEncoder)

二、 執行個體示範通過MessageCoder對消息進行編碼

接下來,我們來示範一個執行個體:如何通過MessageCoder對一個具體的Message對象進行編碼。本例主要示範TextMessageCoder和MtomMessageEncoder編碼方式的對比。此外,為了示範MTOM對二進制資料的編碼優化,我們建立一個基于二進制内容的Message對象,并将一個位圖作為消息的主體。

我們先建立如下一個靜态輔助方法WriteMessage,該方法通過MessageEncoderFactory得到的MessageEncoder對象将Message對象寫入一個檔案中。

如果調用上面的方法,首先需要建立MessageEncoderFactory對象。由于TextMessageEncoderFactory和MtomMessageEncoderFactory是一個内部類型,不能直接執行個體化,是以隻能通過反射的機制建立兩個MessageEncoder。下面是TextMessageEncoder和MtomMessageEncoderFactory構造函數的定義。

在下面的代碼中,先通過Message的靜态方法CreateMessage建立Message對象,需要注意的第3個參數是一個表示位圖的Bitmap對象。然後通過反射建立TextMessageEncoderFactory和MtomMessageEncoderFactory對象,并調用上面定義的輔助方法WriteMessage。

下面給出的兩段文字分别是通過TextMessageEncoder和MtomMessageEncoder對相同的Message對象進行編碼後的結果。從中我們可以清晰地看出,TextMessageEncoder将位圖進行Base64編碼,編碼後的内容以内聯(Inline)的方式包含在SOAP主體中。而MtomMessageEncoder會生成一個MIME

Multipart/Related XOP

Package,SOAP封套作為其主體。編碼後的位元組和SOAP封套是分離的,SOAP的主體部分并不包含位圖的内容,僅僅是通過Context-ID對分離的内容進行引用。

三、WCF體系下的編碼機制實作

最後我們來介紹WCF體系下是如何對消息進行編碼的。在用戶端,以方法調用形式展現的服務通路通過ClientMessageFormatter生成請求消息。該請求消息最終通過綁定對象從服務模型層轉到信道層。我們說綁定是綁定元素的有序組合,對于所有類型的綁定來說,有兩個綁定類型是必不可少的:MessageEncodingBindingElement和TransportBindingElement。而消息的編碼由這兩個綁定元素共同完成。

上面我們介紹了3種編碼方式:Text、Binary和MTOM;對應3種不同的XmlDictionaryWriter/XmlDictionaryReader:XmlUTF8TextWriter/

XmlUTF8TextReader、XmlBinaryWriter/XmlBinaryReader和XmlMtomWriter/XmlMtomReader;3種XmlDictionaryWriter/XmlDictionaryReader又對應着3種MessageEncoder:TextMessageEncoder、BinaryMessagEncoder和MtomMessageEncoder;這3種不同的MessageEncoder又具有它們各自的MessageEncoderFactory:TextMessageEncoderFactory、BinaryMessagEncoderFactory和MtomMessageEncoderFactory。最終這3種MessageEncoderFactory被3種相應的MessageEncodingBindingElement用于進行具體的編碼。MessageEncodingBindingElement通過CreateMessageEncoderFactory得到相應的MessageEncoderFactory。

對應着3種不同的MessageEncoderFactory,WCF定義了3種不同的MessageEncodingBindingElement,它們分别是:TextMessageEncodingBindingElement、BinaryMessageEncodingBindingElement和MtomMessageEncodingBindingElement。

在介紹綁定的時候,我們說BindingElement建立相應的ChannelFactory/ChannelListener,而ChannelFactory/ChannelListener最終建立相應的Channel進行消息的處理。這種說法是不準确的,并不是所有的BindingElement都會建立Channel,實際上沒有用于專門編碼的Channel,具體的編碼工作是TransportChannel完成的。圖1揭示了WCF進行消息編碼的本質。

<a target="_blank" href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/WCFEncoding_11266/clip_image002_2.jpg"></a>

圖1 WCF體系下消息編碼的實作

當通過綁定對象建立信道棧的時候,MessageEncodingBindingElement的BuildChannelFactory/BuildChannelListener方法首先被調用,MessageEncodingBindingElement會建立相應的MessageEncoderFactory對象,将其置于目前的BindingContext中。然後TransportBindingElement的BuildChannelFactory/BuildChannelListener方法被調用,并建立TransportChannelFactory/TransportChannelListener對象,TransportChannelListener和TransportChannelFactory建立TransportChannel用于請求監聽和消息發送,與此同時TransportChannel會将MessageEncoderFactory從BindingContext擷取下來用于消息的解碼和編碼。

作者:蔣金楠

微信公衆賬号:大内老A

如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識别二維碼)關注個人公衆号(原來公衆帳号蔣金楠的自媒體将會停用)。

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

<a href="http://www.cnblogs.com/artech/archive/2009/08/06/1540686.html" target="_blank">原文連結</a>

繼續閱讀