[T2-401 デモ (1)] WCF の Transport レベルの Custom Channel Sample


環境 :
Visual Studio 2008 (.NET Framework 3.5)

こんにちは。 

  1. WCF の Transport レベルの Custom Channel Sample
  2. Rehosting を使ったエンドユーザへのワークフロー公開
  3. WF による Rule Base のアプリケーション
  4. Custom の SharePoint Workflow Editor

製品開発者向けということで実施した Tech Ed の T2-401 セッションですが、お約束通り、デモを添付しておきます。

まずは、最初にお話した、WCF の TransportBindingElement を継承したバインディング要素のカスタムチャネルをみて頂くための BakaChannel というあまりきれいな名前ではないサンプルです。
チャネルのメカニズムを詳しくみていくための簡単なサンプルです。

download sample (20080826_WCFBakaChannelDemo) 

「WCF がその内部でどのようなパイプラインで処理されるか ?」、「WCF のチャネルとは何か ?」 については、申し訳ありませんが、ここでは記載しません。(何某かのドキュメントを参照して事前に理解しておいてください)

セッションでもご説明しましたが、上位のチャネル (TransportBindingElement 以外の層の Channel) の構築は仕組みを理解しておけば一般にそれほどむずかしいものではありませんでした。セッションの中でお見せしたように、こうしたチャネルでは、大元で呼び出される BindingElement に渡されてくる BindingContext というオブジェクトを使い、BuildInnerChannelFactory / BuildInnerChannelListener という各メソッドを呼び出すことで、例えば Request-Reply モデルの場合には、IRequestChannel / IReplyChannel 型を受け付ける内部の (基底の) ファクトリー (ChannelFactory) やリスナー (ChannelListener) を取得することができ、さらに、このファクトリーの CreateChannel メソッドや、リスナーの AcceptChannel メソッドで、今後は内部チャネルを取得することができます。乱暴な書き方かもしれませんが、独自な処理が必要でない箇所では、すべてこれらのメソッドをそのまま使ってインタフェース実装や override メソッドを実装すれば、それでカスタムチャネルの完成ということになります。(独自な処理が必要なメソッドだけカスタムコードを記述して、内部の ChannelListener / ChannelFactory / Channel に処理を渡していけば OK です。)
コードの一部を抜粋すると、以下のようなスタイルになるでしょう。

IDuplexSessionChannel innerChannel;

 

protected override void OnOpen(TimeSpan timeout)

{

    innerChannel.Open(timeout);

}

 

public bool WaitForMessage(TimeSpan timeout)

{

    return innerChannel.WaitForMessage(timeout);

}

 

こうしたサンプルは数多く存在し、例えばダウンロードセンターにある 「Windows Communication Foundation (WCF), Windows Workflow Foundation (WF) and Windows CardSpace Samples」 からも 「ChunkingChannel」 という動くサンプルが入手できます。(ChunkingChannel は、メッセージを特定のバイト数に分割して送信するという Channel のサンプルです)

では、最後のトランスポートレベルのチャネルではどのように処理すれば良いでしょうか ? そのサンプルが、ここで掲載している上記のサンプルになります。

サンプルは、最終的な Message をファイルに書き込んで、サービス側ではそのファイルの内容をウォッチして処理します。(Reply も同様にファイルを使用します。)
大枠の流れは Tech*Ed のセッションでご説明しますので省略しますが、セッションを受けていない方は、ブレークポイント (F9) などを設定して追跡 (F10 / F11) するなどして流れを追うとよいでしょう。(WCF の Message の中身なども見ることができます)
コードは Channel の理解をすることが目的ですので、極力簡単になるように作成しています。そのため、排他の処理などもいっさい配慮していないので注意してください。(このプロジェクト名はそうしたことから名付けています)

以下にソースコードと要旨を簡単に記載しておきます。

==========

まず最初に、サービス側もクライアント側も、すべては BindingElement からはじまります。
今回サンプルとしている単純な Request - Reply 型の通信では、サービスは BindingElement を使って ChannelListener を構築し、クライアントはこの BindingElement を使って ChannelFactory を構築しますので、ここではその構築のための処理を記載しています。

public class BakaBindingElement : TransportBindingElement

{

    public override string Scheme

    {

        get {

            return "baka.file";

        }

    }

 

    public override BindingElement Clone()

    {

        BakaBindingElement clone = new BakaBindingElement();

        return clone;

    }

 

    // Request-Reply 型の通信のみサポート

    // (Input/Output, Duplex, Session, などはサポートしない !)

    public override bool CanBuildChannelFactory<TChannel>(BindingContext context)

    {

        if ((typeof(TChannel) != typeof(IRequestChannel)) &&

            (typeof(TChannel) != typeof(IReplyChannel)))

            return false;

 

        return true;

    }

 

    // Request-Reply 型の通信のみサポート

    // (Input/Output, Duplex, Session, などはサポートしない !)

    public override bool CanBuildChannelListener<TChannel>(BindingContext context)

    {

        if( (typeof(TChannel) != typeof(IRequestChannel)) &&

            (typeof(TChannel) != typeof(IReplyChannel)) )

            return false;

 

        return true;

    }

 

    // SampleClient Factory をつかいます !

    public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)

    {

        BakaChannelFactory factory = new BakaChannelFactory();

        return (IChannelFactory<TChannel>)factory;

    }

 

    // SampleService Listener を使います !

Skip to main content