Dependency Injection with WCF proxy
I have a service (Service1) that uses another serice (Service2). I am using Dependency injection for both services and need to inject the proxy for Service2 into Service1.
I am unsure how to deal with the fact that the proxy is not a simple class of type IService2 but a proxy inheriting from ClientBase as well. Obviously my Service1 implementation needs to open the proxy and should also close it after use or abort it if an exception occurs but if I am just injecting an instance of IService2 then I cannot do this (without casting) because the Open, Close and Abort methods are on the base开发者_如何学编程 class whilst my operations are on the interface.
When it comes to testing Service1, I would expect to mock just the interface but if the Service1 implementation expect Open, Close and Abort methods, then this is tricky. In the past, I have done something hacky like this but there must be a better way!
var proxyBase = _service2 as ClientBase;
if (proxyBase != null)
{
proxyBase.Open();
}
_service2.DoOperation("blah"); //the actual operation
if (proxyBase != null)
{
proxyBase.Close();
}
// repeat for Abort in exception handler(s).
What are other people doing?
Thanks
The auto generated class that you get for adding a service reference for a WCF service is implemented as a partial class. What I do is create a another partial file for that class and implement an interface that exposed those methods, and then use that interface where you would normally use the ClientBase or WCF interface
public partial class Service2 : IClientService2
{}
If IClientService2 has the Abort and Close methods that match the ClientBase methods it should be all you need.
public interface IClientService2 : IService2 // where IService2 is the WCF service interface
{
void Abort();
void Close();
}
I suggest injecting a factory to construct WCF services rather than injecting the proxy itself since when a fault occurs then the channel is no longer able to be used and you will need to construct a new proxy.
IClientService2 proxy = _service2Factory.Create();
proxy.Open();
proxy.DoOperation("blah"); //the actual operation
proxy.Close();
Your interface is poluted because of the requirements imposed by Wcf. If you were not using wcf you would not have an Open and Close method. In an ideal world the interface should look the same as if the service was in process.
Have you chosen your IoC container yet? If you haven't I would consider looking at Windsor. This will allow you to maintain a clean interface and either inject the service as an in process object or a wcf proxy.
container = new WindsorContainer().AddFacility<WcfFacility>();
container.Register(Component
.For<IClientService2>()
.ActAs(DefaultClientModel)
.On(WcfEndpoint.FromConfiguration("YourServiceNameInConfiguration")))
.LifeStyle.Transient);
The WcfFacility will do all the opening and closing of the channel for you.
I ended up using this approach which uses Castle Dynamic Proxy to intercept calls and handle WCF specifics. It works really well and allows the class where the proxy is injected to treat it like a normal class / interface. This class is then totally unit testable by mocking the service contract interface.
精彩评论