依赖注入:静态参数和服务

时间:2018-05-01 15:24:53

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

我将此服务注入其他控制器。

它需要一个服务,以及一个从配置文件中获取的连接字符串。

public class MyService : IMyService
{
  public MyService(IService1 service1, IService2 service2, string connectionString){
     //...
  }
}

我希望注入IService1IService2,但需要手动指定connectionString。我无法解决这个问题,我看到的例子要么是非常复杂,要么就是我想达到的目标。

public void ConfigureServices(IServiceCollection services)
{
    var cfg = new MyConfiguration();   
    Configuration.Bind("config", cfg);
    var connectionString = cfg["myConnectionString"];
    services.AddSingleton<IMyService, MyService>(/*what can I do here?*/)
}

这可以简单地实现吗?

2 个答案:

答案 0 :(得分:3)

您可以访问工厂代理中的服务提供商。

解析其他依赖项并在初始化服务时注入静态变量。

//...
var connectionString = cfg["myConnectionString"];
services.AddSingleton<IMyService>(_ => 
    new MyService(_.GetService<IService1>(), _.GetService<IService2>(), connectionString));

在上面的示例中,工厂委托中的_IServiceProviderGetService<T>扩展方法用于解析其他服务,只要它们也在服务集合中注册。< / p>

首次请求IMyService时将调用工厂代理。

作为替代方案,引用Options pattern in ASP.NET Core

并假设例如 settings.json 文件

{
  "myConnectionString": "value1_from_json",
}

考虑使用配置扩展提供的IOptions<T>

创建一个类来存储所需的配置。

public class MyConnections {
    public string MyConnectionString { get; set; }
}

重构该类以依赖IOption<MyConnections>

public class MyService : IMyService {
    private string connectionString;
    public MyService(IService1 service1, IService2 service2, IOptions<MyConnections> options){
        connectionString = options.Value.MyConnectionString;
        //...
    }

    //...
}

并在启动时配置

//...

services.Configure<MyConnections>(Configuration);
services.AddSingleton<IMyService, MyService>();

答案 1 :(得分:1)

你可以像Nkosi建议的那样去做,并使用创建服务的工厂。但是这有一个缺点,即这是非常明确的,并且需要您在构造函数签名更改时始终调整对象创建(例如,当您需要不同的依赖项时)。

ASP.NET Core世界中更合适的解决方案是使用选项模式。您所做的基本上不是要求将连接字符串传递给构造函数,而是创建一个配置服务的新配置类型。然后,您可以使用选项模式配置此对象。

这看起来像这样:

ghc

然后在你的创业公司中,只需注册你的类型并配置选项:

public class MyService : IMyService
{
    public MyService(IService1 service1, IService2 service2, IOptions<MyServiceOptions> serviceOptions)
    {
        var connectionString = serviceOptions.Value.ConnectionString;

        //...
    }
}

public class MyServiceOptions
{
    public string ConnectionString
    { get; set; }
}

如果将连接字符串的配置放在单独的配置部分中,您甚至可以这样做:

services.AddSingleton<IMyService, MyService>();
services.Configure<MyServiceOptions>(options => {
    options.ConnectionString = "connection string";
});

假设您的配置如下所示:

services.Configure<MyServiceOption>(configuration.GetSection("MyService"));