在应用程序启动时从 IHostedService 异步更新 autofac 容器

Update autofac container from IHostedService asynchronously on app startup

我有一个 ASP.net 核心 3.0 应用程序,我想看看我是否可以在应用程序启动时异步注册我的一些 Orleans Cluster 客户端,因为创建并连接到 Orleans Cluster很重。根据这个 article I created my own IHostedService, but when I implemented startAsync method I am not sure how to get the autofac container which I am using in Startup.cs and update it with my clients registrations. I have read this 但是看我下面的代码,我仍然没有看到客户正在注册。这是可行的还是我在这里遗漏了什么?谢谢!

Startup.cs

...
public static IServiceProvider ConfigureServices(IServiceCollection services)
{
    var coreBuilder = new ContainerBuilder();
    
    // other autofac registrations...

    services.AddHostedService<MyService>();
    coreBuilder.populate(services);

    var container = coreBuilder.Build();

    var serviceProvider = new AutofacServiceProvider(container);
    return serviceProvider;
}
MyService.cs

public MyService : IHostedService
{
    private readonly IServiceProvider _serviceProvider;
    public MyService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        // get the autofac container from Startup.cs and update with cluster client registrations? 
        using(var scope = this._serviceProvider.GetRequiredService<ILifeTimeScope>()
.BeginLifeTimeScope(builder => do registration here...)) {}
    }

    // noop
    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

不能像那样即时更新 DI 容器。建好了就建好了。

您还有另一种选择:创建一个缓存客户端的工厂 class,在后台初始化它们,然后从工厂中检索它们。

class MyService
{
    // ...   
}

class MyServiceFactory
{
    private ConcurrentDictionary<string, MyService> _instances = new ConcurrentDictionary<string, MyService>();

    public async Task<MyService> CreateAsync(string key)
    {
        if (_instances.TryGetValue(key, out var service))
        {
            return service;
        }

        // perform expensive initialization
        // ...
        service = new MyService();

        _instances[key] = service;
        return service;
    }
}

class MyServiceInitializer: BackgroundService
{
    private MyServiceFactory _serviceFactory;

    public MyServiceInitializer(MyServiceFactory serviceFactory)
    {
        _serviceFactory = serviceFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await _serviceFactory.CreateAsync("first instance");
        await _serviceFactory.CreateAsync("second instance");
    }
}

将工厂注册为单例,(或使Instances成为static属性)。

services.AddSingleton<MyServiceFactory>();
services.AddHostedService<MyServiceInitializer>();

然后解析一个你需要的实例。它会立即解析,因为它已在后台初始化。

class MyController
{
    private MyServiceFactory _serviceFactory;

    public MyController(MyServiceFactory serviceFactory)
    {
        _serviceFactory = serviceFactory;
    }

    [HttpGet]
    public async Task<ActionResult> Index()
    {
        var service = await _serviceFactory.CreateAsync("first instance");
        // use the service
    }
}