自訂編碼器
本主題討論如何建立自訂編碼器。
在 Windows Communication Foundation (WCF) 中,您可以使用「繫結」(Binding) 來指定端點之間透過網路傳輸資料的方式。繫結是由「繫結項目」(Binding Element) 的序列所組成。繫結包含選擇性通訊協定繫結項目 (例如安全性)、必要的「訊息編碼器」(Message Encoder) 繫結項目和必要的傳輸繫結項目。訊息編碼器是由訊息編碼繫結項目表示。WCF 中包含三種訊息編碼器:二進位、訊息傳輸最佳化機制 (MTOM) 和文字。
訊息編碼繫結項目會序列化傳出的 Message 並將它傳遞至傳輸,或者從傳輸接收序列化形式的訊息,如果有通訊協定層,就將訊息傳遞給它,如果不存在,則傳遞給應用程式。
訊息編碼器會進行 Message 執行個體與網路傳輸表示之間的相互轉換。雖然一般描述編碼器在通道堆疊中的位置是在傳輸層之上,但卻是在傳輸層之內。傳輸 (例如,HTTP) 會根據傳輸標準的需求將訊息格式化。編碼器 (例如,文字 XML) 則只是對訊息進行編碼。
當連接到已經存在的用戶端或伺服器時,可能由不得您選擇使用特定的訊息編碼。不過,您可以透過多個端點存取 WCF 服務,而這些端點各自使用不同的訊息編碼器。當單一編碼器的輸送量無法涵蓋服務的整個使用群時,請考慮透過多個端點公開您的服務。然後,用戶端應用程式便可以選擇最適用的端點。使用多個端點可讓您將各種不同訊息編碼器的優點與其他繫結項目相結合。
系統提供的編碼器
WCF 提供數個系統提供的繫結,這些繫結是為配合一些最常見的應用程式案例而設計的。這些繫結中的每一個都結合了傳輸、訊息編碼器和其他選項 (例如,安全性)。本主題將說明如何擴充隨附於 WCF 的 Text、Binary 和 MTOM 訊息編碼器,以及為您自己建立自訂編碼器。文字訊息編碼器同時支援純 XML 編碼及 SOAP 編碼。文字訊息編碼器的純 XML 編碼模式稱為 POX ("Plain Old XML") 編碼器,與文字為主的 SOAP 編碼有所區別。
如需 系統提供的繫結提供之繫結項目組合的詳細資訊,請參閱選擇傳輸中對應的章節。
如何使用系統提供的編碼器
您可以使用衍生自 MessageEncodingBindingElement 的類別,將編碼方式加入至繫結。
WCF 提供下列型別的繫結項目,這些繫結項目衍生自可提供文字、二進位和訊息傳輸最佳化機制 (MTOM) 編碼的 MessageEncodingBindingElement 類別:
- TextMessageEncodingBindingElement:互通性最佳、但效率最差的 XML 訊息編碼器。Web 服務或 Web 服務用戶端通常可以瞭解文字 XML。不過,將大型二進位資料區塊當做文字來傳輸是沒有效率的。
- BinaryMessageEncodingBindingElement:表示繫結項目,這個繫結項目會指定用於二進位 XML 訊息的字元編碼和訊息版本處理。這是最有效率、但互通性最差的編碼選項,因為只有 WCF 端點會支援它。
- MTOMMessageEncodingBindingElement:表示繫結項目,這個繫結項目會為使用訊息傳輸最佳化機制 (MTOM) 編碼的訊息指定字元編碼和訊息版本處理。MTOM 是在 WCF 訊息中傳輸二進位資料的有效技術。MTOM 編碼器會嘗試在效率和互通性之間保持平衡。MTOM 編碼方式會以文字格式傳輸大部分的 XML,但是在傳輸大型區塊的二進位資料時,會依照原狀來傳送 (不轉換成文字),好讓這些資料最佳化。
繫結項目會建立二進位、MTOM 或文字的 MessageEncoderFactory。處理站會建立二進位、MTOM 或文字的 MessageEncoder 執行個體。一般而言,只會有一個執行個體。不過,如果是使用工作階段,就可以提供不同的編碼器給每個工作階段。二進位編碼器會利用這種方式來協調動態字典 (請參閱<XML 基礎結構>)。
ReadMessage 和 WriteMessage 方法是編碼器的核心。這些方法會提供從資料流或 Byte 陣列讀取訊息的功能。當傳輸在緩衝模式中運作時,會使用位元組陣列。訊息一定會寫入資料流。如果傳輸必須緩衝訊息,就會提供執行緩衝處理的資料流。
其他成員則會使用支援內容、媒體類型和 MessageVersion。傳輸會呼叫這些編碼器方法來測試是否可以藉此解碼傳入的訊息,或者判斷傳出的訊息是否對此編碼器為有效。
這三個編碼器實作中的每一個都會新增與特定編碼有關的屬性,而且是完全可設定的。這些編碼器也會公開具有安全預設值的讀取器配額。如需配額的詳細討論,請參閱<XML 基礎結構>。
系統提供之編碼器的功能
系統提供的編碼器具有許多功能。
共用
每個編碼器實作都會盡可能嘗試集中共用。減少配置是改善 Managed 程式碼效能的主要方法。為了達成這種共用,這些實作會使用 SynchronizedPool 類別。C# 檔案包含這個類別使用的其他最佳化方法的描述。
為了避免替每一個訊息配置新的 XmlDictionaryReader 和 XmlDictionaryWriter 執行個體,編碼器會共用並重新初始化這些執行個體。對於讀取器,會在呼叫 Close() 時由 OnClose 回呼取回讀取器。編碼器也會回收建構訊息時使用的某些訊息狀態物件。您可以在三個衍生自 MessageEncodingBindingElement 的每一個類別上,透過其 MaxReadPoolSize 和 MaxWritePoolSize 屬性來設定這些集區的大小。
二進位編碼方式
當二進位編碼使用工作階段時,必須將動態字典字串傳達至訊息的接收者。做法是在訊息前面加上動態字典字串。接收者會剝取這些字串,然後將它們加入至工作階段,再處理訊息。為了正確傳遞字典字串,傳輸需要獲得緩衝。
內部的 AddSessionInformationToMessage 方法會將字串附加至訊息。它會將 UTF-8 格式的字串新增到訊息前頭並加上這些字串的長度,然後在整個字典標頭前面加上其資料的長度。內部的 ExtractSessionInformationFromMessage 方法則會執行反向作業。
除了處理動態字典索引鍵之外,還會以獨特的方式來接收緩衝的工作階段訊息。二進位編碼器並非在文件上建立讀取器,然後加以處理,而是使用內部的 MessagePatterns 類別來拆解二進位資料流。這樣的構想源自於大部分的訊息都含有特定的一組標頭,當 WCF 產生這些標頭時,它們會依照特定的次序出現。模式系統會根據其需求分解訊息。如果分解成功,這個系統就會將 MessageHeaders 物件初始化,而不剖析 XML。如果失敗,則退而求其次,使用標準的方法。
MTOM 編碼方式
MtomMessageEncodingBindingElement 類別具有另一個名為 MaxBufferSize 的組態屬性。這個屬性可以設定允許繫結項目在讀取訊息過程中緩衝資料數量的上限。可能需要將 XML 資訊集 (Infoset) 或其他 MIME 部分加以緩衝,才能將所有 MIME 部分重組成單一訊息。
為能搭配 HTTP 而正常運作,內部 MTOM 訊息編碼器類別提供了一些適用於 GetContentType (同樣是內部的) 和 WriteMessage (公用的且可覆寫) 的內部 API。編碼器必須進行更多的通訊,才能確保 HTTP 標頭中的值與 MIME 標頭中的值一致。
因此,MTOM 訊息編碼器會在內部使用 WCF 的文字讀取器,其運作方式與文字編碼器相似。但是有所不同,主要差異在於最佳化大型二進位區塊 (即「二進位大型物件」(BLOB)) 的方式;在這些區塊嵌入至訊息位元組之前,MTOM 訊息編碼器並不會將它們轉換為 Base-64 編碼,而是讓這些 BLOB 繼續以未經壓縮的狀態存在,並且將它們當做 MIME 附件來參考。
撰寫您自己的編碼器
若要實作您自己的自訂訊息編碼器,您必須提供下列抽象基底類別的自訂實作:
- MessageEncoder
- MessageEncoderFactory
- MessageEncodingBindingElement
訊息由「記憶體中」表示變成「可寫入至資料流」表示的轉換功能是封裝在 MessageEncoder 類別中,這個類別可以當做支援特定類型 XML 編碼之 XML 讀取器和 XML 寫入器的處理站使用。
- 在這個類別中,您必須加以覆寫的主要方法如下:
- WriteMessage,這個方法會接受 Message 物件,並將它寫入至 Stream 物件。
- ReadMessage,這個方法會接受 Stream 物件和最大標頭大小,然後傳回 Message 物件。
在處理標準傳輸通訊協定與自訂編碼之間轉換的這些方法中,它就是您要撰寫的程式碼。
接下來,您必須針對建立自訂編碼器的處理站類別編寫程式碼。覆寫 Encoder,以傳回自訂 MessageEncoder 的執行個體。
最後,覆寫 CreateMessageEncoderFactory 方法以傳回這個處理站的執行個體,讓自訂的 MessageEncoderFactory 連接到用於設定服務或用戶端的繫結項目堆疊。
WCF 隨附了兩個說明此程序的範例,其範例程式碼為:Custom Message Encoder: Custom Text Encoder和Custom Message Encoder: Compression Encoder。
請參閱
參考
MessageEncodingBindingElement
MessageEncoderFactory
MessageEncoder