简单注入器:注入外部Web服务
本文关键字:Web 服务 外部 注入 注入器 简单 | 更新日期: 2023-09-27 18:01:51
我在如何使用SimpleInjector正确配置DI方面遇到了一些困难。我有一个外部Web服务,它的绑定位于Web。配置文件。我的外部Web服务位于服务层。我的Web层包含复合根,它调用我的域层来注册服务,然后域层调用DAL层和服务层来注册它需要的服务。这将正常工作,然后在我的域层中,我可以使用我在域服务层构造函数中的服务层上创建的注入服务。
然而,在我的服务层,我有类似下面的东西:
public class MyService : IMyService
{
private readonly ExternalServiceClient _externalServiceClient;
public MyService()
{
_externalServiceClient = new ExternalServiceClient("WSHttpBinding_IExternalService");
}
这个设计可能不是最好的,因为它将MyService与依赖于外部ServiceClient紧密耦合在一起——我想要实现的是能够拥有这个外部客户端的自己的存根,然后轻松地在实际的外部服务客户端或我的存根版本之间切换。
构造函数是这样的
private readonly ExternalServiceClient _externalServiceClient;
public MyService(ExternalServiceClient externalServiceClient)
{
_externalServiceClient = externalServiceClient);
}
其中- externalServiceClient是一个新的
ExternalServiceClient("WSHttpBinding_IExternalService");
或我的存根版本的外部客户端。
我不确定的是SimpleInjector如何正确地连接起来,这样我就可以轻松地在ExternalClient传递到构造函数之间切换?
所以IMyService
是您自己的抽象,ExternalServiceClient
是一些生成的代理和MyService
只是委托给ExternalServiceClient
?如果是这样的话,我会说MyService
实现与ExternalServiceClient
强耦合是很好的。它不包含任何逻辑,只是一些允许将ExternalServiceClient
隐藏在抽象后面的基础设施。您可以简单地创建一个存根IMyService
,而不是创建一个存根ExternalServiceClient
。
此外,如果ExternalServiceClient
是WCF生成的代理,您可能希望让MyService
类控制ExternalServiceClient
的创建和处置,特别是因为WCF服务需要特别注意处置。如果您让容器控制ExternalServiceClient
的处理,那么无论您选择哪种容器,都将使您的DI配置更加困难。
MyService
,最简单的注册方法如下:
container.Register<IMyService>(() => new MyService(
new ExternalServiceClient("WSHttpBinding_IExternalService")));
然而,这个注册的问题是ExternalServiceClient
没有被处理。如果您显式地将ExternalServiceClient
注册为具有作用域生活方式之一的容器,则容器将自动为您处理dispose:
container.Register<IMyService, MyService>();
container.RegisterPerWebRequest<ExternalServiceClient>(
() => new ExternalServiceClient("WSHttpBinding_IExternalService"));
然而,作用域生活方式意味着在整个请求中重用ExternalServiceClient
,这可能不是您所需要的。因此,您也可以将其注册为暂态,并允许在请求结束时处置任何已创建的实例:
var scopedLifestyle = new WebRequestLifestyle();
container.Register<IMyService, MyService>();
container.Register<ExternalServiceClient>(
() => new ExternalServiceClient("WSHttpBinding_IExternalService"));
container.RegisterInitializer<ExternalServiceClient>(client =>
{
scopedLifestyle.RegisterForDisposal(container, client);
});
当然,这种配置的问题是WCF代理是令人讨厌的fckers,可能会从它们的Dispose方法抛出异常,所以您需要做一些额外的处理来正确处理:
var scopedLifestyle = new WebRequestLifestyle();
container.Register<IMyService, MyService>();
container.Register<ExternalServiceClient>(
() => new ExternalServiceClient("WSHttpBinding_IExternalService"));
container.RegisterInitializer<ExternalServiceClient>(client =>
{
scopedLifestyle.WhenScopeEnds(container, () =>
{
try
{
client.Dispose();
}
catch
{
// According to Marc Gravell we need to have a catch all here.
}
});
});