読者です 読者をやめる 読者になる 読者になる

WCF でコールバックを使う

WCF ではコールバックが使えるので、試してみました。
コールバックを行うには、専用のインタフェースを定義する必要があります。

public interface IMyCallback
{
    [OperationContract(IsOneWay = true)]
    void Reply(string message);
}

次にサービスコントラクトを定義します。先日のコードをちょっと変更しただけの簡単なものです。ServiceContract 属性で、コールバック用インタフェースを指定しています。

[ServiceContract(CallbackContract = typeof(IMyCallback))]
public interface IMyService
{
    [OperationContract(IsOneWay = true)]
    void Call(string message);
}

サービスを実装します。

public class MyService : IMyService
{
    public void Call(string message)
    {
        Console.WriteLine(message);

        // コールバック用インタフェースを取得
        IMyCallback client = OperationContext.Current.GetCallbackChannel<IMyCallback>();

        // コールバック
        client.Reply("いっぱ〜つ!!");
    }
}

ホストを作成します。今回もコンソールアプリケーションで作成。構成ファイルを書くのが面倒なので、エンドポイントはコードで指定します。

class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(MyService.MyService));

        host.AddServiceEndpoint(
            typeof(MyService.IMyService),   // サービスコントラクト
            new NetTcpBinding(),            // バインディングは TCP
            "net.tcp://localhost:8000/MyService");

        host.Open();

        Console.WriteLine("サービスを起動しました。");
        Console.WriteLine("終了するには Enter キーを押してください。");
        Console.ReadLine();

        host.Close();
    }
}

コールバック用インタフェースを実装するクラスを作成。このクラスがコールバックを処理します。

public class MyCallback : IMyCallback
{
    public void Reply(string message)
    {
        Console.WriteLine(message);
    }
}

最後に、クライアントもコンソールアプリケーションで作成します。

static void Main(string[] args)
{
    // コールバックで呼ばれるオブジェクト
    MyCallback callback = new MyCallback();

    // 非同期双方向通信用のファクトリを生成
    DuplexChannelFactory<IMyService> factory = new DuplexChannelFactory<IMyService>(callback);
    factory.Endpoint.Binding = new NetTcpBinding();
    factory.Endpoint.Contract.ContractType = typeof(IMyService);
    factory.Endpoint.Address = new EndpointAddress("net.tcp://localhost:8000/MyService");

    // チャネル生成
    IMyService service = factory.CreateChannel();

    // サービス呼び出し
    service.Call("ファイト〜!!");

    // 接続を閉じる
    ((IChannel)service).Close();

    Console.ReadLine();
}

実行結果が下の画像です。
f:id:griefworker:20080830003503j:image