问题描述
我试图从 Startup.cs
中注入的配置调用 GetSection
.值是 null
,而 indexer
到具体的部分值返回 non-null
值.在我看来 GetSection
方法背后的错误还是我错了?
I was trying to call GetSection
from injected configuration in the Startup.cs
.The Value was null
, while indexer
to a concrete section value returns non-null
value. It seems to me a bug behind the GetSection
method or I am wrong with it?
appsettings.json:
{我的配置":{"ConfigA": "valueA","ConfigB": "valueB" } }
Program.cs:
public static void Main(string[] args)
{
var host = BuildWebHost(args);
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var mySection = this.Configuration.GetSection("MyConfig");
var myVal = this.Configuration["MyConfig:ConfigA"];
推荐答案
我首先检查了 1.1.1 和 2.x 的JsonConfigurationProvider.cs
,内部代码最终从您的 JSON 文件构造可检索的值.此代码或最终由您的 this.Configuration.GetSection("MyConfig");
调用的任何其他代码没有任何更改.
I first checked to see if there were any changes between 1.1.1 and 2.x of JsonConfigurationProvider.cs
, the internal code that ultimately constructs retrievable values from your JSON file. There were no changes to this or any of the other code that ultimately gets called by your this.Configuration.GetSection("MyConfig");
.
检索值的工作方式是 Configuration
将在每个配置提供程序中查找您的密钥 MyConfig
按代码中定义的相反顺序直到找到一个值.在您的示例中,提供程序(json、环境变量、命令行参数)在 Webhost.CreateDefaultBuilder()
(参见此处).
The way retrieving values works is that the Configuration
will look for your key MyConfig
in each config provider in reverse order as defined in code until a value is found. In your example, providers (json, envionment variables, command line args) are provided within Webhost.CreateDefaultBuilder()
(see here).
查看JsonConfigurationFileParser.cs,它为键和值构建了一个Dictionary
,但仅用于原始值.也就是说,没有为 MyConfig
存储键(在这个级别它是一个对象),但是 MyConfig:ConfigA
会有一个键,数组值看起来像MyConfig:ConfigA:0
、MyConfig:ConfigA:1
等
Looking at the code for JsonConfigurationFileParser.cs, it builds a Dictionary<string, string>
for keys and values, but only for primitive values. That is, no key is stored for MyConfig
(at this level it is an object), but there will be a key for MyConfig:ConfigA
, and array values would look like MyConfig:ConfigA:0
, MyConfig:ConfigA:1
, etc.
最后,你会发现Configuration.GetSection("MyConfig")
总是返回一个新构造的 ConfigurationSection
,它从不为空,最坏的情况是 Value
property 为 null
.
Lastly, you will find that Configuration.GetSection("MyConfig")
always returns you a newly constructed ConfigurationSection
that is never null, and at the very worst will have a Value
property of null
.
因此,当您使用 Intellisense 将鼠标悬停在 ConfigurationSection
上并查看 Value
属性时会发生什么情况是 每个 配置提供程序都已被搜索并且没有发现具有MyConfig"键,原始值转换为字符串以返回.
So what happens when you hover over a ConfigurationSection
with Intellisense and look at the Value
property is that every config provider had been searched and none was found to have a key of "MyConfig" with a primitive value converted to string to return.
您至少需要致电:
services.Configure<MyConfigOptions>(configuration.GetSection("MyConfig"));
services.AddSingleton(cfg => cfg.GetService<IOptions<MyConfigOptions>>().Value);
将其作为 C# 对象注入到整个应用程序中.否则,使用冒号 ["MyConfig:ConfigA"]
分隔符语法或使用 var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];
调用各个值code>,这是多余的,但说明它仅用于检索原语.
to have it injected throughout your app as a C# object. Otherwise, call individual values with the colon ["MyConfig:ConfigA"]
separator syntax or with var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];
, which is redundant but illustrates it is only used to retrieve primitives.
为了绑定到 C# 对象并注入它们,我创建了以下扩展方法:
To bind to C# objects and inject them, I created the following extension method:
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddConfigOptions<TOptions>(this IServiceCollection services,
IConfiguration configuration, string section) where TOptions : class, new()
{
services.Configure<TOptions>(configuration.GetSection(section));
services.AddSingleton(cfg => cfg.GetService<IOptions<TOptions>>().Value);
return services;
}
}
可以这样调用:
public class Startup
{
public Startup(IConfiguration configuration) => Configuration = configuration;
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddConfigOptions<EmailOptions>(Configuration, "Email")
并像这样注入:
public class EmailSender : IEmailSender
{
private EmailOptions _emailOptions;
public EmailSender(EmailOptions options) => _emailOptions = options;
这篇关于ASP.net Core 2.0 中的 appsettings.json 预览配置 GetSection null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!