Heim  >  Artikel  >  Backend-Entwicklung  >  Tutorial zur ASP.NET Core-Konfiguration – Lesen von Konfigurationsinformationen

Tutorial zur ASP.NET Core-Konfiguration – Lesen von Konfigurationsinformationen

高洛峰
高洛峰Original
2017-02-07 11:46:491282Durchsuche

Wenn es um das Wort „Konfiguration“ geht, denken die meisten .NET-Entwickler wahrscheinlich sofort an zwei spezielle Dateien, nämlich app.config und web.config, mit denen wir seit vielen Jahren nur allzu vertraut sind zum Definieren strukturierter Konfigurationsinformationen in diesen beiden Dateien. Wenn es um .NET Core geht, haben sich viele Dinge geändert, die wir für selbstverständlich halten, einschließlich der Art und Weise, Konfigurationen zu definieren. Im Allgemeinen ist das neue Konfigurationssystem schlanker und skalierbarer. Sein größtes Merkmal ist, dass es verschiedene Datenquellen unterstützt. Wir können Speichervariablen als Datenquelle für die Konfiguration verwenden oder sie direkt in persistenten Dateien oder sogar Datenbanken konfigurieren und definieren.

Da viele Menschen noch nie mit diesem neu gestalteten Konfigurationssystem in Berührung gekommen sind, werden wir es zunächst aus der Programmierperspektive erleben, um jedem ein sinnliches Verständnis dafür zu vermitteln. Die API für die Konfiguration umfasst drei Objekte: Configuration, ConfigurationBuilder und ConfigurationProvider. Das Konfigurationsmodell verfügt über entsprechende Schnittstellen, um sie darzustellen. Die Beziehung zwischen diesen drei Objekten ist sehr klar. Das Konfigurationsobjekt trägt die im Programmierprozess verwendeten Konfigurationsinformationen, und der ConfigurationProvider ist der Anbieter der ursprünglichen Datenquelle der Konfigurationsinformationen. Die Kommunikation zwischen den beiden wird durch den ConfigurationBuilder abgeschlossen. das den ConfigurationProvider zum Extrahieren von Quelldaten verwendet, wird in ein Konfigurationsobjekt konvertiert.

1. Lesen Sie die Konfiguration in Form von Schlüssel-Wert-Paaren.
Obwohl die Konfigurationsinformationen in den meisten Fällen als Ganzes eine strukturierte hierarchische Beziehung aufweisen, sind die „atomaren“ Konfigurationselemente darin enthalten Die einfachste Form von „Schlüssel-Wert-Paaren“, und sowohl Schlüssel als auch Werte sind Zeichenfolgen. Als Nächstes zeigen wir anhand eines einfachen Beispiels, wie die Konfiguration in Form von Schlüssel-Wert-Paaren gelesen wird. Wir erstellen eine Konsolenanwendung für ASP.NET Core und fügen die Abhängigkeit vom NuGet-Paket „Microsoft.Extensions.Configuration“ in project.json wie folgt hinzu. Das Konfigurationsmodell wird in diesem Paket implementiert.

{
  ...
   "dependencies": {
   "Microsoft.Extensions.Configuration": "1.0.0-rc1-final"
  },
 }

Angenommen, unsere Anwendung muss das Datums-/Uhrzeitanzeigeformat durch Konfiguration festlegen. Zu diesem Zweck definieren wir die folgende DateTimeFormatSettings-Klasse. Ihre vier Eigenschaften verkörpern DateTime Four-Anzeigeformate für Objekte (langes Datum/Uhrzeit bzw. kurzes Datum/Uhrzeit).

public class DateTimeFormatSettings
 {
    public string LongDatePattern { get; set; }
    public string LongTimePattern { get; set; }
    public string ShortDatePattern { get; set; }
   public string ShortTimePattern { get; set; }
   //其他成员
 }

Wir hoffen, das Datums-/Uhrzeitanzeigeformat, das durch die vier Eigenschaften von DateTimeFormatSettings widergespiegelt wird, durch Konfiguration steuern zu können, also definieren wir einen Konstruktor dafür. Wie im folgenden Codeausschnitt gezeigt, verfügt der Konstruktor über einen Parameter vom Typ IConfiguration-Schnittstelle, der formal das Configuration-Objekt mit zugehörigen Konfigurationsinformationen trägt. Wir rufen den Index des Konfigurationsobjekts auf und geben den Schlüssel des entsprechenden Konfigurationselements an, um dessen Wert zu erhalten.

