问题描述
.NET Core 从配置文件中懒惰地读取设置,将其反序列化为POCO,然后使用一行代码将POCO注册到内置DI容器中:
.NET Core allows to lazily read settings from configuration file, de-serialize it to a POCO and register that POCO in built-in DI container with one line of code:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration.GetSection("MySection"));
}
然后,任何消费者都可以解析 IOptions< MyOptions>
访问该POCO:
Then any consumer can resolve IOptions<MyOptions>
to access that POCO:
public HomeController(IOptions<MyOptions> optionsAccessor)
{
MyOptions options = optionsAccessor.Value;
}
这种方法有很多缺点:
-
Microsoft.Extensions.Options
包中不必要的依赖项:
Unnecessary dependency from
Microsoft.Extensions.Options
package:
模拟,测试和显式实例创建变得更加冗长。
Mocking, testing and explicit instance creation become a bit more verbose.
什么是没有 IOptions< T>
的最简单解决方案?
What is the easiest solution to resolve options without IOptions<T>
?
推荐答案
反序列化 configuration.Get< TOptions>
或 configuration.Bind
的选项,并在DI容器中将POCO明确注册为单例:
Deserialize options with configuration.Get<TOptions>
or configuration.Bind
call and register a POCO in DI container explicitly as singleton:
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>()
提示。
UPD: thanks to @NPNelson for .Get<TOptions>()
hint.
然后 IOptions< T>
解析不再
public HomeController(MyOptions options)
{
_options = options;
}
仅供参考:也可以从外部服务(数据库等)读取方式:
FYI: reading from an external service (database etc.) is also possible this way:
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>()));
}
备注:
- Singleton并不懒惰(总是在启动时实例化);
- 如果是单例注册,则在运行时会丢失任何更新选项的功能(.NET Core通过
reloadOnChange
选项设置本地支持运行时文件重新加载:.AddJsonFile( appsettings.json,false,reloadOnChange:true)
);
- Singleton is not lazy (it's always instantiated at startup);
- In case of singleton registration, any ability to update options at runtime is lost (.NET Core natively supports runtime file reloading with
reloadOnChange
option setup:.AddJsonFile("appsettings.json", false, reloadOnChange: true)
);
如果您确实需要重新加载文件,但仍然不想使用 IOptions
,请考虑临时解析。当然,按请求解决可能会导致性能显着下降。
If you really need the file reload and you still don't want to use IOptions
, consider a transient resolving. Of course, per-request resolving can lead to the significant perfomance decrease.
这篇关于在没有IOptions< T>的情况下从appsettings.json中读取和使用设置吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!