我有一个使用另一个服务(Service2)的服务(Service1)。我正在为两个服务使用依赖注入,并且需要将Service2的代理注入Service1。
我不确定如何处理代理不是IService2类型的简单类,而是从ClientBase继承的代理。显然我的Service1实现需要打开代理,也应该在使用后关闭它或者如果发生异常就中止它但是如果我只是注入一个IService2实例那么我就不能这样做(没有强制转换)因为Open,Close和Abort方法当我的操作在界面上时,它们在基类上。
在测试Service1时,我希望只模拟接口,但如果Service1实现需要Open,Close和Abort方法,那么这很棘手。在过去,我做过像这样的hacky但是必须有更好的方法!
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).
其他人在做什么?
由于
答案 0 :(得分:3)
为WCF服务添加服务引用所获得的自动生成的类实现为部分类。我所做的是为该类创建另一个部分文件,并实现一个暴露这些方法的接口,然后使用通常使用ClientBase或WCF接口的接口
public partial class Service2 : IClientService2
{}
如果IClientService2具有与ClientBase方法匹配的Abort和Close方法,那么它应该就是您所需要的。
public interface IClientService2 : IService2 // where IService2 is the WCF service interface
{
void Abort();
void Close();
}
我建议注入一个工厂来构建WCF服务,而不是注入代理本身,因为当发生故障时,不再能够使用该通道,并且您将需要构建一个新的代理。
IClientService2 proxy = _service2Factory.Create();
proxy.Open();
proxy.DoOperation("blah"); //the actual operation
proxy.Close();
答案 1 :(得分:3)
由于Wcf强加的要求,您的界面很糟糕。如果你没有使用wcf,你将没有Open和Close方法。在理想的世界中,界面看起来应该与服务正在进行中一样。
您是否选择了IoC容器?如果你还没有,我会考虑看Windsor。这将允许您维护一个干净的接口,并将服务作为进程对象或wcf代理注入。
container = new WindsorContainer().AddFacility<WcfFacility>();
container.Register(Component
.For<IClientService2>()
.ActAs(DefaultClientModel)
.On(WcfEndpoint.FromConfiguration("YourServiceNameInConfiguration")))
.LifeStyle.Transient);
WcfFacility将为您完成所有频道的开启和关闭。
答案 2 :(得分:0)
我最终使用了this approach,它使用Castle Dynamic Proxy来拦截调用并处理WCF细节。它工作得很好,并允许注入代理的类将其视为普通的类/接口。然后,通过模拟服务合同接口,该类完全可以进行单元测试。