Maison > Article > développement back-end > Tutoriel de configuration ASP.NET Core - lecture des informations de configuration
En ce qui concerne le mot « configuration », je pense que la plupart des développeurs .NET penseront immédiatement à deux fichiers spéciaux, à savoir app.config et web.config, que nous connaissons tous trop bien depuis de nombreuses années. à définir des informations de configuration structurées dans ces deux fichiers. En ce qui concerne .NET Core, de nombreuses choses que nous tenons pour acquises ont changé, notamment la manière de définir les configurations. En général, le nouveau système de configuration est plus léger et offre une meilleure évolutivité. Sa principale caractéristique est qu'il prend en charge diverses sources de données. Nous pouvons utiliser des variables de mémoire comme source de données pour la configuration, ou les configurer et les définir directement dans des fichiers persistants ou même des bases de données.
Étant donné que de nombreuses personnes n'ont jamais été exposées à ce système de configuration nouvellement conçu, afin d'en donner à chacun une compréhension sensorielle, nous allons d'abord l'expérimenter du point de vue de la programmation. L'API de configuration implique trois objets, à savoir Configuration, ConfigurationBuilder et ConfigurationProvider. Le modèle de configuration possède des interfaces correspondantes pour les représenter. La relation entre ces trois objets est très claire. L'objet Configuration transporte les informations de configuration utilisées dans le processus de programmation, et le ConfigurationProvider est le fournisseur de la source de données d'origine des informations de configuration. La communication entre les deux est complétée par le ConfigurationBuilder. qui utilise le ConfigurationProvider pour extraire les données source est converti en un objet Configuration.
1. Lire la configuration sous forme de paires clé-valeur
Bien que dans la plupart des cas les informations de configuration aient une relation hiérarchique structurée dans leur ensemble, les éléments de configuration « atomiques » sont incorporés dans le forme la plus simple de « paires clé-valeur », et les clés et les valeurs sont toutes deux des chaînes. Ensuite, nous utiliserons un exemple simple pour montrer comment lire la configuration sous forme de paires clé-valeur. Nous créons une application console pour ASP.NET Core et ajoutons une dépendance sur le package NuGet « Microsoft.Extensions.Configuration » dans project.json comme suit. Le modèle de configuration est implémenté dans ce package.
{ ... "dependencies": { "Microsoft.Extensions.Configuration": "1.0.0-rc1-final" }, }
Supposons que notre application doive définir le format d'affichage de la date/heure via la configuration. À cette fin, nous définissons la classe DateTimeFormatSettings suivante. Ses quatre propriétés incarnent DateTime Quatre formats d'affichage. pour les objets (date/heure longue et date/heure courte respectivement).
public class DateTimeFormatSettings { public string LongDatePattern { get; set; } public string LongTimePattern { get; set; } public string ShortDatePattern { get; set; } public string ShortTimePattern { get; set; } //其他成员 }
Nous souhaitons contrôler le format d'affichage de la date/heure reflété par les quatre propriétés de DateTimeFormatSettings via la configuration, nous définissons donc un constructeur pour cela. Comme le montre l'extrait de code suivant, le constructeur possède un paramètre de type interface IConfiguration, qui transporte formellement l'objet Configuration des informations de configuration associées. Nous appelons l'index de l'objet Configuration et spécifions la clé de l'élément de configuration correspondant pour obtenir sa valeur.
public class DateTimeFormatSettings { //其他成员 public DateTimeFormatSettings (IConfiguration configuration) { this.LongDatePattern = configuration["LongDatePattern"]; this.LongTimePattern = configuration["LongTimePattern"]; this.ShortDatePattern = configuration["ShortDatePattern"]; this.ShortTimePattern = configuration["ShortTimePattern"]; } }
Pour créer un objet DateTimeFormatSettings qui reflète la configuration actuelle, nous devons obtenir l'objet Configuration qui contient les informations de configuration pertinentes. Comme nous l'avons dit ci-dessus, l'objet Configuration est créé par ConfigurationBuilder et les informations de configuration d'origine sont lues via le ConfigurationProvider correspondant. La méthode de programmation correcte pour créer un objet Configuration consiste donc à créer d'abord un objet ConfigurationBuilder, puis à l'ajouter un ou plusieurs ConfigurationProvider. objets, et enfin utilisez ConfigurationBuilder pour créer l'objet Configuration dont nous avons besoin.
Selon le modèle de programmation ci-dessus, nous avons écrit le programme suivant dans une application console. Nous avons créé un objet de type ConfigurationBuilder et le ConfigurationProvider ajouté en appelant sa méthode Add est un objet de type MemoryConfigurationProvider. Comme son nom l'indique, MemoryConfigurationProvider utilise des objets en mémoire pour fournir des informations de configuration d'origine. Plus précisément, ces informations de configuration d'origine sont stockées dans une collection dont le type d'élément est KeyValuePair708d620c35cc3f2d1dd0b997d136c07a. Nous appelons enfin la méthode Build de ConfigurationBuilder pour obtenir la Configuration requise pour créer un objet DateTimeFormatSettings.
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); } }
Afin de vérifier la relation entre l'objet DateTimeFormatSettings créé en fonction de la configuration et les données de configuration d'origine, nous affichons ses quatre propriétés sur la console. Lorsque ce programme est exécuté, il produira la sortie affichée ci-dessous sur la console. On peut voir qu'il s'agit d'un véritable reflet de la configuration que nous avons fournie.
LongDatePattern : jjj, MMMM j, aaaa
LongTimePattern : h:mm:ss tt
ShortDatePattern : M/d/yyyy
ShortTimePattern : h:mm tt
2. Lire Prenez une configuration structurée
La plupart des configurations impliquées dans des projets réels ont une structure hiérarchique structurée, donc l'objet Configuration dans le modèle de configuration a également une telle structure. Une configuration structurée possède une hiérarchie arborescente et un objet Configuration représente un nœud qui constitue l'arborescence de configuration. Cette arborescence de configuration peut être représentée par l'objet Configuration en tant que nœud racine. Les éléments de configuration atomiques incorporés sous forme de paires clé-valeur existent généralement dans les objets de configuration en tant que nœuds feuilles. La configuration des nœuds non-feuilles contient un ensemble de nœuds enfants, et chaque nœud enfant est également un objet de 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对象来提供原始的配置信息。由于承载原始配置信息的是一个元素类型为KeyValuePair708d620c35cc3f2d1dd0b997d136c07a的集合,所以原始配置在物理存储上并不具有树形化的层次结构,那么它如何能够最终提供一个结构化的Configuration对象呢?其实很简单,虽然MemoryConfigurationProvider对象只能将配置信息存储为简单的“数据字典”,但是如果将Configuration对象在配置树中体现的路径作为Key,这个数据字典在逻辑上实际上就具有了一棵树的结构。实际上MemoryConfigurationProvider就是这么做的,这体现在我们如下所示的程序之中。
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方法得到一个类型为IOptionsb7508df415eea39e792050f586bf7677的对象,后者的Value属性返回的就是绑定了相关配置的FormatSettings对象。
以上就是本文的全部内容,希望对大家的学习有所帮助。
更多asp.net core实现文件上传功能相关文章请关注PHP中文网!