2017-10-04 167 views
3

我使用ASP.NET 2.0的核心,我必須在Main方法類似這樣的配置代碼:ASP.NET核心配置reloadOnChange與IOptionsSnapshot仍然沒有響應

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 E設置爲true ,在我的控制,我使用IOptionsSnapshot

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

但是,當我修改我在appsettings.json的價值觀,我必須重新啓動我的應用程序每次或修改都沒有隻是通過刷新回升瀏覽器。我究竟做錯了什麼?我試圖用控制檯和IIS Express運行應用程序;我也試過IOptionsMonitor,同樣的事情。順便提一下,IOptionsMonitorIOptionsSnapshot之間有什麼區別?

+0

你如何註冊'AppSettings'選項? – poke

+0

我在Startup.cs中添加了像這樣的服務的AppSettings。配置(Configuration.GetSection(「AppSettings」)); –

回答

8

正如the documentation中提到的,只需啓用reloadOnChange然後注入IOptionsSnapshot<T>而不是IOptions<T>就足夠了。這需要您已經正確配置了該類型T。通常配置註冊將是這樣的:

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

然而,看着你的代碼越近,它似乎並不認爲你正在使用配置程序的新ASP.NET 2.0的核心方式。該配置現在是依賴項注入的一部分,因此您將使用ConfigureAppConfiguration將其設置爲WebHostBuilder的一部分。這可能例如是這樣的:

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>是一個單例服務,允許您在任何給定時間檢索當前配置值。所以對於需要獲取當前配置的單件服務來說,它尤其有用。此外,選件監視器還提供推送機制以通過配置源獲得配置更改的通知。這樣,您可以顯式處理配置更改。

選項快照旨在用於臨時或範圍的依賴關係,因此大多數情況下您都可以使用這些快照。只有在極少數情況下,當您使用需要使用單一服務,需要具有最新的配置時,您應該需要使用選項監視器。在這些情況下,請注意,僅從快照切換到顯示器是不夠的。通常,您將不得不以某種方式處理更改的配置(例如清理狀態,清除緩存等)。因此,您應該始終考慮是否實際需要的所有的可重新配置配置,或者只是重新啓動應用程序不是一個可行的選擇。

+0

謝謝你的回答!我更新了我的配置代碼,像我的配置代碼和我的控制器中的AppSettings一樣工作。然而,我有一箇中間件構造函數中的代碼仍然沒有找到變化,公共MyMiddleware(RequestDelegate接下來,IOptionsSnapshot 選項,ILoggerFactory loggerFactory),你知道中間件是否應該對控制器的配置變化做出反應嗎? –

+0

@fanray是的,中間件是不幸的是不同的事情。當應用程序運行並執行'Startup.Configure'方法時,中間件會設置*一次*。因此,當時所有的依賴關係都被解析,並且中間件實例保持爲共享實例。所以你不能在那裏注入選項。您將必須解決'Invoke'方法中的選項,然後,例如使用'context.RequestServices.GetRequiredService >()'。 – poke

+0

嗨@poke我知道它在我的中間件中使用var settings = context.RequestServices.GetService >()。Value;如果每次請求都進入該中間件,此GetService代碼是否會影響性能?最後,有沒有辦法在Startup的ConfigureServices方法中獲取AppSettings對象?謝謝! –