每次在.NET核心1.1控制台应用程序中更改时,如何在运行时重新加载appsettings.json?

Rog*_*gne 3 runtime configuration-files .net-core

我试图重现Andrew Lock这篇伟大文章中描述的方法.但是,我无法在.NET核心1.1控制台应用程序中运行此功能.当appsettings.json文件进行修改和保存,这些变化都没有重新启动它反映在应用程序中.

涉及多个文件,所以我创建了我可以在github上出现的最小的例子.我还在github上的README.MD文件中提供了详细信息.

任何帮助解决这个问题将是非常感谢.请记住,我是.NET核心新手,而不是经验丰富的开发人员.这是我关于stackoverflow的第一个问题...在此先感谢!

Soc*_*ock 6

要理解的关键是范围.

ASP.NET Core中有三个范围 - transient,scoped和singleton.IOptionsSnapshot被配置为作用域服务.

在ASP.NET Core中,为每个请求启动一个范围,因此每个请求都会获得一个IOptionsSnapshot具有更新配置值的新实例.

在您提供的示例中,您正在创建一个IServiceProvider,并IMyService从顶级提供程序直接获取实例:

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);
}
Run Code Online (Sandbox Code Playgroud)

从本质上讲,对于服务提供商的每个请求,您总是使用相同的范围,因此您总是获得相同的实例IOptionsSnapshot.实际上,如果您从未创建新范围,那么您的所有范围服务都将成为单身人士!

解决此问题的方法是每次获取服务时创建一个新范围:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在执行诸如DbContext在ASP.NET Core应用程序(或控制台应用程序)中的请求上下文之外创建EF Core,这也很重要.始终在从服务提供商访问服务之前创建新范围!

PS我已经创建了一个拉取请求来修复你的样本:)