WCFには、3種類の通信方法があります。
- 要求/応答パターン
- 一方向通信パターン
- 双方向通信パターン(非同期)
双方向通信パターンは、文字通りクライアントとサービスの双方で通信を行いあうパターンです。
イメージとしては、クライアントがサービスを呼び出すと、処理がサービス側で行われ
サービス側の処理が完了すると、今度はサービス側からクライアント側のコールバックが呼ばれるイメージです。
双方向通信を行う場合、サービスインタフェースの定義に加えてコールバック用のインタフェースを定義する必要があります。
双方向通信の場合、サービスメソッドとコールバックメソッドのどちらもIsOneWay=trueを設定する必要があります。
(非同期で呼び合うため、IsOneWayを設定する必要がある。)
双方向通信を行うために必要な設定は
- Callback用のインターフェースを定義
- CallbackContractの設定
- ServiceContractにCallbackContractを設定する必要がある。
- サービスメソッドにIsOneWay=trueを設定
- コールバックメソッドにIsOneWay=trueを設定
- クライアント側にてコールバックインターフェースを実装
- サービスメソッド内にて、OperationContextからコールバックを取得し呼出
- クライアント側にて、プロキシ作成時にInstanceContextを渡す
- bindingに双方向通信をサポートしているものを設定 (wsDualHttpBindingなど)
となります。箇条書きにすると多くなりますが
実際、実装するとなると、そんなに大変ではないです。
以下、サンプルです。
まず、コールバックインターフェース定義。
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { public interface IMyCallback { [OperationContract(IsOneWay=true)] void SendData(string name); } }
つづいて、サービス定義。
CallbackContractを設定する必要がある事に注意。
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { [ServiceContract( Namespace="http://Gsf.Samples.WCF", CallbackContract=typeof(IMyCallback))] public interface IMyService { [OperationContract(IsOneWay=true)] void Regist(string name); } }
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { public class MyService : IMyService { public void Regist(string name) { Console.Write("[CALL] Regist() => "); var context = OperationContext.Current; var callback = context.GetCallbackChannel<IMyCallback>(); Console.WriteLine("[CALLBACK] SendData();"); callback.SendData(string.Format("{0}_Callback", name)); } } }
次にホストアプリ。
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { class Program { static void Main() { using (var host = new ServiceHost(typeof(MyService))) { host.Open(); Console.WriteLine("サービスが開始されました。"); Console.WriteLine("press <ENTER> to exit..."); Console.ReadLine(); host.Close(); } } } }
ホスト側のアプリケーション構成ファイル。
bindingには、双方向通信をサポートしているwsDualHttpBindingを指定しています。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="Gsf.Samples.WCF.MyService"> <host> <baseAddresses> <add baseAddress="http://localhost:8087/WCFSample007/MyService"/> </baseAddresses> </host> <endpoint address="" binding="wsDualHttpBinding" contract="Gsf.Samples.WCF.IMyService" /> </service> </services> </system.serviceModel> </configuration>
次にクライアント側。
コールバックインターフェースを実装しています。
また、Loadイベントにてプロキシオブジェクトを作成していますが
その際に、InstanceContextを生成し渡しています。
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.ServiceModel; namespace Gsf.Samples.WCF { public partial class Form1 : Form, MyServiceRef.IMyServiceCallback { MyServiceRef.MyServiceClient _client; public Form1() { InitializeComponent(); FormClosing += (s, e) => { _client.Close(); }; } private void Form1_Load(object sender, EventArgs e) { lblResult.ResetText(); ActiveControl = btnCallServiceMethod; // 双方向通信を行う場合、サービス側にコールバックの実装を教える必要がある。 var context = new InstanceContext(this); _client = new MyServiceRef.MyServiceClient(context); } private void btnCallServiceMethod_Click(object sender, EventArgs e) { _client.Regist("WCF Study"); } // コールバックの実装 public void SendData(string name) { lblResult.Text = name; } } }
最後にクライアント側のアプリケーション構成ファイル。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="http://localhost:8087/WCFSample007/MyService" binding="wsDualHttpBinding" contract="MyServiceRef.IMyService" /> </client> </system.serviceModel> </configuration>
サンプルは以下の場所にアップしてあります。
https://sites.google.com/site/gsfzero1/Home/WCFSample-007.zip?attredirects=0&d=1
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