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!
            }
        }
    }
}