class 中的依赖注入不适用于辅助服务

Dependency injection in a class not working on a worker service

有没有办法将一些东西 DI 到 class?

例如,

我有一个 .net 6 worker 服务,如下所示:

启动:

IConfiguration builder =
    new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", false, true)
    .AddEnvironmentVariables()
    .Build();

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
        services.AddSingleton(mapper);

        services.AddScoped<MpwContext>(
            serviceProvider =>
            {
                return new MyDBContext(builder.GetSection("MyDBConnectionString").Value.ToString());
            });
    }

Worker.cs:

      public Worker(ILogger<Worker> logger, IConfiguration configuration, IMapper mapper)
        {
            //All the constructor stuff here
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var partService = new PartService();

            await partService.DoSomething();
        }

零件服务:

       public PartService(IMapper mapper, MyDbContext myDbContext)
        {
            _mapper = mapper;
            _myDbContext = myDbContext;
        }

        public async Task DoSomething()
        {
        }

我面临的问题是我说的:var partService = new PartService(); 它告诉我我缺少构造函数中的所有参数。

There is no argument given that corresponds to the required field MyDbContext and mapper....

我知道使用 mvc 时构造函数会自行处理 DI 内容,在这种情况下我该怎么做?

数据库是有范围的,所以我不能直接在 worker 中使用它们,所以我需要将它们 DI 到每个相应的服务中。但是它在对象创建时要求它们。

你快搞定了。

后台服务是单例是正常的(因此只允许单例依赖)。默认情况下,ExecuteAsync 内没有 DI 范围,但您可以 create your own:

private readonly IServiceProvider _serviceProvider;

public Worker(IServiceProvider serviceProvider, ILogger<Worker> logger, IConfiguration configuration, IMapper mapper)
{
  _serviceProvider = serviceProvider;
  ...
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
  using var scope = _serviceProvider.CreateScope();

  // Not working yet:
  var partService = new PartService();
  await partService.DoSomething();
}

您需要了解的另一件事是 .NET DI 相当 simple-minded。常见的模式是显式注册您需要的每个类型,包括只有一个构造函数的类型:

services.AddHostedService<Worker>();
services.AddSingleton(mapper);

services.AddScoped<MpwContext>(
    serviceProvider =>
    {
      return new MyDBContext(builder.GetSection("MyDBConnectionString").Value.ToString());
});
services.AddScoped<PartService>();

现在您已经将 PartService 定义为范围服务,您可以要求 DI 为您创建一个实例:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
  using var scope = _serviceProvider.CreateScope();

  var partService = scope.ServiceProvider.GetRequiredService<PartService>();
  await partService.DoSomething();
}