System.AggregateException: '部分服务无法构建
System.AggregateException: 'Some services are not able to be constructed
我在 运行 我的应用程序中偶然发现了这个错误。
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: testing.CacheUpdater': Unable to resolve service for type 'testing.CacheMonitorOptions' while attempting to activate 'testing.CacheUpdater'.
应用说明
我正在制作一个应用程序,我定期(每 10 秒)用我从数据库中获取的值更新 MemoryCache。
为此我使用了 3 个 classes,CacheMonitor(负责 update/override 缓存),StudentsContext(负责从数据库中获取数据)和 CacheUpdater是在 CacheMonitor class.
中调用 Update 方法的后台服务
我已经像这样将它们注入到我的 DI 容器中:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddHostedService<CacheUpdater>();
services.AddDbContext<StudentsContext>(options =>
{
options.UseSqlServer(Configuration["Database:ConnectionString"]);
});
services.Configure<CacheMonitorOptions>(Configuration.GetSection("CacheUpdater"));
services.AddTransient<ICacheMonitor, CacheMonitor>();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "testing", Version = "v1" });
});
}
CacheMonitor.cs
public class CacheMonitor : ICacheMonitor
{
private readonly IMemoryCache _cache;
private readonly ILogger<CacheMonitor> _logger;
private readonly StudentContext _databaseContext;
public CacheMonitor(
IMemoryCache cache,
IOptions<CacheMonitor> options,
StudentContext context,
ILogger<CacheMonitor> logger)
{
this._cache = cache;
this._databaseContext = context;
this._logger = logger;
}
public void UpdateCache()
{
//updates cache
}
}
CacheUpdater.cs
public class CacheUpdater{
private readonly ICacheMonitor _cacheMonitor;
private readonly CacheMonitorOptions _cacheMonitorOptions;
private readonly ILogger<CacheUpdater> _logger;
public CacheUpdater(
ICacheMonitor cacheMonitor,
CacheMonitorOptions cacheMonitorOptions,
ILogger<CacheUpdater> logger)
{
_cacheMonitor = cacheMonitor;
_cacheMonitorOptions = cacheMonitorOptions;
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"trying to update cache");
_cacheMonitor.UpdateCache();
Thread.Sleep(_cacheMonitorOptions.Interval);
return Task.CompletedTask;
}
}
我知道它与服务的生命周期有关,但我不确定如何解决它。
更改 CacheUpdater
ctor 以接受 IOptions<CacheMonitorOptions>
而不是选项(对其他代码进行相应更改):
public CacheUpdater(
ICacheMonitor cacheMonitor,
IOptions<CacheMonitorOptions> cacheMonitorOptions,
ILogger<CacheUpdater> logger
)
{
...
}
另请查看 docs。
UPD
解决评论中的问题 - 如果您不想在文档中使用 timed background tasks 中的模式,您可以按照以下方式做一些事情(未测试):
public class CacheUpdater
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly CacheMonitorOptions _cacheMonitorOptions;
private readonly ILogger<CacheUpdater> _logger;
public CacheUpdater(
IServiceScopeFactory scopeFactory,
CacheMonitorOptions cacheMonitorOptions,
ILogger<CacheUpdater> logger
)
{
_scopeFactory = scopeFactory;
_cacheMonitorOptions = cacheMonitorOptions;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while(!stoppingToken.IsCancellationRequested) // !
{
_logger.LogInformation($"trying to update cache");
using (var scope = _serviceScopeFactory.CreateScope())
{
var cacheMonitor = scope.ServiceProvider.GetService<ICacheMonitor>();
cacheMonitor.UpdateCache();
await Task.Delay(_cacheMonitorOptions.Interval, stoppingToken); // DO NOT USE THREAD SLEEP HERE!
}
}
}
}
我在 运行 我的应用程序中偶然发现了这个错误。
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: testing.CacheUpdater': Unable to resolve service for type 'testing.CacheMonitorOptions' while attempting to activate 'testing.CacheUpdater'.
应用说明 我正在制作一个应用程序,我定期(每 10 秒)用我从数据库中获取的值更新 MemoryCache。
为此我使用了 3 个 classes,CacheMonitor(负责 update/override 缓存),StudentsContext(负责从数据库中获取数据)和 CacheUpdater是在 CacheMonitor class.
中调用 Update 方法的后台服务我已经像这样将它们注入到我的 DI 容器中:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddHostedService<CacheUpdater>();
services.AddDbContext<StudentsContext>(options =>
{
options.UseSqlServer(Configuration["Database:ConnectionString"]);
});
services.Configure<CacheMonitorOptions>(Configuration.GetSection("CacheUpdater"));
services.AddTransient<ICacheMonitor, CacheMonitor>();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "testing", Version = "v1" });
});
}
CacheMonitor.cs
public class CacheMonitor : ICacheMonitor
{
private readonly IMemoryCache _cache;
private readonly ILogger<CacheMonitor> _logger;
private readonly StudentContext _databaseContext;
public CacheMonitor(
IMemoryCache cache,
IOptions<CacheMonitor> options,
StudentContext context,
ILogger<CacheMonitor> logger)
{
this._cache = cache;
this._databaseContext = context;
this._logger = logger;
}
public void UpdateCache()
{
//updates cache
}
}
CacheUpdater.cs
public class CacheUpdater{
private readonly ICacheMonitor _cacheMonitor;
private readonly CacheMonitorOptions _cacheMonitorOptions;
private readonly ILogger<CacheUpdater> _logger;
public CacheUpdater(
ICacheMonitor cacheMonitor,
CacheMonitorOptions cacheMonitorOptions,
ILogger<CacheUpdater> logger)
{
_cacheMonitor = cacheMonitor;
_cacheMonitorOptions = cacheMonitorOptions;
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"trying to update cache");
_cacheMonitor.UpdateCache();
Thread.Sleep(_cacheMonitorOptions.Interval);
return Task.CompletedTask;
}
}
我知道它与服务的生命周期有关,但我不确定如何解决它。
更改 CacheUpdater
ctor 以接受 IOptions<CacheMonitorOptions>
而不是选项(对其他代码进行相应更改):
public CacheUpdater(
ICacheMonitor cacheMonitor,
IOptions<CacheMonitorOptions> cacheMonitorOptions,
ILogger<CacheUpdater> logger
)
{
...
}
另请查看 docs。
UPD
解决评论中的问题 - 如果您不想在文档中使用 timed background tasks 中的模式,您可以按照以下方式做一些事情(未测试):
public class CacheUpdater
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly CacheMonitorOptions _cacheMonitorOptions;
private readonly ILogger<CacheUpdater> _logger;
public CacheUpdater(
IServiceScopeFactory scopeFactory,
CacheMonitorOptions cacheMonitorOptions,
ILogger<CacheUpdater> logger
)
{
_scopeFactory = scopeFactory;
_cacheMonitorOptions = cacheMonitorOptions;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while(!stoppingToken.IsCancellationRequested) // !
{
_logger.LogInformation($"trying to update cache");
using (var scope = _serviceScopeFactory.CreateScope())
{
var cacheMonitor = scope.ServiceProvider.GetService<ICacheMonitor>();
cacheMonitor.UpdateCache();
await Task.Delay(_cacheMonitorOptions.Interval, stoppingToken); // DO NOT USE THREAD SLEEP HERE!
}
}
}
}