>  기사  >  백엔드 개발  >  ASP.NET Core 구성 자습서 - 구성 정보 읽기

ASP.NET Core 구성 자습서 - 구성 정보 읽기

高洛峰
高洛峰원래의
2017-02-07 11:46:491282검색

"구성"이라는 단어가 나오면 대부분의 .NET 개발자는 우리 모두가 수년 동안 사용해 온 app.config와 web.config라는 두 가지 특수 파일을 즉시 떠올릴 것입니다. 이 두 파일에 구조화된 구성 정보를 정의하는 것입니다. .NET Core의 경우 구성을 정의하는 방법을 포함하여 우리가 당연하게 여기는 많은 사항이 변경되었습니다. 전반적으로 새로운 구성 시스템은 더욱 가볍고 확장성이 향상되었습니다. 가장 큰 특징은 다양한 데이터 소스를 지원한다는 것입니다. 메모리 변수를 구성을 위한 데이터 소스로 사용하거나 영구 파일 또는 데이터베이스에서 직접 구성하고 정의할 수 있습니다.

이렇게 새롭게 디자인된 구성 시스템을 한 번도 접해보지 못한 분들이 많기 때문에, 모두가 감각적으로 이해할 수 있도록 프로그래밍 관점에서 먼저 경험해 보겠습니다. 구성용 API에는 Configuration, ConfigurationBuilder 및 ConfigurationProvider라는 세 가지 개체가 포함됩니다. 구성 모델에는 이를 나타내는 해당 인터페이스가 있습니다. 이 세 개체 사이의 관계는 매우 명확합니다. Configuration 개체는 프로그래밍 프로세스에 사용되는 구성 정보를 전달하며, ConfigurationProvider는 구성 정보의 원본 데이터 소스 제공자입니다. 둘 사이의 통신은 ConfigurationBuilder에 의해 완료됩니다. ConfigurationProvider를 사용하여 소스 데이터를 추출하는 것은 Configuration 개체로 변환됩니다.

1. 키-값 쌍 형태로 구성 읽기
대부분의 경우 구성 정보는 전체적으로 구조화된 계층 관계를 가지지만 "원자적" 구성 항목은 가장 간단한 형태의 "키-값 쌍"이며 키와 값은 모두 문자열입니다. 다음으로 간단한 예를 사용하여 키-값 쌍 형태로 구성을 읽는 방법을 보여 드리겠습니다. ASP.NET Core용 콘솔 애플리케이션을 만들고 project.json의 NuGet 패키지 "Microsoft.Extensions.Configuration"에 대한 종속성을 다음과 같이 추가합니다. 구성 모델은 이 패키지에 구현됩니다.

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

이를 위해 애플리케이션이 구성을 통해 날짜/시간 표시 형식을 설정해야 한다고 가정합니다. 해당 클래스의 네 가지 속성은 DateTime 개체를 반영합니다. 형식(각각 긴 날짜/시간 및 짧은 날짜/시간).

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

DateTimeFormatSettings의 네 가지 속성에 반영된 날짜/시간 표시 형식을 구성을 통해 제어하려고 하므로 이에 대한 생성자를 정의합니다. 다음 코드 조각에 표시된 대로 생성자에는 관련 구성 정보의 Configuration 개체를 공식적으로 전달하는 IConfiguration 인터페이스 유형의 매개 변수가 있습니다. 구성 개체의 인덱스를 호출하고 해당 구성 항목의 키를 지정하여 해당 값을 가져옵니다.

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 객체를 생성한 다음 하나 이상의 ConfigurationProvider를 추가하는 것입니다. 마지막으로 ConfigurationBuilder를 사용하여 필요한 Configuration 객체를 생성합니다.

위 프로그래밍 모델에 따라 콘솔 애플리케이션에 다음 프로그램을 작성했습니다. 우리는 ConfigurationBuilder 유형의 개체를 만들었고 Add 메서드를 호출하여 추가된 ConfigurationProvider는 MemoryConfigurationProvider 유형의 개체입니다. 이름에서 알 수 있듯이 MemoryConfigurationProvider는 메모리의 개체를 사용하여 원래 구성 정보를 제공합니다. 특히 이러한 원래 구성 정보는 요소 유형이 KeyValuePair708d620c35cc3f2d1dd0b997d136c07a인 컬렉션에 저장됩니다. 마지막으로 ConfigurationBuilder의 Build 메서드를 호출하여 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);
   }
 }

구성에 따라 생성된 DateTimeFormatSettings 개체와 구성 원본 데이터 간의 관계를 확인하기 위해 해당 개체의 4가지 속성을 콘솔에 출력합니다. 이 프로그램이 실행되면 콘솔에 아래와 같은 출력이 생성됩니다. 이는 우리가 제공한 구성이 실제로 반영된 것임을 알 수 있습니다.
LongDatePattern: dddd, MMMM d, yyyy
LongTimePattern: h:mm:ss tt
ShortDatePattern: M/d/yyyy
ShortTimePattern: h:mm tt

2. 읽기 구조화된 구성을 취하세요
실제 프로젝트에 포함된 대부분의 구성은 구조화된 계층 구조를 가지므로 구성 모델의 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中文网!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.