简体   繁体   English

class 中的依赖注入不适用于工人服务

[英]Dependency injection in a class not working on a worker service

Is there a way to DI something into a class?有没有办法将一些东西输入 class?

For example,例如,

I have a .net 6 worker service that looks like the following:我有一个 .net 6 工人服务,如下所示:

Startup:启动:

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:工人.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();
        }

PartService:零件服务:

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

        public async Task DoSomething()
        {
        }

The issue I am facing is where I say: var partService = new PartService();我面临的问题是我说的: var partService = new PartService(); It is telling me that I am missing all the paramters in the constructor.它告诉我我缺少构造函数中的所有参数。

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

I know with mvc the constructors pick up on the DI stuff on its own, how can I do that in this case?我知道使用 mvc,构造函数会自行处理 DI 内容,在这种情况下我该怎么做?

The Databases are scoped so I cannot consume them directly in the worker, so I need to DI them in to each respective service.数据库是有范围的,所以我不能直接在 worker 中使用它们,所以我需要将它们 DI 到每个相应的服务中。 But its asking for them on the object creation.但它在 object 创建时要求它们。

You've almost got it.你几乎明白了。

It's normal for background services to be singletons (and thus only allow singleton dependencies).后台服务是单例是正常的(因此只允许 singleton 依赖)。 By default, there's no DI scope within ExecuteAsync , but you can create your own :默认情况下, ExecuteAsync中没有 DI scope,但您可以创建自己的

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();
}

The other thing you need to know is that the .NET DI is rather simple-minded.您需要知道的另一件事是 .NET DI 相当简单。 The common pattern is to explicitly register every single type you need, including types that only have a single constructor:常见的模式是显式注册您需要的每个类型,包括只有一个构造函数的类型:

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

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

Now that you've defined PartService as a scoped service, you can ask the DI to create an instance for you:现在您已经将PartService定义为作用域服务,您可以要求 DI 为您创建一个实例:

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

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

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

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