回答linked in Mark's commentとthis article hereのバリエーションを使用して、私にとって効果的な解決策を思いつきました。あなたが定義したサービス契約を考えると
、ステップ1はあなたのサービスとIClientChannel
を実装するインターフェイスを定義することになります。
// Service Contract
public interface ICalculator
{
Add(double a, double b);
}
// Interface to expose Close and Abort
public interface ICalculatorChannel : ICalculator, IClientChannel { }
ステップ2プロキシを作成し、接続を閉じるか、中止するコードを実装処理する再利用可能なコードを作成することを含みます。 ServiceClient<T>
で
public class ServiceClient<T> where T : class, IClientChannel
{
private ProxyGenerator _generator = new ProxyGenerator();
public T CreateProxy(string endpointConfigurationName)
{
return _generator.CreateInterfaceProxyWithoutTarget<T>
(new WcfInterceptor<T>(endpointConfigurationName));
}
}
T ProxyGenerator城プロジェクトの一部であり、ステップ1で定義ICalculatorChannel
かかります。ここでの使用方法は、WCFサービスへの呼び出しをインターセプトし、前後のアクションを実行できるようにすることです。
public class WcfInterceptor<T> : IInterceptor where T : IClientChannel
{
private ChannelFactory<T> _factory = null;
public WcfInterceptor(string endpointConfigurationName)
{
_factory = new ChannelFactory<T>(endpointConfigurationName);
}
public void Intercept(IInvocation invocation)
{
T channel = _factory.CreateChannel();
try
{
invocation.ReturnValue = invocation.Method.Invoke
(channel, invocation.Arguments);
}
finally
{
closeChannel(channel);
}
}
}
ご覧のとおり、Interceptメソッドは、チャネルとチャネルを閉じるための呼び出しをカプセル化します。 closeChannel
メソッドは、Close()
またはAbort()
を呼び出すという決定を処理します。
private void closeChannel(T channel)
{
if (channel != null)
{
try
{
if (channel.State != CommunicationState.Faulted)
{
channel.Close();
}
else
{
channel.Abort();
}
}
catch
{
channel.Abort();
}
}
}
ここで、このServiceClientの使用方法をまとめたクラスを作成します。
public class Calculator : ICalculator
{
private var _calcualtor = new ServiceClient<ICalculatorChannel>();
public void Add(double a, double b)
{
var proxy = _calculator.CreateProxy("endpointConfigGoesHere");
return proxy.Add(a, b);
}
}
addの実装は、もはやWCF接続の問題に対処する必要はありません。消費クラスは、サービス契約について知っているだけです。障害のある接続を扱うのは、今やServiceClient
クラスで扱われています。
クライアントは、現在1つの依存関係のみを取る必要があります。
public class MyClient
{
private ICalculator _calculator;
public MyClient(ICalculator calculator)
{
_calculator = calculator;
}
}
そして、IOCは、クライアントを移入することができます
Bind<ICalculator>().To<Calculator>();
あなたはサービス側またはクライアント側について尋ねていますか? –
私はクライアント側について疑問に思います。明確にするために、別のアセンブリでインターフェイスを作成し、複数の実装を使用すると、wcf実装のオブジェクトのライフタイムを管理するのが難しいため、実装をスワップするのが難しくなります。 –
http://stackoverflow.com/questions/3010820/dependency-injection-wcf/3011473#3011473 –