「構成」という言葉に関して、ほとんどの .NET 開発者は、私たちが長年にわたってよく知っている app.config と web.config という 2 つの特別なファイルをすぐに思い浮かべると思います。これら 2 つのファイルで構造化された構成情報を定義するのが一般的です。 .NET Core に関しては、構成の定義方法を含め、私たちが当然と思っている多くのことが変更されています。一般に、新しい構成システムはより軽量で、拡張性が優れています。その最大の特徴は、多様なデータ ソースをサポートしていることです。メモリ変数を構成用のデータ ソースとして使用したり、永続ファイルやデータベースで直接構成および定義したりできます。
多くの人がこの新しく設計された構成システムに触れたことがないため、誰もがそれを感覚的に理解できるように、まずプログラミングの観点からそれを初めて体験します。構成用の API には、Configuration、ConfigurationBuilder、ConfigurationProvider という 3 つのオブジェクトが含まれます。構成モデルには、それらを表す対応するインターフェイスがあります。これら 3 つのオブジェクト間の関係は非常に明確です。Configuration オブジェクトはプログラミング プロセスで使用される構成情報を保持し、ConfigurationProvider は構成情報の元のデータ ソースのプロバイダーです。この 2 つの間の通信は ConfigurationBuilder によって行われます。 ConfigurationProvider を使用してソース データを抽出するものは、Configuration オブジェクトに変換されます。
1. キーと値のペアの形式で設定を読み取ります
ほとんどの場合、設定情報は全体として構造化された階層関係を持ちますが、「アトミック」な設定項目は最も単純な「キー」と「値」のペアで表されます。次に、簡単な例を使用して、キーと値のペアの形式で構成を読み取る方法を示します。次のように、ASP.NET Core のコンソール アプリケーションを作成し、project.json 内の NuGet パッケージ「Microsoft.Extensions.Configuration」への依存関係を追加します。構成モデルはこのパッケージに実装されています。
{ ... "dependencies": { "Microsoft.Extensions.Configuration": "1.0.0-rc1-final" }, }
この目的のために、アプリケーションが構成を通じて日付/時刻の表示形式を設定する必要があるとします。そのために、その 4 つのプロパティは、DateTime オブジェクトの 4 つの表示形式 (長い日付/時刻) を反映します。短い日付/時間)。
public class DateTimeFormatSettings { public string LongDatePattern { get; set; } public string LongTimePattern { get; set; } public string ShortDatePattern { get; set; } public string ShortTimePattern { get; set; } //其他成员 }
DateTimeFormatSettings の 4 つのプロパティによって反映される日付/時刻の表示形式を構成によって制御したいので、そのコンストラクターを定義します。次のコード スニペットに示すように、コンストラクターには IConfiguration インターフェイス型のパラメーターがあり、これは関連する構成情報の Configuration オブジェクトを形式的に保持します。 Configuration オブジェクトのインデックスを呼び出し、対応する構成アイテムの Key を指定して、その値を取得します。
public class DateTimeFormatSettings { //其他成员 public DateTimeFormatSettings (IConfiguration configuration) { this.LongDatePattern = configuration["LongDatePattern"]; this.LongTimePattern = configuration["LongTimePattern"]; this.ShortDatePattern = configuration["ShortDatePattern"]; this.ShortTimePattern = configuration["ShortTimePattern"]; } }
現在の構成を反映する DateTimeFormatSettings オブジェクトを作成するには、関連する構成情報を保持する Configuration オブジェクトを取得する必要があります。上で述べたように、Configuration オブジェクトは ConfigurationBuilder によって作成され、元の構成情報は対応する ConfigurationProvider を通じて読み取られます。そのため、Configuration オブジェクトを作成する正しいプログラミング方法は、最初に ConfigurationBuilder オブジェクトを作成し、次にそれを 1 つ以上の ConfigurationProvider に追加することです。オブジェクトを作成し、最後に ConfigurationBuilder を使用して必要な Configuration オブジェクトを作成します。
上記のプログラミング モデルに従って、コンソール アプリケーションで次のプログラムを作成しました。 ConfigurationBuilder 型のオブジェクトを作成しました。Add メソッドを呼び出して追加された ConfigurationProvider は、MemoryConfigurationProvider 型のオブジェクトです。名前が示すように、MemoryConfigurationProvider はメモリ内のオブジェクトを使用して元の構成情報を提供します。具体的には、これらの元の構成情報は、要素タイプが KeyValuePair
public class Program { public static void Main(string[] args) { Dictionary<string, string> source = new Dictionary<string, string> { ["LongDatePattern"] = "dddd, MMMM d, yyyy", ["LongTimePattern"] = "h:mm:ss tt", ["ShortDatePattern"] = "M/d/yyyy", ["ShortTimePattern"] = "h:mm tt" }; IConfiguration configuration = new ConfigurationBuilder() .Add(new MemoryConfigurationProvider(source)) .Build(); DateTimeFormatSettings settings = new DateTimeFormatSettings(configuration); Console.WriteLine("{0,-16}: {1}", "LongDatePattern", settings.LongDatePattern); Console.WriteLine("{0,-16}: {1}", "LongTimePattern", settings.LongTimePattern); Console.WriteLine("{0,-16}: {1}", "ShortDatePattern", settings.ShortDatePattern); Console.WriteLine("{0,-16}: {1}", "ShortTimePattern", settings.ShortTimePattern); } }
設定に従って作成された DateTimeFormatSettings オブジェクトと設定元データの関係を確認するために、その 4 つのプロパティをコンソールに出力します。このプログラムを実行すると、コンソールに次のような出力が生成されます。これは、提供した構成を正確に反映していることがわかります。
LongDatePattern: dddd, MMMM d, yyyy
LongTimePattern: h:mm:ss tt
ShortDatePattern: M/d/yyyy
ShortTimePattern: h:mm tt
2. 構造化された構成を読み取る
実際のプロジェクトに関係する構成 ほとんどは構造化された構成を持っていますしたがって、構成モデル内の Configuration オブジェクトもそのような構造を持ちます。構造化された構成にはツリー階層があり、Configuration オブジェクトは構成ツリーを構成するノードを表します。この構成ツリーは、Configuration オブジェクトをルート ノードとして表すことができます。キーと値のペアとして具体化されたアトミック構成アイテムは、通常、構成オブジェクト内にリーフ ノードとして存在し、非リーフ ノードの構成には一連の子ノードが含まれており、各子ノードも構成オブジェクトです。
接下来我们同样以实例的方式来演示如何定义并读取具有层次化结构的配置。我们依然沿用上一节的应用场景,现在我们不仅仅需要设置日期/时间的格式,还需要设置其他数据类型的格式,比如表示货币的Decimal类型。为此我们定义了如下一个CurrencyDecimalFormatSettings类,它的属性Digits和Symbol分别表示小数位数和货币符号,一个CurrencyDecimalFormatSettings对象依然是利用一个表示配置的Configuration对象来创建的。
{ public int Digits { get; set; } public string Symbol { get; set; } public CurrencyDecimalFormatSettings(IConfiguration configuration) { this.Digits = int.Parse(configuration["Digits"]); this.Symbol = configuration["Symbol"]; } }
我们定义了另一个名为FormatSettings的类型来表示针对不同数据类型的格式设置。如下面的代码片段所示,它的两个属性DateTime和CurrencyDecimal分别表示针对日期/时间和货币数字的格式设置。FormatSettings依然具有一个参数类型为IConfiguration接口的构造函数,它的两个属性均在此构造函数中被初始化。值得注意的是初始化这两个属性采用的是当前Configuration的“子配置节”,通过指定配置节名称调用GetSection方法获得。
public class FormatSettings { public DateTimeFormatSettings DateTime { get; set; } public CurrencyDecimalFormatSettings CurrencyDecimal { get; set; } public FormatSettings(IConfiguration configuration) { this.DateTime = new DateTimeFormatSettings(configuration.GetSection("DateTime")); this.CurrencyDecimal = new CurrencyDecimalFormatSettings(configuration.GetSection("CurrencyDecimal")); } }
在我们上面演示的实例中,我们通过以一个MemoryConfigurationProvider对象来提供原始的配置信息。由于承载原始配置信息的是一个元素类型为KeyValuePair
class Program { static void Main(string[] args) { Dictionary<string, string> source = new Dictionary<string, string> { ["Format:DateTime:LongDatePattern"] = "dddd, MMMM d, yyyy", ["Format:DateTime:LongTimePattern"] = "h:mm:ss tt", ["Format:DateTime:ShortDatePattern"] = "M/d/yyyy", ["Format:DateTime:ShortTimePattern"] = "h:mm tt", ["Format:CurrencyDecimal:Digits"] = "2", ["Format:CurrencyDecimal:Symbol"] = "$", }; IConfiguration configuration = new ConfigurationBuilder() .Add(new MemoryConfigurationProvider(source)) .Build(); FormatSettings settings = new FormatSettings(configuration.GetSection("Format")); Console.WriteLine("DateTime:"); Console.WriteLine("\t{0,-16}: {1}", "LongDatePattern", settings.DateTime.LongDatePattern); Console.WriteLine("\t{0,-16}: {1}", "LongTimePattern", settings.DateTime.LongTimePattern); Console.WriteLine("\t{0,-16}: {1}", "ShortDatePattern", settings.DateTime.ShortDatePattern); Console.WriteLine("\t{0,-16}: {1}\n", "ShortTimePattern", settings.DateTime.ShortTimePattern); Console.WriteLine("CurrencyDecimal:"); Console.WriteLine("\t{0,-16}: {1}", "Digits", settings.CurrencyDecimal.Digits); Console.WriteLine("\t{0,-16}: {1}", "Symbol", settings.CurrencyDecimal.Symbol); } }
如上面的代码片段所示,创建MemoryConfigurationProvider对象采用的字典对象包含6个基本的配置项,为了让它们在逻辑上具有一个树形化层次结构,所以的Key实际上体现了每个配置项所在配置节在配置树中的路径,路径采用冒号(“:”)进行分割。改程序执行之后会在控制台上呈现如下所示的输出结果。
DateTime: LongDatePattern : dddd, MMMM d, yyyy LongTimePattern : h:mm:ss tt ShortDatePattern: M/d/yyyy ShortTimePattern: h:mm tt CurrencyDecimal: Digits : 2 Symbol : $
三、将结构化配置直接绑定为对象
在真正的项目开发过程中,我们都不会直接使用直接读取的配置,而都倾向于像我们演示的两个实例一样通过创建相应的类型(比如DateTimeFormatSettings、CurrencyDecimalSettings和FormatSettings)来定义一组相关的配置选项(Option),我们将定义配置选项(Option)的这些类型称为Option类型。在上面演示的实例中,为了创建这些封装配置的对象,我们都是采用手工读取配置的形式,如果定义的配置项太多的话,逐条读取配置项其实是一项非常繁琐的工作。
对于一个对象来说,如果我们将它的属性视为它的子节点,一个对象同样具有类似于Configuration对象的树形层次化结构。如果我们根据某个Option类型的结构来定义配置,或者反过来根据配置的结构来定义这个Option类型,那么Option类型的属性成员将与某个配置节具有一一对应的关系,那么原则上我们可以自动将配置信息绑定为一个具体的Option对象。
ASP.NET Core针对配置的Option模型(OptionModel)帮助我们实现了从配置到Option对象之间的绑定,接下来我们就对此做一个简单的演示。Option模型实现在“Microsoft.Extensions.OptionModel”这个NuGet包中,除此之外,我们需要采用依赖注入的方式来使用Option模型,所以我们需要按照如下的方式为应用添加针对相应的依赖。
{ ... "dependencies": { "Microsoft.Extensions.OptionsModel" : "1.0.0-rc1-final", "Microsoft.Extensions.DependencyInjection" : "1.0.0-rc1-final" }, }
借助于Option模型的自动绑定机制,我们无需再手工地读取配置信息,所以我们将FormatSettings、DateTimeFormatSettings和CurrencyDecimalSettings的构造函数删除,只保留其属性成员。在作为程序入口的Main方法中,我们采用如下的方式创建这个表示格式设置的FormatSettings对象。
class Program { static void Main(string[] args) { Dictionary<string, string> source = new Dictionary<string, string> { ["Format:DateTime:LongDatePattern"] = "dddd, MMMM d, yyyy", ["Format:DateTime:LongTimePattern"] = "h:mm:ss tt", ["Format:DateTime:ShortDatePattern"] = "M/d/yyyy", ["Format:DateTime:ShortTimePattern"] = "h:mm tt", ["Format:CurrencyDecimal:Digits"] = "2", ["Format:CurrencyDecimal:Symbol"] = "$", }; IConfiguration configuration = new ConfigurationBuilder() .Add(new MemoryConfigurationProvider(source)) .Build() .GetSection("Format")); IOptions<FormatSettings> optionsAccessor = new ServiceCollection() .AddOptions() .Configure<FormatSettings>(configuration) .BuildServiceProvider() .GetService<IOptions<FormatSettings>>(); FormatSettings settings = optionsAccessor.Value; Console.WriteLine("DateTime:"); Console.WriteLine("\t{0,-16}: {1}", "LongDatePattern",settings.DateTime.LongDatePattern); Console.WriteLine("\t{0,-16}: {1}", "LongTimePattern",settings.DateTime.LongTimePattern); Console.WriteLine("\t{0,-16}: {1}", "ShortDatePattern",settings.DateTime.ShortDatePattern); Console.WriteLine("\t{0,-16}: {1}\n", "ShortTimePattern",settings.DateTime.ShortTimePattern); Console.WriteLine("CurrencyDecimal:"); Console.WriteLine("\t{0,-16}: {1}", "Digits",settings.CurrencyDecimal.Digits); Console.WriteLine("\t{0,-16}: {1}", "Symbol",settings.CurrencyDecimal.Symbol); } }
如上面的代码片段所示,我们创建一个ServiceCollection对象并调用扩展方法AddOptions注册于针对Option模型的服务。接下来我们调用Configure方法将FormatSettings这个Option类型与对应的Configuration对象进行映射。我们最后利用这个ServiceCollection对象生成一个ServiceProvider,并调用其GetService方法得到一个类型为IOptions
以上就是本文的全部内容,希望对大家的学习有所帮助。
更多asp.net core实现文件上传功能相关文章请关注PHP中文网!