繁体   English   中英

在asp.net核心依赖注入中注册类型时如何处理混合构造函数参数

[英]How to deal with mixed constructor parameters when registering types in asp.net core dependency injection

我想知道如何在 ASP.NET Core 中处理具有对象和字符串作为参数的类型的依赖项注入。 由于字符串无法注册到 DI 框架,我目前正在使用 implementationfactory使用服务定位器模式,还有其他方法吗? 是否有类似于 Autofac 的 .WithParamenter 命名参数?

对于参数已经注册到 DI 框架的类型,Asp.net 核心 DI 使得向 DI 框架注册类型变得容易(并且干净)。

给定以下三个构造函数:

  public MyStateService() { /* .... */ }
  public MyServiceBackend(IMyStateService state) { /* .... */}
  public MyServiceClient(IMyStateService state, IMyServiceBackend backend, string logConfigPath) { /*.... */ }

前两种类型很容易注册到 DI 容器,如下所示:

  services.AddScoped<IMyStateService , MyStateService>();
  services.AddScoped<IMyServiceBackend, MyServiceBackend>();

然而,对于第三个,我必须使用 implementationfactory使用服务定位器模式来获取前两种类型的注入。

  services.AddScoped<IMyServiceClient, MyServiceClient>((ctx) =>
  {
      IMyStateService state= ctx.GetRequiredService<IMyStateService >();
      IMyServiceBackend backend = ctx.GetRequiredService<IMyServiceBackend>();
      return new MyServiceClient(state, backend, _serilogConfigPath);
  }); 
            
            

我的技术项目在看到服务定位器 [反模式] 时变得疯狂,并需要一个没有服务定位器的解决方案。 如果我们使用Autofac,我们可以使用.WithParameter()作为命名参数,但 dotnet core di 没有,是吗? 还有另一种优雅的方式吗?

利用ActivatorUtilities

public static T CreateInstance<T> (IServiceProvider provider, params object[] parameters);

哪一个

使用直接和/或从 IServiceProvider 提供的构造函数参数实例化类型。

//...

services.AddScoped<IMyServiceClient, MyServiceClient>((provider) => {
    return ActivatorUtilities.CreateInstance<MyServiceClient>(provider, _serilogConfigPath);      
}); 

//...

在上面的示例中,提供程序将用于解析其他依赖项,而将直接提供字符串参数。

如果目标类可以重构,则不要显式依赖字符串。 考虑使用选项模式

参考: ASP.NET Core 中的选项模式

创建一个具体的类来存储所需的数据

public class LogConfigOPtions {
    public string Path { get; set; }
}

重构目标类以依赖它

//...
string string logConfigPath;

//ctor
public MyServiceClient(IMyStateService state, IMyServiceBackend backend, IOptions<LogConfigOPtions> options) { 

    logConfigPath = options.Value.Path;

    //...
 }

最后,在注册服务时相应地配置选项

//...

services.Configure<LogConfigOPtions>(option => {
    option.Path = _serilogConfigPath;
});
services.AddScoped<IMyServiceClient, MyServiceClient>();
services.AddScoped<IMyStateService , MyStateService>();
services.AddScoped<IMyServiceBackend, MyServiceBackend>();

//...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM