依赖注入,带参数注入

Posted

技术标签:

【中文标题】依赖注入,带参数注入【英文标题】:Dependency injection, inject with parameters 【发布时间】:2016-01-17 02:01:16 【问题描述】:

我正在使用 DI 的 vNext 实现。 如何将参数传递给构造函数? 例如,我有课:

public class RedisCacheProvider : ICacheProvider

    private readonly string _connectionString;

    public RedisCacheProvider(string connectionString)
    
        _connectionString = connectionString;
    
    //interface methods implementation...

和服务注册:

services.AddSingleton<ICacheProvider, RedisCacheProvider>();

如何将参数传递给 RedisCacheProvider 类的构造函数? 以 Autofac 为例:

builder.RegisterType<RedisCacheProvider>()
       .As<ICacheProvider>()
       .WithParameter("connectionString", "myPrettyLocalhost:6379");

【问题讨论】:

我的通用解决方案:gist.github.com/ReallyLiri/c669c60db2109554d5ce47e03613a7a9 相关帖子 - .NET Core DI, ways of passing parameters to constructor 【参考方案1】:

您可以提供一个委托来手动实例化您的缓存提供程序,也可以直接提供一个实例:

services.AddSingleton<ICacheProvider>(provider => new RedisCacheProvider("myPrettyLocalhost:6379"));

services.AddSingleton<ICacheProvider>(new RedisCacheProvider("myPrettyLocalhost:6379"));

请注意,容器不会显式处理手动实例化的类型,即使它们实现了 IDisposable。有关详细信息,请参阅有关 Disposal of Services 的 ASP.NET Core 文档。

【讨论】:

简单实用 不要忘记如果你的服务接受了你注册的其他参数,你可以在注册的时候传递一个引用到你的服务。例如如果“RedisCacheProvider”也需要 ISomeService,你可以这样做:services.AddSingleton(provider => new RedisCacheProvider("myPrettyLocalhost:6379", provider.GetService())); @KévinChalet 如果您在回答中指定“手动实例化类型”是关于通过AddSingleton&lt;T&gt;(T) 注册类型,那将是一件好事。从注册代表返回的类型(例如使用AddSingleton&lt;T&gt;(Func&lt;IServiceProvider, T&gt;))实际上将被丢弃。 如果我有另一个 ICacheProvider 实现,我该如何处理?【参考方案2】:

如果构造器还具有应该由 DI 解决的依赖项,您可以使用它:

public class RedisCacheProvider : ICacheProvider

    private readonly string _connectionString;
    private readonly IMyInterface _myImplementation;

    public RedisCacheProvider(string connectionString, IMyInterface myImplementation)
    
        _connectionString = connectionString;
        _myImplementation = myImplementation;
    
    //interface methods implementation...


Startup.cs:

services.AddSingleton<IMyInterface, MyInterface>();
services.AddSingleton<ICacheProvider>(provider => 
    RedisCacheProvider("myPrettyLocalhost:6379", provider.GetService<IMyInterface>()));

【讨论】:

【参考方案3】:

你可以使用:

 services.AddSingleton<ICacheProvider>(x =>
      ActivatorUtilities.CreateInstance<RedisCacheProvider>(x, "myPrettyLocalhost:6379"));

依赖注入:ActivatorUtilities 会将任何依赖注入到您的类中。

这是 MS 文档的链接:Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance

另外:请参阅@poke 的答案here 了解更多信息。基本上它从提供的服务和您传递的任何其他参数中提取,例如复合构造函数。

【讨论】:

【参考方案4】:

您可以使用下面的示例代码。

经理类:

public class Manager : IManager

    ILogger _logger;
    IFactory _factory;
    public Manager(IFactory factory, ILogger<Manager> logger)
    
        _logger = logger;
        _factory = factory;
    

Startup.cs 类:

public void ConfigureServices(IServiceCollection services)

    services.AddSingleton<IFactory, Factory>(sp =>
    
        var logger = sp.GetRequiredService<ILogger<Factory>>();
        var dbContext = sp.GetRequiredService<MyDBContext>();
        return new Factory(dbContext, logger);
    );
    services.AddTransient<IManager, Manager>(sp =>
    
        var factory = sp.GetRequiredService<IFactory>();
        var logger = sp.GetRequiredService<ILogger<Manager>>();
        return new Manager(factory, logger);
    );

您可以在此处阅读完整示例:DI in Startup.cs in .Net Core

【讨论】:

【参考方案5】:

聚会有点晚了,但您可以 DI 注入一个工厂,该工厂创建并公开您的提供程序类的实例。

【讨论】:

以上是关于依赖注入,带参数注入的主要内容,如果未能解决你的问题,请参考以下文章

Spring Bean 依赖注入常见错误

一个简单例子带你理解 依赖注入

Spring 依赖注入(注入参数)

Spring 依赖注入(注入参数)

ThinkPHP6.0 容器和依赖注入

依赖注入的含义