Startup.cs
に挿入された構成からGetSection
を呼び出そうとしました。値はnull
でしたが、具体的なセクション値へのindexer
はnon-null
値を返します。 GetSection
メソッドの背後にあるバグのように見えますか、それとも間違っていますか?
appsettings.json:
{"MyConfig":{"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"];
最初に、JSONファイルから取得可能な値を構築する内部コードであるJsonConfigurationProvider.cs
の 1.1.1 と 2.x の間に変更があるかどうかを確認しました。これや、最終的にthis.Configuration.GetSection("MyConfig");
によって呼び出される他のコードに変更はありませんでした。
値を取得する方法は、Configuration
が各構成プロバイダーでキーMyConfig
を逆順で検索することです。値が見つかるまでコードで定義されているとおり。あなたの例では、プロバイダー(json、環境変数、コマンドライン引数)はWebhost.CreateDefaultBuilder()
(こちらを参照) で提供されています。
JsonConfigurationFileParser.cs のコードを見ると、キーと値のDictionary<string, string>
が作成されますただし、プリミティブ値のみ。つまり、MyConfig
(このレベルではオブジェクト)のキーは保存されませんが、MyConfig:ConfigA
のキーがあり、配列値はMyConfig:ConfigA:0
、MyConfig:ConfigA:1
などのようになります。
最後に、Configuration.GetSection("MyConfig")
常に新しく構築されたものを返しますConfigurationSection
つまりnever null、最悪の場合はValue
property of null
になります。
したがって、IntellisenseでConfigurationSection
にカーソルを合わせてValue
プロパティを見ると、every構成プロバイダーが検索され、キーを持つものが見つからなかったことがどうなりますか返される文字列に変換されたプリミティブ値を持つ「MyConfig」の。
少なくとも以下を呼び出す必要があります。
services.Configure<MyConfigOptions>(configuration.GetSection("MyConfig"));
services.AddSingleton(cfg => cfg.GetService<IOptions<MyConfigOptions>>().Value);
アプリ全体にC#オブジェクトとして注入します。そうでない場合は、コロン["MyConfig:ConfigA"]
セパレーター構文またはvar mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];
を使用して個々の値を呼び出します。これは冗長ですが、プリミティブの取得にのみ使用されることを示しています。
C#オブジェクトにバインドして注入するために、次の拡張メソッドを作成しました。
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;
AspNetCore 2.0は、構成の点で1.xよりもはるかに単純であることがわかりました。
Startup(IConfiguration configuration)
コンストラクターにブレークポイントを配置すると、configuration
変数には約5つのプロバイダーが含まれることに気付くでしょう。
JsonConfigurationProvider
は、appsettings.jsonファイルで関心のあるプロバイダーですが、おそらくData
プロパティには_Count=0
_。これはおそらく、アプリケーションが_JsonConfigurationProvider.Source.FileProvider.Root
_(デフォルトではwwwroot)で指定されたディレクトリでappsettings.jsonファイルを探しているという事実によるものです。
次のように、.csprojファイルにMSBuildタスクを追加しました。
_<Copy SourceFiles="appsettings.json" DestinationFolder="wwwroot" />
_
そして、それは完璧に機能するように見えました。
これは明らかにローカル開発のみ中に役立ちます。ただし、最近の一般的なプラクティスでは、最初にファイルに構成を設定することはありません。特に、リポジトリの履歴の一部になるためです。代わりに、アプリをデプロイするとき、最近の2つの一般的なプラクティスは、環境変数を使用して値をオーバーライドするか、consulなどのキー/値ストアを使用することです。
さらに、services.Configure<>()
を使用する方法についての素晴らしい例がオンラインでたくさんありますが、_Startup.cs
_は既にDIを使用して_IConfiguration configuration
_に値を注入します。これは、IConfiguration
が.NETコアのIoCコンテナーに既に登録されていることを意味します。したがって、本質的には、アプリの他のクラスでIConfiguration
を次のように使用できることを意味します。
_public JobsRepository(IConfiguration configuration)
{
this.configA = configuration.GetSection("MyConfig:ConfigA").Value;
}
_