I have a service that asynchronously reads some content from a file in a method called InitAsync
public class MyService : IService {
private readonly IDependency injectedDependency;
public MyService(IDependency injectedDependency) {
this.injectedDependency = injectedDependency;
}
public async Task InitAsync() {
// async loading from file.
}
}
Now this service is injected into my controller.
public class MyController : Controller {
private readonly IService service;
public MyController(IService service) {
this.service = service;
}
}
Now I want a singleton instance of MyService. And I want to call InitAsync in startup.
public class Startup {
public void ConfigureServices(IServiceCollection services) {
......
services.AddSingleton<IService, MyService>();
var serviceProvider = services.BuildServiceProvider();
// perform async init.
serviceProvider.GetRequiredService<IService>().InitAsync();
}
}
What is happening is at the time of startup, an instance of MyService is created and InitAsync()
is called on it. Then when I called the controller class, another instance of MyService is created which is then reused for consequent calls.
What I need is to initialize only 1 instance, called InitAsync() on it in startup and have it be reused by controllers as well.
When you call
BuildServiceProvider()
, you create a separate instance ofIServiceProvider
, which creates its own singleton instance ofIService
. TheIServiceProvider
that gets used when resolving theIService
that's provided forMyController
is different to the one you created yourself and so theIService
itself is also different (and uninitialised).Rather than attempting to resolve and initialise
IService
inside ofStartup.ConfigureServices
, you can do so inProgram.Main
. This allows for two things:IService
for initialisation and later use.await
ing the call toInitAsync
, which is currently fire-and-forget in the approach you've shown.Here's an example of how
Program.Main
might look:This uses
async Main
to enable use ofawait
, builds theIWebHost
and uses itsIServiceProvider
to resolve and initialiseIService
. The code also shows how you can useawait
withRunAsync
if you prefer, now that the method isasync
.