使用 configuration.Get<TOptions> 或 configuration.Bind 调用反序列化选项并将 DI 容器中的 POCO 显式注册为单例:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingletonFromFile<MyOptions>(Configuration.GetSection("MySection"));
}
//...
public static IServiceCollection AddSingletonFromFile<TOptions>(
this IServiceCollection services,
IConfiguration configuration)
where TOptions : class, new()
{
//POCO is created with actual values
TOptions options = configuration.Get<TOptions>();
services.AddSingleton(options);
return services;
}
UPD:感谢@NPNelson 提供.Get<TOptions>() 提示。
那么IOptions<T>就不再需要解析了,类依赖变得清晰了:
public HomeController(MyOptions options)
{
_options = options;
}
仅供参考:也可以通过这种方式从外部服务(数据库等)读取数据:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransientFromService<OptionsReader, MyOptions>(reader => reader.GetOptions());
}
//...
public static void AddTransientFromService<TReader, TOptions>(
this IServiceCollection services,
Func<TReader, TOptions> getOptions)
where TReader : class
where TOptions : class
{
services.AddTransient(provider => getOptions(provider.GetService<TReader>()));
}
备注:
- 单例不是惰性的(它总是在启动时实例化);
- 在单例注册的情况下,任何在运行时更新选项的能力都会丢失(.NET Core 原生支持使用
reloadOnChange 选项设置重新加载运行时文件:.AddJsonFile("appsettings.json", false, reloadOnChange: true));
如果您真的需要重新加载文件并且您仍然不想使用IOptions,请考虑临时解决。当然,按请求解析会导致性能显着下降。