简单注入器:注入外部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传递到构造函数之间切换?

简单注入器:注入外部Web服务

所以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. 
        }
    });
});