カスタム エンコーダー
このトピックでは、カスタム エンコーダーを作成する方法について説明します。
Windows Communication Foundation (WCF) では "バインディング" を使用して、エンドポイントどうしがネットワーク経由でデータを転送する方法を指定します。バインディングは、一連の "バインド要素" で構成されます。バインディングには、セキュリティなどのオプションのプロトコル バインド要素、必須のメッセージ エンコーダーのバインド要素、および必須のトランスポートのバインド要素が含まれます。メッセージ エンコーダーは、メッセージ エンコーディング バインド要素で表されます。WCF に含まれるメッセージ エンコーダーは、バイナリ、MTOM (Message Transmission Optimization Mechanism)、およびテキストの 3 つです。
メッセージ エンコーディング バインド要素は、送信する Message をシリアル化してそれをトランスポートに渡すか、シリアル化された形式のメッセージをトランスポートから受信して、それをプロトコル層 (ある場合) またはアプリケーション (プロトコル層がない場合) に渡します。
メッセージ エンコーダーは、Message インスタンスと物理メッセージ形式を相互に変換します。エンコーダーは、チャネル スタックのトランスポート層の上に位置すると説明されていますが、トランスポート層の内部に存在します。トランスポート (HTTP など) は、トランスポート標準の要件に従ってメッセージの書式設定を行います。エンコーダー (テキスト XML など) は、単にメッセージのエンコードを行います。
既存のクライアントまたはサーバーに接続する場合、特定のメッセージ エンコーディングを使用する選択ができない場合があります。ただし、WCF サービスは、それぞれが異なるメッセージ エンコーダーを使用する複数のエンドポイントからアクセスできるようにすることができます。1 つのエンコーダーでサービスの対象ユーザー全体を網羅しない場合、複数のエンドポイントにサービスを公開することを検討します。これによりクライアント アプリケーションはそのアプリケーションに最も適したエンドポイントを選択できます。複数のエンドポイントを使用することにより、さまざまなメッセージ エンコーダーの利点を他のバインド要素と組み合わせることが可能になります。
システム指定のエンコーダー
WCF では、最も一般的なアプリケーション シナリオに合わせて設計されたシステム既定のバインディングがいくつか用意されています。これらのバインディングは、それぞれトランスポート、メッセージ エンコーダー、その他のオプション (セキュリティなど) を組み合わせます。このトピックでは、WCF に含まれる Text、Binary、MTOM メッセージ エンコーダーの拡張方法、つまり独自のカスタム エンコーダーの作成方法について説明します。テキスト メッセージ エンコーダーは、通常の XML のエンコーディングに加えて、SOAP のエンコーディングもサポートします。テキスト メッセージ エンコーダーの通常の XML エンコーディング モードは、テキスト ベースの SOAP エンコーディングと区別するために、POX ("Plain Old XML") エンコーダーと呼ばれます。
システム定義のバインディングにより提供されるバインド要素の組み合わせ詳細情報、「トランスポートの選択」の対応するセクションを参照してください。
システム標準のエンコーダーの操作方法
エンコーディングは、MessageEncodingBindingElement からの派生クラスを使用してバインディングに追加します。
WCF では、テキスト、バイナリ、および MTOM (Message Transmission Optimization Mechanism) のエンコーディングに対応した MessageEncodingBindingElement クラスから派生した次の種類のバインド要素が提供されます。
TextMessageEncodingBindingElement : 相互運用性は最も高く、効率は最も低い、XML メッセージ用のエンコーダー。Web サービスまたは Web サービス クライアントは、一般に、テキスト形式の XML を認識できます。ただし、大きいブロックのバイナリ データをテキストとして転送するのは効率的ではありません。
BinaryMessageEncodingBindingElement : バイナリベースの XML メッセージで使用される、文字エンコーディングおよびメッセージのバージョン管理を指定するバインド要素を表します。これは最も効率的なエンコーディング オプションですが、WCF エンドポイントでしかサポートされないため、相互運用性は最も低くなります。
MTOMMessageEncodingBindingElement : Message Transmission Optimization Mechanism (MTOM) エンコードを使用するメッセージの文字エンコードおよびメッセージ バージョン管理を指定するバインド要素を表します。MTOM は、WCF メッセージでのバイナリ データの転送に有効なテクノロジです。MTOM エンコーダーは、効率と相互運用性のバランスをとろうとします。MTOM エンコーディングは、ほとんどの XML をテキスト形式で転送しますが、大きいサイズのバイナリ データ ブロックはテキストに変換せずにそのまま転送することによって最適化します。
バインド要素は、バイナリ、MTOM、またはテキストの MessageEncoderFactory を作成します。ファクトリは、バイナリ、MTOM、またはテキストの MessageEncoder を作成します。通常、インスタンスは 1 つだけあります。ただし、セッションを使用すると、異なるエンコーダーを各セッションに提供できます。バイナリ エンコーダーでは、これを利用して動的ディクショナリ (XML インフラストラクチャを参照) を調整します。
ReadMessage メソッドと WriteMessage メソッドは、エンコーダーのコアです。このメソッドは、ストリームまたは Byte 配列からのメッセージの読み取りに対応します。バイト配列は、トランスポートをバッファー モードで操作している場合に使用されます。メッセージはストリームに常に書き込まれます。トランスポートでメッセージをバッファーする必要がある場合は、バッファリングを行うストリームが提供されます。
残りのメンバーは、サポート コンテンツ、メディア タイプ、および MessageVersion を処理します。トランスポートは、このエンコーダー メソッドを呼び出して、受信メッセージがデコード可能かどうかをテストするか、または送信メッセージがこのエンコーダーに対して有効かどうかを決定します。
3 つのそれぞれのエンコーダー実装は、特定のエンコーディングに関連するプロパティを追加し、完全に構成可能です。また、エンコーダーは、安全な既定値を持つリーダーのクォータも公開しています。クォータの詳細については、XML インフラストラクチャを参照してください。
システム標準のエンコーダーの機能
システム標準のエンコーダーは多くの機能を提供します。
プール
各エンコーダー実装は、可能な限りプールを試みます。マネージ コードのパフォーマンスを向上するには、割り当てを減らすことが重要です。このプールを実現するには、実装で SynchronizedPool クラスを使用します。C# ファイルには、このクラスで使用する追加の最適化に関する記述を含めます。
メッセージごとに新しい XmlDictionaryReader および XmlDictionaryWriter インスタンスを割り当てるのを避けるため、これらのインスタンスをプールして再初期化します。リーダーについては、Close() の呼び出し時に OnClose コールバックでリーダーが再利用されます。また、エンコーダーでは、メッセージを作成するときに使用するいくつかのメッセージ状態オブジェクトが再利用されます。このプールのサイズは、MessageEncodingBindingElement から派生した 3 つの各クラスの MaxReadPoolSize プロパティと MaxWritePoolSize プロパティによって構成可能です。
バイナリ エンコーディング
バイナリ エンコーディングでセッションを使用する場合、動的ディクショナリの文字列をメッセージの受信者と通信する必要があります。これを行うには、メッセージのプレフィックスに動的ディクショナリの文字列を指定します。受信側では、その文字列を取り除いて、セッションに追加し、メッセージ処理を行います。ディクショナリの文字列を正しく渡すには、トランスポートをバッファーする必要があります。
文字列は、内部 AddSessionInformationToMessage メソッドによってメッセージに追加されます。文字列は、メッセージの先頭に UTF-8 として追加され、その長さがプレフィックスに指定されます。次にディクショナリ ヘッダー全体のプレフィックスにそのデータ長が指定されます。内部 ExtractSessionInformationFromMessage メソッドにより逆操作が実行されます。
動的ディクショナリ キーの処理に加え、バッファーされセッションの多いメッセージが独自の方法で受信されます。ドキュメントでリーダーを作成して処理する代わりに、バイナリ エンコーダーは、内部 MessagePatterns クラスを使用してバイナリ ストリームを分解します。つまり、WCF で作成されたほとんどのメッセージには、特定の順序で表された特定セットのヘッダーがあります。想定を基にしたパターン システムによりメッセージは分割されます。成功した場合は、XML の解析を行わずに MessageHeaders オブジェクトを初期化します。成功しなかった場合は、標準の方法に戻ります。
MTOM エンコーディング
MtomMessageEncodingBindingElement クラスには、MaxBufferSize という追加の構成プロパティがあります。これには、メッセージ読み取り中にバッファーできるデータ量の上限が設けられています。すべての MIME パートを 1 つのメッセージに再アセンブルするために、XML 情報セット (Infoset) または他の MIME パートをバッファーすることが必要な場合もあります。
HTTP を正しく操作するために、内部 MTOM メッセージ エンコーダーのクラスでは、GetContentType (内部) や WriteMessage (パブリックで、オーバーライド可能) の内部 API がいくつか用意されています。HTTP ヘッダーの値を MIME ヘッダーの値と一致させるには、多くの通信を行う必要があります。
内部的に、MTOM メッセージ エンコーダーは、WCF のテキスト リーダーを使用するので、テキスト エンコーダーに似ています。主な違いは、Base-64 エンコーディングに変換せずにメッセージ バイトに埋め込むことで、大きいサイズのバイナリ (バイナリ ラージ オブジェクト (BLOB) と呼びます) を最適化する点です。代わりに、この BLOB は抽出され、MIME 添付として参照されます。
独自のエンコーダーの作成
独自のカスタム メッセージ エンコーダーを実装するには、次の抽象基本クラスのカスタム実装を提供する必要があります。
MessageEncoder
MessageEncoderFactory
MessageEncodingBindingElement
メッセージのメモリ内表現からストリームに書き込むことのできる表現への変換は、 MessageEncoder クラスにカプセル化されており、このクラスは、特定の種類の XML エンコーディングをサポートする XML リーダーおよび XML ライターに対するファクトリとして機能します。
オーバーライドを必要とする、このクラスの主要なメソッドを次に示します。
WriteMessage。Message オブジェクトを受け取り、それを Stream オブジェクトに書き込みます。
ReadMessage。Stream オブジェクトと最大ヘッダー サイズを受け取り、Message オブジェクトを返します。
これらのメソッドに記述するコードは、標準トランスポート プロトコルとカスタマイズしたエンコーディングの間の変換処理です。
次に、カスタム エンコーダーを作成するファクトリ クラスをコーディングする必要があります。Encoder をオーバーライドして、独自のカスタム MessageEncoder のインスタンスを返します。
次に、CreateMessageEncoderFactory メソッドをオーバーライドしてこのファクトリのインスタンスを返すようにすることで、サービスまたはクライアントの構成に使用されるバインド要素スタックにカスタム MessageEncoderFactory を接続します。
WCF には、この処理を説明する 2 つの例がサンプル コードと共に用意されています。「カスタム メッセージ エンコーダー : カスタム テキスト エンコーダー」および「カスタム メッセージ エンコーダー : 圧縮エンコーダー」を参照してください。
参照
リファレンス
MessageEncodingBindingElement
MessageEncoderFactory
MessageEncoder