zoukankan      html  css  js  c++  java
  • 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(七)-- 结构化配置

    本篇将记录.Net Core里颇有特色的结构化配置的使用方法。

    相比较之前通过Web.Config或者App.Config配置文件里使用xml节点定义配置内容的方式,.Net Core在配置系统上发生了很大的变化,具有了配置源多样化、更加轻量、扩展性更好的特点。

    第一部分、基于键值对的配置

    如果要使用结构化配置,需要先引用 "Microsoft.Extensions.Configuration": "1.0.0" nuget包。下面通过一个.Net Core控制台程序演示

    一、单层结构的配置

     1 using Microsoft.Extensions.Configuration;
     2 using Microsoft.Extensions.Configuration.Memory;
     3 using System;
     4 using System.Collections.Generic;
     5 
     6 namespace DiApplicationTest
     7 {
     8     public class Program
     9     {
    10         public static void Main(string[] args)
    11         {
    12             IDictionary<string, string> source = new Dictionary<string, string>()
    13             {
    14                 ["Ele1"] = "value1",
    15                 ["Ele2"] = "value2"
    16             };
    17 
    18             IConfiguration config = new ConfigurationBuilder().Add(new MemoryConfigurationSource() { InitialData = source }).Build();
    19             Console.WriteLine($"Ele1: {config["Ele1"]}");
    20             Console.WriteLine($"Ele2: {config["Ele2"]}");
    21 
    22             Console.ReadLine();
    23         }
    24     }
    25 }

    启动调试,查看cmd窗口输出内容

    上面的例子里,将一个字典作为配置源读入到config配置对象里,通过键可以读取到对应的值。

    二、多层结构的配置

    在大多数情况下,项目里的配置都是多层结构的,也可以称为是结构化的。在上面的例子的基础上稍加修改,实现结构化的配置读取。

     1 using Microsoft.Extensions.Configuration;
     2 using Microsoft.Extensions.Configuration.Memory;
     3 using System;
     4 using System.Collections.Generic;
     5 
     6 namespace DiApplicationTest
     7 {
     8     public class Program
     9     {
    10         public static void Main(string[] args)
    11         {
    12             IDictionary<string, string> source = new Dictionary<string, string>()
    13             {
    14                 ["Ele1"] = "value1",
    15                 ["Ele2:Sub1"] = "value2.1",
    16                 ["Ele2:Sub2"] = "value2.2"
    17             };
    18 
    19             IConfiguration config = new ConfigurationBuilder().Add(new MemoryConfigurationSource() { InitialData = source }).Build();
    20             Console.WriteLine($"Ele1: {config["Ele1"]}");
    21             Console.WriteLine($"Ele2.Sub1: {config.GetSection("Ele2")["Sub1"]}");
    22             Console.WriteLine($"Ele2.Sub2: {config.GetSection("Ele2")["Sub2"]}");
    23 
    24             Console.ReadLine();
    25         }
    26     }
    27 }

    启动调试,查看cmd窗口输出内容

    在这个例子里,字典内容描述了一个具有两层结构的配置,第一层有Ele1和Ele2两个节点,分别对应一个字符内容和一个复合内容,第二层有Sub1和Sub2两个节点,同时挂在Ele2节点下,组成了一个复合结构。

    注意看字典项里的Key,因为字典里的数据是扁平化的,为了能清晰描述节点之间的上下层关系,需要通过“:”符号来标识。

    config对象通过GetSection方法来获取当前节点的某个下级节点内容。

     

    第二部分、其他配置来源

    除了上面例子里展示的配置源来自内存内容,也可以来自Xml文件、JSON文件或者数据库等。因为在.Net Core里使用JSON文件描述配置内容很常见,下面就展示如何读取JSON配置文件。

    先添加如下两个nuget包,支持从json文件读取内容

    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",

    添加 appsettings.json 文件

    1 {
    2   "Ele1": "value1",
    3   "Ele2": {
    4     "Sub1": "value2.1",
    5     "Sub2": "value2.2"
    6   }
    7 }

    修改Main函数内容

     1 using Microsoft.Extensions.Configuration;
     2 using System;
     3 using System.IO;
     4 
     5 namespace DiApplicationTest
     6 {
     7     public class Program
     8     {
     9         public static void Main(string[] args)
    10         {
    11             IConfigurationBuilder builder = new ConfigurationBuilder();
    12             builder.SetBasePath(Directory.GetCurrentDirectory());
    13             builder.AddJsonFile("appsettings.json");
    14 
    15             IConfiguration config = builder.Build();
    16             Console.WriteLine($"Ele1: {config["Ele1"]}");
    17             Console.WriteLine($"Ele2.Sub1: {config.GetSection("Ele2")["Sub1"]}");
    18             Console.WriteLine($"Ele2.Sub2: {config.GetSection("Ele2")["Sub2"]}");
    19 
    20             Console.ReadLine();
    21         }
    22     }
    23 }

    启动调试,查看cmd窗口输入内容,与上面的例子内容一致。

    这个例子将原来在字典里的内容转换成Json格式化的内容存储在持久化文件里。通过指定配置源,同样可以读取内容。

     

    第三部分、Options对象映射

    当配置文件内容较多时,通过config的Key获取对应的配置项的值变得比较繁琐。.Net Core的配置系统采用了一种叫“Options Pattern”的模式使配置内容与有着对应结构的对象进行映射,这种对象就叫做Options对象。

    下面将简单演示一下这种映射方式。

    首先添加如下nuget包引用,使用此模式的相关接口和类都在这个包里。同时还需要引入DI容器。

    "Microsoft.Extensions.DependencyInjection": "1.0.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",

    添加两个具有层级结构的Options类

     1     public class ConfigOptions
     2     {
     3         public string Ele1 { get; set; }
     4         public SubConfigOptions Ele2 { get; set; }
     5     }
     6 
     7     public class SubConfigOptions
     8     {
     9         public string Sub1 { get; set; }
    10         public string Sub2 { get; set; }
    11     }

    修改Main函数内容

     1         public static void Main(string[] args)
     2         {
     3             // 创建DI容器,注册Options Pattern服务
     4             IServiceCollection services = new ServiceCollection();
     5             services.AddOptions();
     6 
     7             // 读取配置文件
     8             IConfigurationBuilder builder = new ConfigurationBuilder();
     9             builder.SetBasePath(Directory.GetCurrentDirectory());
    10             builder.AddJsonFile("appsettings.json");
    11             IConfiguration config = builder.Build();
    12 
    13             // 通过注册的服务获取最终映射的配置对象
    14             IServiceProvider serviceProvider = services.Configure<ConfigOptions>(config).BuildServiceProvider();
    15             ConfigOptions options = serviceProvider.GetService<IOptions<ConfigOptions>>().Value;
    16 
    17             Console.WriteLine($"Ele1: {options.Ele1}");
    18             Console.WriteLine($"Ele2.Sub1: {options.Ele2.Sub1}");
    19             Console.WriteLine($"Ele2.Sub2: {options.Ele2.Sub2}");
    20 
    21             Console.ReadLine();
    22         }

    启动调试,查看cmd窗口输入内容,与上面的例子内容一致。

    在定义Options对象结构时,对象内的属性名称要与对应层级的配置Key的值保持一致,层级关系也要与配置内容的层级结构保持一致。

    通过调用 services.AddOptions() 方法注册Options Pattern服务。将配置内容注册到容器里,来获取对应的服务Provider对象。通过调用GetService方法获得对应的真实服务对象,即带有事先定义的Options类型的泛型接口IOptions,接口的Value值就是配置内容映射的Options对象。

     

    第四部分、Asp.Net Core里的配置管理

    这个系列之前使用的例子里添加配置管理相关的功能,来修改初始化日志级别的代码,同时添加一些自定义配置。

    先添加配置相关的nuget包

        "Microsoft.Extensions.Configuration": "1.0.0",
        "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
        "Microsoft.Extensions.Configuration.Json": "1.0.0",
        "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"

    添加appsettings.json文件

     1 {
     2     // 日志配置
     3     "Logging": {
     4         "LogLevel": {
     5             "Microsoft": "Warning"
     6         }
     7     },
     8     // 自定义配置
     9     "CfgContent": {
    10         "Ele1": "value1",
    11         "Ele2": {
    12             "Sub1": "value2.1",
    13             "Sub2": "value2.2"
    14         }
    15     }
    16 }

    添加上个例子里的 ConfigOptions.cs、SubConfigOptions.cs 类,修改 Startup.cs 的内容,添加配置相关代码

     1 using System.IO;
     2 using Microsoft.AspNetCore.Builder;
     3 using Microsoft.Extensions.Configuration;
     4 using Microsoft.Extensions.DependencyInjection;
     5 using Microsoft.Extensions.Logging;
     6 
     7 namespace WebApiFrame
     8 {
     9     public class Startup
    10     {
    11         public IConfiguration Configuration { get; }
    12 
    13         public Startup()
    14         {
    15             var builder = new ConfigurationBuilder()
    16                 .SetBasePath(Directory.GetCurrentDirectory())
    17                 .AddJsonFile("appsettings.json");
    18 
    19             Configuration = builder.Build();
    20         }
    21 
    22         public void ConfigureServices(IServiceCollection services)
    23         {
    24             services.AddOptions();
    25             services.Configure<ConfigOptions>(Configuration.GetSection("CfgContent"));
    26 
    27             // 注入MVC框架
    28             services.AddMvc();
    29         }
    30 
    31         public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    32         {
    33             // 添加日志支持
    34             loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    35             loggerFactory.AddDebug();
    36 
    37             // 添加NLog日志支持
    38             //loggerFactory.AddNLog();
    39 
    40             // 添加MVC中间件
    41             app.UseMvc();
    42         }
    43     }
    44 }

    修改 DemoController.cs 内容

     1 using System.Threading.Tasks;
     2 using Microsoft.AspNetCore.Http;
     3 using Microsoft.AspNetCore.Mvc;
     4 using Microsoft.Extensions.Options;
     5 
     6 namespace WebApiFrame
     7 {
     8     [Route("[controller]")]
     9     public class DemoController : Controller
    10     {
    11         private ConfigOptions _cfgContent { get; }
    12 
    13         public DemoController(IOptions<ConfigOptions> options)
    14         {
    15             _cfgContent = options.Value;
    16         }
    17 
    18         [HttpGet("index")]
    19         public async Task Index()
    20         {
    21             HttpContext.Response.ContentType = "text/html";
    22             await HttpContext.Response.WriteAsync($"<span>Ele1: {_cfgContent.Ele1}</span><br />");
    23             await HttpContext.Response.WriteAsync($"<span>Ele2.Sub1: {_cfgContent.Ele2.Sub1}</span><br />");
    24             await HttpContext.Response.WriteAsync($"<span>Ele2.Sub2: {_cfgContent.Ele2.Sub2}</span><br />");
    25         }
    26     }
    27 }

    启动调试,访问地址 http://localhost:5000/demo/index ,页面显示配置内容

    从这个例子里可以看到,读取 appsettings.json 配置文件内容并分成两部分,其中一部分配置Logging作为Logger的配置内容用于日志初始化,另外一部分CfgContent配置内容注册到DI容器,在控制器的构造函数里通过IOptions泛型类型的参数注入,这样控制器就可以读取配置文件的内容。

  • 相关阅读:
    最小公倍数
    记录输入的数字并输出
    带时间的进度条
    进度条二:普通版
    文件的练习
    《k8s权威指南》读书笔记
    面试后如何判断岗位是否符合自己要求
    索引的三星系统
    使用Mysql分区表对数据库进行优化
    MySQL索引的基本操作
  • 原文地址:https://www.cnblogs.com/niklai/p/5701905.html
Copyright © 2011-2022 走看看