2017-05-24 76 views
0

我有一个中间件库,我打算在多个项目中使用它。中间件本身看起来是这样的:将注入器注入中间件依赖关系

public SdkMiddleware(RequestDelegate next, ILogger<SdkMiddleware> logger, ISdk sdk) 
{ 
    this.next = next; 
    this.logger = logger; 
    this.sdk = agentSdk; 

    this.sdk.Init(); 
    ... 
} 

由于DI,我可以简单地注入我的记录:

// Would rather this class be internal... 
public class Sdk: ISdk 
{ 
    private ILogger<Sdk> logger; 
    public Sdk(ILogger<Sdk> logger) 
    { 
     this.logger = logger; 
    } 

    public void Init() { 
     this.logger.Info(...) // Do some logging 
    } 

这样做的缺点是我的类需要在每一个ASP.Net项目的Startup.cs登记:

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddTransient<ISdk, Sdk>(); 

是最好的/唯一的路线?每次我想要将一个记录器注入一个类,我需要在我的组合根目录中注册该类的DI。

+0

看看内存缓存怎么注册自己[这里](https://github.com/aspnet/Caching/blob/dev/src/Microsoft.Extensions.Caching.Memory/MemoryCacheServiceCollectionExtensions.cs#L22-L33) – Tseng

回答

2

使您的库的使用者在组合根中为此库创建依赖关系没有任何问题。这就是依赖注入的工作原理。您当然可以提供一些默认实现和自定义扩展方法,将这些默认实现注册到DI中,然后让消费者简单地调用您的扩展方法。

+0

的确如此是框架本身使用的模式。 – ssmith

+0

自定义扩展方法是一个很好的主意 - 让我在内部实现具体实现,但仍然将它们注册在我的组合根目录中。 –

1

有几件事情,我觉得需要澄清一下:

控制

要了解什么是依赖注入的好处(DI)最好是看原则

依赖注入/反转DI实现的控制反转(IoT)。 就你而言,你希望SdkMiddleware类包含对ILogger实现的引用。最简单的方法是为SdkMiddleware类创建一个实现ILogger接口的类的实例。这种方法的缺点是SdkMiddleware需要知道哪个类实现了ILogger接口以及如何实例化它。换句话说,SdkMiddleware控制着ILogger对象的创建。当知道哪个类实现ILogger以及如何创建实例的责任从SdkMiddleware转移到其他类(DI中的依赖容器)和实例(如果提供给SdkMiddleware使用(通过DI注射)。在这种情况下,对创建ILogger对象的控制在SdkMiddleware之外。由于这改变了控制方向,所以称为“控制反转”。 这种方法的好处是,当您需要提供另一个ILogger实现或更改创建该类实例的方式时,您根本不需要更改SdkMiddleware。

自举

所以现在我们澄清为什么我们使用DI,让我们来看看有哪些我们需要使用它。 创建所有实例的对象,控制将哪个对象注入到哪个对象中并将准备好使用对象的对象称为DI容器或IoT容器。在asp.net核心中,“IServiceCollection服务”用作这样的容器。但它仍然需要知道如何创建对象以及为哪个接口注入哪个实现。这是引导进来的地方。 在引导程序类或方法中,您需要指定如何从类构建对象以及类如何与接口相关。作为前者的一个例子,假设您需要将数据库的连接字符串从配置传递到创建数据库连接的类。至于后者,这正是你的行“services.AddTransient()”所做的。

答案

我很抱歉花了这么久才给你的问题的实际答案,但我想先提供一些概述。 您是否需要指定类和接口之间的关系以将记录器插入到类中?不可以。您的类甚至可能没有接口,DI容器将默认注入所有依赖项,如果您要求类的对象而不是接口的实例。您还可以使用或定义一些约定而不是配置解决方案,以便类和接口的绑定将自动发生。 底线是一个类的注册和实际的注入没有连接。但是您提供的代码是执行此操作的默认方式。