public class DateTimeFormatSettings
  {
   //其他成员
   public DateTimeFormatSettings (IConfiguration configuration)
    {
      this.LongDatePattern   = configuration["LongDatePattern"];
     this.LongTimePattern   = configuration["LongTimePattern"];
     this.ShortDatePattern  = configuration["ShortDatePattern"];
      this.ShortTimePattern  = configuration["ShortTimePattern"];
   }
 }

Um ein DateTimeFormatSettings-Objekt zu erstellen, das die aktuelle Konfiguration widerspiegelt, müssen wir das Configuration-Objekt abrufen, das relevante Konfigurationsinformationen enthält. Wie oben erwähnt, wird das Konfigurationsobjekt von ConfigurationBuilder erstellt und die ursprünglichen Konfigurationsinformationen werden über den entsprechenden ConfigurationProvider gelesen. Die richtige Programmiermethode zum Erstellen eines Konfigurationsobjekts besteht also darin, zuerst ein ConfigurationBuilder-Objekt zu erstellen und dann einen oder mehrere ConfigurationProvider hinzuzufügen Objekte und verwenden Sie schließlich ConfigurationBuilder, um das benötigte Konfigurationsobjekt zu erstellen.

Gemäß dem obigen Programmiermodell haben wir das folgende Programm in einer Konsolenanwendung geschrieben. Wir haben ein Objekt vom Typ „ConfigurationBuilder“ erstellt und der durch Aufruf seiner Add-Methode hinzugefügte ConfigurationProvider ist ein Objekt vom Typ „MemoryConfigurationProvider“. Wie der Name schon sagt, verwendet MemoryConfigurationProvider Objekte im Speicher, um Originalkonfigurationsinformationen bereitzustellen. Diese Originalkonfigurationsinformationen werden insbesondere in einer Sammlung gespeichert, deren Elementtyp KeyValuePair708d620c35cc3f2d1dd0b997d136c07a ist. Schließlich rufen wir die Build-Methode von ConfigurationBuilder auf, um die Konfiguration abzurufen, die zum Erstellen eines DateTimeFormatSettings-Objekts erforderlich ist.

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);
   }
 }

Um die Beziehung zwischen dem gemäß der Konfiguration erstellten DateTimeFormatSettings-Objekt und den ursprünglichen Konfigurationsdaten zu überprüfen, geben wir seine vier Eigenschaften auf der Konsole aus. Wenn dieses Programm ausgeführt wird, erzeugt es die unten gezeigte Ausgabe auf der Konsole. Es ist ersichtlich, dass es sich um eine echte Widerspiegelung der von uns bereitgestellten Konfiguration handelt.
LongDatePattern: dddd, MMMM d, yyyy
LongTimePattern: h:mm:ss tt
ShortDatePattern: M/d/yyyy
ShortTimePattern: h:mm tt

2. Lesen Nehmen Sie eine strukturierte Konfiguration
Die meisten Konfigurationen in realen Projekten weisen eine strukturierte hierarchische Struktur auf, sodass auch das Konfigurationsobjekt im Konfigurationsmodell eine solche Struktur aufweist. Eine strukturierte Konfiguration hat eine Baumhierarchie und ein Konfigurationsobjekt stellt einen Knoten dar, der den Konfigurationsbaum bildet. Dieser Konfigurationsbaum kann durch das Konfigurationsobjekt als Wurzelknoten dargestellt werden. Als Schlüssel-Wert-Paare verkörperte atomare Konfigurationselemente existieren im Allgemeinen in Konfigurationsobjekten als Blattknoten. Die Konfiguration von Nicht-Blattknoten enthält eine Reihe von untergeordneten Knoten, und jeder untergeordnete Knoten ist auch ein Konfigurationsobjekt.

接下来我们同样以实例的方式来演示如何定义并读取具有层次化结构的配置。我们依然沿用上一节的应用场景,现在我们不仅仅需要设置日期/时间的格式,还需要设置其他数据类型的格式,比如表示货币的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中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn