在我的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文件时,永远不会触发该事件。有人知道我可以更改些什么以使重装机制在我的方案中工作吗?
答案 0 :(得分:4)
您需要注入IOptionsSnapshot<AppSettings>
才能使重新加载正常工作。
很遗憾,您无法将IOptionsSnapshot
加载到Singleton服务中。 IOptionsSnapshot
是范围服务,因此您只能在范围或瞬态注册类中引用它。
但是,如果考虑一下,那是有道理的。更改设置时需要重新加载设置,因此,如果将它们注入到Singleton中,则该类将永远不会获得更新的设置,因为不会为Singleton再次调用构造函数。
答案 1 :(得分:2)
您可以做的是像在 AppSettingsWrapper 中一样在config类周围创建包装器类,然后注入IOptionsMonitor。然后保留您的设置类的私有属性。该包装器可以作为单例注入,并且IOptionsMonitor将跟踪您的更改。
react-dom
然后将包装器类注册为单例
public class AppSettingsWrapper
{
private AppSettings _settings;
public AppSettingsWrapper(IOptionsMonitor<AppSettings> settings)
{
_settings = settings.CurrentValue;
// Hook in on the OnChange event of the monitor
settings.OnChange(Listener);
}
private void Listener(AppSettings settings)
{
_settings = settings;
}
// Example getter
public string ExampleOtherApiUrl => _settings.ExampleOtherApiUrl;
}
答案 2 :(得分:0)
如果您想拥有一个单例IHostedService
,例如注册为单例,并且Execute
方法被计时器重复触发+您希望每个触发器上有一个新的IOptionsSnapshot
,您可以使用以下代码:
public MyHostedService (IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
private void ExecutedByTimer ()
{
using var scope = _serviceProvider.CreateScope();
var options = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<MyHostedServiceOptions>>().Value;
// Voila, options is an up-to-date snapshot
}