您如何依赖于将服务注入 IHostedService(计划作业)?
How can you dependency inject an service into an IHostedService (scheduled job)?
意图:我想构建一个 cronjob,用当前数据覆盖缓存内存。它应该是一个单独的服务。
我有一个名为 TimedHostedService 的 IHostedService 和一个名为 ExampleService 的自定义服务。 Example 应该被注入到 TimedHostedService 中,所以它可以调用 ExampleService 中的方法。
ExampleService 应该是唯一覆盖内存的服务
问题: 程序在尝试将 ExampleService 注入 TimedHostedService 时崩溃。出现以下错误信息。
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: Example_Project.Backend.Job.TimedHostedService': Cannot consume scoped service 'Example_Project.Services.IExampleService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable serviceDescriptors, ServiceProviderOptions options)
InvalidOperationException: Error while validating the service
descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService
Lifetime: Singleton ImplementationType:
Example_Project.Backend.Job.TimedHostedService': Cannot consume
scoped service 'Example_Project.Services.IExampleService' from
singleton 'Microsoft.Extensions.Hosting.IHostedService'.
代码
StartUp.cs
public void ConfigureServices(IServiceCollection services)
{
/* Add MemoryCache */
services.AddMemoryCache();
/* Add CronJob / Scheduled Job */
services.AddHostedService<TimedHostedService>();
/* Add Dependency Injection of ExampleService */
services.AddScoped<IExampleService, ExampleService>();
}
ExampleService.cs
public interface IExampleService
{
void SetExample();
IInventoryArticle[] GetExamples();
}
public class ExampleService : IExampleService
{
public Examples[] GetExamples()
{ return null; }
public void SetExample()
{ }
}
TimedHostedService.cs
public class TimedHostedService : IHostedService, IDisposable
{
private readonly ILogger<TimedHostedService> _logger;
private Timer _timer;
private readonly IInventoryService _inventoryService;
public TimedHostedService(
ILogger<TimedHostedService> logger,
IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService; /// Problem Child
}
}
如果您希望使用范围服务,您需要自己创建一个范围;
private readonly IServiceProvider serviceProvider;
public TimedHostedService(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
//...
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using (var scope = serviceProvider.CreateScope())
{
var ... = scope.ServiceProvider.GetService<...>();
//...
}
}
意图:我想构建一个 cronjob,用当前数据覆盖缓存内存。它应该是一个单独的服务。
我有一个名为 TimedHostedService 的 IHostedService 和一个名为 ExampleService 的自定义服务。 Example 应该被注入到 TimedHostedService 中,所以它可以调用 ExampleService 中的方法。 ExampleService 应该是唯一覆盖内存的服务
问题: 程序在尝试将 ExampleService 注入 TimedHostedService 时崩溃。出现以下错误信息。
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: Example_Project.Backend.Job.TimedHostedService': Cannot consume scoped service 'Example_Project.Services.IExampleService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.) Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable serviceDescriptors, ServiceProviderOptions options)
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: Example_Project.Backend.Job.TimedHostedService': Cannot consume scoped service 'Example_Project.Services.IExampleService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
代码
StartUp.cs
public void ConfigureServices(IServiceCollection services)
{
/* Add MemoryCache */
services.AddMemoryCache();
/* Add CronJob / Scheduled Job */
services.AddHostedService<TimedHostedService>();
/* Add Dependency Injection of ExampleService */
services.AddScoped<IExampleService, ExampleService>();
}
ExampleService.cs
public interface IExampleService
{
void SetExample();
IInventoryArticle[] GetExamples();
}
public class ExampleService : IExampleService
{
public Examples[] GetExamples()
{ return null; }
public void SetExample()
{ }
}
TimedHostedService.cs
public class TimedHostedService : IHostedService, IDisposable
{
private readonly ILogger<TimedHostedService> _logger;
private Timer _timer;
private readonly IInventoryService _inventoryService;
public TimedHostedService(
ILogger<TimedHostedService> logger,
IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService; /// Problem Child
}
}
如果您希望使用范围服务,您需要自己创建一个范围;
private readonly IServiceProvider serviceProvider;
public TimedHostedService(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
//...
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using (var scope = serviceProvider.CreateScope())
{
var ... = scope.ServiceProvider.GetService<...>();
//...
}
}