在我的ASP.NET Core应用程序中,我将appsettings.json绑定到强类型的AppSettings类。
public Startup(IHostingEnvironment environment)
{
var builder = new ConfigurationBuilder()
.SetBasePath(environment.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration);
//...
}
在单例类中,我将这个AppSettings类包装如下:
public class AppSettingsWrapper : IAppSettingsWrapper
{
private readonly IOptions<AppSettings> _options;
public AppSettingsAdapter(IOptions<AppSettings> options)
{
_options = options ?? throw new ArgumentNullException("Options cannot be null");
}
public SomeObject SomeConvenienceGetter()
{
//...
}
}
现在,如果json文件发生更改,我正在努力重新加载AppSettings。我在某处读到IOptionsMonitor类可以检测到更改,但是在我的情况下它不起作用。
为了测试目的,我尝试像这样调用OnChange事件:
public void Configure(IApplicationBuilder applicationBuilder, IOptionsMonitor<AppSettings> optionsMonitor)
{
applicationBuilder.UseStaticFiles();
applicationBuilder.UseMvc();
optionsMonitor.OnChange<AppSettings>(vals =>
{
System.Diagnostics.Debug.WriteLine(vals);
});
}
当我更改json文件时,永远不会触发该事件。有人知道我可以进行哪些更改以使重装机制在我的方案中工作吗?
你需要注入IOptionsSnapshot<AppSettings>
以使重新加载工作。
很遗憾,你无法将加载IOptionsSnapshot
到Singleton服务中。IOptionsSnapshot
是范围服务,因此你只能在范围或瞬态注册类中引用它。
但是,如果考虑一下,那是有道理的。更改设置时需要重新加载设置,因此,如果将它们注入到Singleton中,则该类将永远不会获得更新的设置,因为不会为Singleton再次调用构造函数。
我以为我可以在“ OnChange”事件中将AppSettingsWrapper与新的AppSettings重新绑定。不幸的是,我不得不更改包装器类的生命周期,因为除了罕见的重载之外,它永远都不会改变。
除非您有真正令人信服的理由将其保持为单例,例如实时性能,
Scoped
否则切换到服务应该给您想要的东西而不会带来太多损失,毕竟您仍然在注入相同的类,只有注册已更改。没有什么可以阻止您使用IServiceProvider.CreateScope在单例内部创建范围的。
如果在配置源(在本例中为文件)更改时不ping通更改句柄,则reloadOnChange的目的是什么?