ということでちょっと調べたことのまとめ。(正しいアプローチかどうかは謎です。詳しい人突っ込みどころあったらお願いしますm(_ _)m)
とりあえずクライアント側に自作ビヘイビアをつっこんで、そこでIClientMessageInspectorを継承したクラスをエンドポイントに差し込むイメージでした。
// 自作ビヘイビアとメッセージインスペクター public class SampleBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { Console.WriteLine("AddBindingParameters"); } public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { Console.WriteLine("ApplyClientBehavior"); // クライアントのメッセージインスペクターを仕掛ける clientRuntime.MessageInspectors.Add(new Inspector()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { Console.WriteLine("ApplyDispatchBehavior"); } public void Validate(ServiceEndpoint endpoint) { Console.WriteLine("Validate"); } } // メッセージインスペクター public class Inspector : IClientMessageInspector { public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { Console.WriteLine("AfterReceiveReply"); } public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) { // 何処に接続してそうなのか見る Console.WriteLine("BeforeSendRequest : {0}", channel.RemoteAddress.Uri); return null; } }
ポイントはApplyClientBehaviorで自作のIClientMessageInspectorを差し込んでるところとIClientMessageInspectorの実装クラスのBeforeSendRequestでchannel経由で接続先のアドレスをとっているところです。例ではUriを直接出力してますが、まぁUriをばらしてポートとか接続先のIPとかもとれると思います。
お試し
下記のようなサービスを作って試してみました。
// 公開するサービス [ServiceContract] public interface IService { [OperationContract] string Greet(string name); } public class ServiceImpl : IService { public string Greet(string name) { return string.Format("{0}さんこんにちは", name); } }
あとは、Mainで以下のようにサービスを公開しつつクライアントも作って(作る過程で作成したビヘイビアを設定しています)呼び出しを行っています。
var address = new Uri("http://localhost:8888/Service"); // サービスの公開 var host = new ServiceHost(typeof(ServiceImpl), address); host.AddServiceEndpoint( typeof(IService), new BasicHttpBinding(), address); host.Open(); // クライアントの作成 var channel = new ChannelFactory<IService>( new BasicHttpBinding(), new EndpointAddress(address.ToString())); // ここでエンドポイントに作成したビヘイビアを追加する channel.Endpoint.Behaviors.Add(new SampleBehavior()); // サービスの呼び出し var client = channel.CreateChannel(); Console.WriteLine(client.Greet("Tanaka")); Console.WriteLine(client.Greet("Jiro")); Console.WriteLine(client.Greet("Saburo")); // 後始末 channel.Close(); host.Close();
実行すると以下のような結果になります。
Validate AddBindingParameters ApplyClientBehavior BeforeSendRequest : http://localhost:8888/Service AfterReceiveReply Tanakaさんこんにちは BeforeSendRequest : http://localhost:8888/Service AfterReceiveReply Jiroさんこんにちは BeforeSendRequest : http://localhost:8888/Service AfterReceiveReply Saburoさんこんにちは 続行するには何かキーを押してください . . .