J'ai un service qui lit de manière asynchrone du contenu d'un fichier dans une méthode appelée InitAsync
public class MyService : IService {
private readonly IDependency injectedDependency;
public MyService(IDependency injectedDependency) {
this.injectedDependency = injectedDependency;
}
public async Task InitAsync() {
// async loading from file.
}
}
Maintenant, ce service est injecté dans mon contrôleur.
public class MyController : Controller {
private readonly IService service;
public MyController(IService service) {
this.service = service;
}
}
Maintenant, je veux une instance singleton de MyService. Et je veux appeler InitAsync au démarrage.
public class Startup {
public void ConfigureServices(IServiceCollection services) {
......
services.AddSingleton<IService, MyService>();
var serviceProvider = services.BuildServiceProvider();
// perform async init.
serviceProvider.GetRequiredService<IService>().InitAsync();
}
}
Ce qui se passe est au moment du démarrage, une instance de MyService est créée et InitAsync()
est appelée dessus. Ensuite, lorsque j'ai appelé la classe contrôleur, une autre instance de MyService est créée qui est ensuite réutilisée pour les appels conséquents.
Ce dont j'ai besoin est d'initialiser une seule instance, appelée InitAsync () sur elle au démarrage et de la faire réutiliser également par les contrôleurs.
Ce qui se passe est au moment du démarrage, une instance de MyService est créée et InitAsync () est appelée dessus. Ensuite, lorsque j'ai appelé la classe contrôleur, une autre instance de MyService est créée qui est ensuite réutilisée pour les appels conséquents.
Lorsque vous appelez BuildServiceProvider()
, vous créez une instance distincte de IServiceProvider
, qui crée sa propre instance singleton de IService
. Le IServiceProvider
qui est utilisé lors de la résolution du IService
fourni pour MyController
est différent de celui que vous avez créé vous-même et donc le IService
lui-même est également différent ( et non initialisé).
Ce dont j'ai besoin, c'est d'initialiser une seule instance, appelée InitAsync () sur elle au démarrage et de la faire réutiliser également par les contrôleurs.
Plutôt que d'essayer de résoudre et d'initialiser IService
à l'intérieur de Startup.ConfigureServices
, vous pouvez le faire dans Program.Main
. Cela permet deux choses:
IService
pour l'initialisation et l'utilisation ultérieure.await
en appelant à InitAsync
, qui est actuellement ignoré dans l'approche que vous avez montrée.Voici un exemple de la façon dont Program.Main
pourrait ressembler:
public static async Task Main(string[] args)
{
var webHost = CreateWebHostBuilder(args).Build();
await webHost.Services.GetRequiredService<IService>().InitAsync();
webHost.Run();
// await webHost.RunAsync();
}
Cela utilise async Main
pour activer l'utilisation de await
, construit le IWebHost
et utilise son IServiceProvider
pour résoudre et initialiser IService
. Le code montre également comment vous pouvez utiliser await
avec RunAsync
si vous préférez, maintenant que la méthode est async
.