带有IOptionsSnapshot的ASP.NET核心配置reloadOnChange仍然没有响应

时间:2017-10-04 15:58:38

标签: asp.net-core configuration asp.net-core-mvc

我使用的是ASP.NET Core 2.0,我在Main方法中有这样的配置代码:

public static void Main(string[] args)
{
    var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
    var configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{environment ?? "Production"}.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables()
        .AddCommandLine(args)
        .Build();
}

我将reloadOnChang设置为true,在我的控制器中我使用IOptionsSnapshot

public HomeController(ILogger<HomeController> logger, IOptionsSnapshot<AppSettings> options)

但是当我修改appsettings.json中的值时,我必须每次都重新启动我的应用程序,或者只是通过刷新浏览器来获取更改。我究竟做错了什么?我尝试使用控制台和IIS Express运行应用程序;我也试过IOptionsMonitor,同样的事情。顺便问一下,IOptionsMonitorIOptionsSnapshot之间有什么区别?

1 个答案:

答案 0 :(得分:25)

正如the documentation中所述,只需启用reloadOnChange,然后注入IOptionsSnapshot<T>代替IOptions<T>即可。这要求您正确配置类型T。通常,配置注册将如下所示:

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

但是,仔细查看代码,您似乎没有使用新的ASP.NET Core 2.0配置程序的方式。配置现在是依赖注入的一部分,因此您将使用WebHostBuilder将其设置为ConfigureAppConfiguration的一部分。例如,这可能是这样的:

public static IWebHost BuildWebHost()
    => new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureAppConfiguration((builderContext, config) =>
        {
            IHostingEnvironment env = builderContext.HostingEnvironment;

            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
        })
        .UseStartup<Startup>()
        .Build();

如果您使用WebHost.CreateDefaultBuilder()使用默认构建器,则您甚至不需要这样做,因为配置会自动设置为激活reloadOnChange的配置。

IOptionsSnapshotIOptionsMonitor之间的区别在于IOptionsSnapshot只会在IOptionsSnapshot<T>时为您提供选项的快照物体正在建造中。

这就是使用与IOptions<T>完全相同的原因:您将它注入构造函数中,然后将options.Value存储在实例中以便稍后访问这些选项。那时,该对象是固定的,永远不会改变。只是将IOptionsSnapshot<T>注册为作用域依赖项而不是像IOptions<T>那样的单例依赖项,因此它有机会在每个请求上获取当前配置值,而不是仅仅一次。

IOptionsMonitor<T>是一个单例服务,允许您在任何给定时间检索当前配置值。因此,对于需要在需要时获取当前配置的单例服务尤其有用。此外,选项监视器还提供推送机制,以通过配置源通知配置更改。这样,您就可以显式处理配置更改。

选项快照旨在用于瞬态或作用域依赖关系,因此您可以在大多数情况下使用它们。只有在 使用 需要具有最新配置的单件服务的极少数情况下,您才需要使用选项监视器。在这些情况下,请注意仅从快照切换到监视器是不够的。通常,您必须以某种方式处理更改的配置(例如清理状态,清除缓存等)。因此,您应该始终考虑是否确实需要所有的可重新加载配置,或者只是重新启动应用程序不是一个可行的选择。