ASP.NET ядро ​​вызова асинхронной инициализации на одно сервис - PullRequest
2 голосов
/ 10 мая 2019

У меня есть служба, которая асинхронно читает некоторое содержимое из файла с помощью метода InitAsync

public class MyService : IService {
    private readonly IDependency injectedDependency;

    public MyService(IDependency injectedDependency) {
        this.injectedDependency = injectedDependency;
    }

    public async Task InitAsync() {
        // async loading from file.
    }
}

Теперь этот сервис внедрен в мой контроллер.

public class MyController : Controller {
    private readonly IService service;

    public MyController(IService service) {
        this.service = service;
    }
}

Теперь я хочу одноэлементный экземпляр MyService. И я хочу вызвать InitAsync при запуске.

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        ......
        services.AddSingleton<IService, MyService>();
        var serviceProvider = services.BuildServiceProvider();
        // perform async init.
        serviceProvider.GetRequiredService<IService>().InitAsync();
    }
}

То, что происходит во время запуска, создается экземпляр MyService и на нем вызывается InitAsync(). Затем, когда я вызвал класс контроллера, создается другой экземпляр MyService, который затем повторно используется для последующих вызовов.

Что мне нужно, так это инициализировать только 1 экземпляр, который называется InitAsync () на нем при запуске, и чтобы он мог повторно использоваться контроллерами.

1 Ответ

2 голосов
/ 10 мая 2019

То, что происходит во время запуска, создается экземпляр MyService и вызывается InitAsync () для него.Затем, когда я вызвал класс контроллера, создается другой экземпляр MyService, который затем повторно используется для последующих вызовов.

Когда вы вызываете BuildServiceProvider(), вы создаете отдельный экземпляр IServiceProvider, который создаетего собственный экземпляр синглтона IService.IServiceProvider, который используется при разрешении IService, который предусмотрен для MyController, отличается от того, который вы создали сами, поэтому сам IService также отличается (и не инициализирован).

Что мне нужно, так это инициализировать только 1 экземпляр, называемый InitAsync () на нем при запуске, и чтобы его также могли повторно использовать контроллеры.

Вместо того, чтобы пытаться разрешить и инициализировать IService внутриStartup.ConfigureServices, вы можете сделать это в Program.Main.Это допускает две вещи:

  1. Использование того же экземпляра IService для инициализации и последующего использования.
  2. await при вызове InitAsync, который в настоящее время используется для запуска и показа.

Вот пример того, как Program.Main может выглядеть:

public static async Task Main(string[] args)
{
    var webHost = CreateWebHostBuilder(args).Build();

    await webHost.Services.GetRequiredService<IService>().InitAsync();

    webHost.Run();
    // await webHost.RunAsync();
}

Используется async Main, чтобы разрешить использование await, создает IWebHost и использует его IServiceProvider для разрешения и инициализации IService.Код также показывает, как вы можете использовать await с RunAsync, если вы предпочитаете, теперь, когда метод async.

...