【问题标题】:Injecting logger into middleware dependency将记录器注入中间件依赖项
【发布时间】:2017-05-25 22:18:37
【问题描述】:

我有一个打算在多个项目中使用的中间件库。中间件本身看起来像:

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 注册该类?

【问题讨论】:

  • 看看内存缓存如何注册自己here

标签: asp.net asp.net-core


【解决方案1】:

让您的库的使用者在组合根目录中组合该库的依赖项并没有错。这就是依赖注入的工作原理。您当然可以提供一些默认实现和自定义扩展方法,将这些默认实现注册到 DI 中,然后让使用者简单地调用您的扩展方法。

【讨论】:

  • 确实这是框架本身使用的模式。
  • 自定义扩展方法是一个绝妙的主意 - 它让我可以在内部实现具体实现,但仍将它们注册到我的组合根目录中。
【解决方案2】:

我觉得这里有几点需要澄清:

依赖注入/控制反转

要了解依赖注入 (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 容器将在其中注入所有依赖项。您还可以使用或定义一些配置解决方案的约定,以便类和接口的绑定将自动发生。 底线是类的注册和实际的注入没有联系。但是您提供的代码是执行此操作的默认方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多