【问题标题】: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");

【问题讨论】:

标签: c# asp.net-core dependency-injection asp.net-core-mvc


【解决方案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 注入一个工厂,该工厂创建并公开您的提供程序类的实例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-16
          • 1970-01-01
          • 1970-01-01
          • 2023-03-09
          • 1970-01-01
          • 2016-01-26
          • 2023-03-09
          • 1970-01-01
          相关资源
          最近更新 更多