I attempted to reproduce the method described in this great article by Andrew Lock. However, I am unable to get this running in a .NET core 1.1 console application. When the appsettings.json
file is changed and saved, the changes are not reflected in the application without restarting it.
There are multiple files involved, so I created the smallest example I could come up on github. I also provided details in the README.MD file on github.
Any help in resolving this would be most appreciated. Please keep in mind I am new to .NET core, and not an experienced developer. And this is my first question on stackoverflow... Thanks in advance!
The key thing to understand is scope.
There are three scopes in ASP.NET Core - transient, scoped, and singleton. IOptionsSnapshot
is configured as a scoped service.
In ASP.NET Core, a scope is started for every request, so every request, you would get a new instance of IOptionsSnapshot
, with updated configuration values.
In the example you provided, you are creating an IServiceProvider
, and are fetching an instance of IMyService
directly from the top level provider:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
var service = serviceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
Essentially, you're always using the same scope for every request to the service provider, so you're always getting the same instance of IOptionsSnapshot
. Effectively, if you never create a new scope, all of your scoped services become singletons!
The way to fix this is to create a new scope each time you fetch the service:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
using (var scope = serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
}
This also becomes important if you're doing things like creating an EF Core DbContext
outside the context of a request in ASP.NET Core app (or in a console app). Always create a new scope before accessing services from the service provider!
P.S. I've created a pull request to fix your sample :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With