具有多个参数的构造函数的依赖注入解析,其值在运行时确定 .NET Core 3

Ash*_*ran 4 c# dependency-injection .net-core asp.net-core

作为对先前问题(从 Class Libary .NET Core 3 中的非控制器类访问 ILogger )的回复,我们可以将依赖类注入到控制器中。DI 容器在启动时解决对瞬态服务注册的依赖。因此,如果 ClassA 由 Controller 实例化,作为这种机制的结果,我们可以访问 Class A 中的 ILogger。

原始问题代码示例:

public class Startup
{
    ...

    public void ConfigureServices(IServiceCollection services)
    {      
        services.AddLogging();
        services.AddTransient<ClassX>();

        ...
    }
}

public class ControllerB : ControllerBase
{
    private readonly ClassX classX;
    private readonly ILogger logger;

    public ControllerB(ClassX classX, ILogger<ControllerB> logger)
    {
        this.classX = classX;
        this.logger = logger;
    }

    ...
}

public class ClassX
{
   private readonly ILogger logger;

   public ClassX(ILogger<ClassX> logger)
   {
       this.logger = logger;
   }
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个如下场景,其中的构造函数ClassX有多个参数:

public class ClassX
{
    private readonly ILogger logger;
    private int _num1;

    public ClassX(ILogger<ClassX> logger, int num1)
    {
        this.logger = logger;
        this.num1 = num1;
    }
}
Run Code Online (Sandbox Code Playgroud)

ClassX可通过 .NET Core DI 容器使用的构造函数[ActivatorUtilitiesConstructor]

[ActivatorUtilitiesConstructor]
public ClassX(int num)
{
    this.constructorNum = num;
}
Run Code Online (Sandbox Code Playgroud)

所以我们需要在启动时DI解析期间注入构造函数参数。我试过这个

services.AddTransient<Func<int, ClassX>>((provider) =>
{
    return new Func<int, ClassX>((numParam) => new ClassX(numParam));
});
Run Code Online (Sandbox Code Playgroud)

但这会引发错误,因为我们没有传递 ILogger。

如何在运行时通过 DI 注入 ILogger 以及构造函数参数?

Kir*_*kin 8

对于这种情况,您可以使用provider传递给工厂函数的参数来解析ILogger<ClassX>来自 IoC 容器的实例:

services.AddTransient<Func<int, ClassX>>((provider) =>
{
    return new Func<int, ClassX>((numParam) =>
        new ClassX(provider.GetRequiredService<ILogger<ClassX>>(), numParam));
});
Run Code Online (Sandbox Code Playgroud)

provider这是IServiceProvider. 此示例使用扩展方法GetRequiredService来检索 的实例ILogger<ClassX>

  • 您可能想要使用 [`ActivatorUtilities.CreateInstance&lt;ClassX&gt;(provider, numParam)`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createinstance?view =dotnet-plat-ext-3.1) 以避免手动列出所有注入的参数。 (3认同)