「チャネル生成→サービス呼び出し→チャネルを閉じる」という処理を、サービスを呼び出すたびに記述するのは面倒です。できれば、これらの処理を一度のメソッド呼び出しで完結させたい。
何か上手い方法がないか考えたところ、RealProxy を使う方法を思いつきました。
public class ServiceProxy<TChannel> : RealProxy where TChannel : class { private Binding _binding; private EndpointAddress _address; public ServiceProxy(Binding binding, EndpointAddress address) : base(typeof(TChannel)) { _binding = binding; _address = address; } public override IMessage Invoke(IMessage msg) { // チャネル生成 TChannel channel = ChannelFactory<TChannel>.CreateChannel( _binding, _address); IMethodMessage methodMsg = (IMethodMessage)msg; // サービス呼び出し object returnValue = typeof(TChannel).InvokeMember(methodMsg.MethodName, BindingFlags.InvokeMethod, null, channel, methodMsg.Args); ReturnMessage returnMsg = new ReturnMessage( returnValue, null, 0, methodMsg.LogicalCallContext, (IMethodCallMessage)msg); // チャネルを閉じる ((IClientChannel)channel).Close(); return returnMsg; } } public static class ServiceProxyFactory<TChannel> where TChannel : class { public static TChannel Create(Binding binding, EndpointAddress address) { return new ServiceProxy<TChannel>(binding, address).GetTransparentProxy() as TChannel; } }
使い方はいたって簡単。
// プロキシ生成 IHogeService proxy = ServiceProxyFactory<IHogeService>.Create( new NetTcpBinding(), new EndpointAddress(address)); // サービス呼び出し proxy.HogeHoge();
ChannelFactory で生成されるオブジェクトは TransparentProxy だったけど、InvokeMember でサービスを呼び出すことができました。
これは使い勝手が良さそう。