• ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置


    前言

    最近有点忙,学习有点懈怠(惭愧),抽时间学习把这篇博客写完,希望理解。相信自己能坚持下去,把这个系列写完。好啦,开搞。说道配置文件,基本大多数软件为了扩展性、灵活性都会涉及到配置文件,比如之前常见的app.config和web.config。然后再说.NET Core,很多都发生了变化。总体的来说技术在进步,新的方式更加轻量级,具有更好的扩展性,数据源更加多样性。

    ASP.NET Core 应用可用的配置提供程序

    提供程序 一下对象提供配置
    Azure Key Vault 配置提供程序 Azure Key Vault
    Azure 应用配置提供程序 Azure 应用程序配置
    命令行配置提供程序 命令行参数
    自定义配置提供程序 自定义源
    环境变量配置提供程序 环境变量
    文件配置提供程序 INI、JSON 和 XML 文件
    Key-per-file 配置提供程序 目录文件
    内存配置提供程序 内存中集合
    用户机密 用户配置文件目录中的文件

    配置提供程序的典型顺序为:
    1.appsettings.json
    2.appsettings.Environment.json
    3.用户机密
    4.使用环境变量配置提供程序通过环境变量提供。
    5.使用命令行配置提供程序通过命令行参数提供。
    注意: 通常的做法是将命令行配置提供程序添加到一系列提供程序的末尾,使命令行参数能够替代由其他提供程序设置的配置。

    配置模型三要素

    .NET Core的配置系统由三个核心对象构成,分别是IConfiguration、IConfigurationBuilder、IConfigurationSource。

    • IConfiguration:读取出来的配置信息最终会转换成一个IConfiguration对象供应用程序使用。
    • IConfigurationBuilder:IConfigurationBuilder是IConfiguration对象的构建者。
    • IConfigurationSource:则代表配置数据最原始的来源。

    文件配置

    读取INI文件配置

    首先创建一个ASP .NET Core Web API项目,在主目录下添加MyIniConfig.ini文件。

    ID=1
    Title="INIConfig title"
    Name="INIConfig name"
    
    [Logging:LogLevel]
    Default=Information
    

    在Program类中读取配置文件

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.Sources.Clear();
                    var env = hostingContext.HostingEnvironment;
                    config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true);
                    config.AddEnvironmentVariables();
                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }
    

    新建一个名为SettingsController的控制器,读取配置文件。

        [Route("api/[controller]/[action]")]
        [ApiController]
        public class SettingsController : ControllerBase
        {
            private readonly IConfiguration Configuration;
            public SettingsController(IConfiguration configuration)
            {
                Configuration = configuration;
            }
            public ContentResult INISetting()
            {
                int id = Configuration.GetValue<int>("ID");
                var title = Configuration["Title"];
                var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
                return Content($"ID:{id}
    " +$"Title:{title}
    "+
                    $"Default Log Level: {defaultLogLevel}");
            }
        }
    

    利用PostMan可以看到已经读取到刚刚设置的INI文件。
    image

    读取Json配置文件。

    新建ASP.NET Core Web API项目,在主目录下添加MyJsonConfig.json文件。

    {
      "ID": "1",
      "Title": "My JsonConfig",
      "Logging": {
        "LogLevel": {
          "Default": "Information"
        }
      }
    }
    

    在Program类中读取配置文件

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.Sources.Clear();
                    var env = hostingContext.HostingEnvironment;
                    config.AddJsonFile("MyJsonConfig.json", optional: true, reloadOnChange: true);
                    config.AddEnvironmentVariables();
                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }
    

    新建一个名为SettingsController的控制器,读取配置文件。

        [Route("api/[controller]/[action]")]
        [ApiController]
        public class SettingsController : ControllerBase
        {
            private readonly IConfiguration Configuration;
            public SettingsController(IConfiguration configuration)
            {
                Configuration = configuration;
            }
            public ContentResult JsonSetting()
            {
                int id = Configuration.GetValue<int>("ID");
                var title = Configuration["Title"];
                var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
    
                return Content($"ID:{id}
    " + $"Title:{title}
    " +
                    $"Default Log Level: {defaultLogLevel}");
            }
        }
    

    利用PostMan可以看到已经读取到刚刚设置的Json文件。
    image

    读取XML文件

    新建ASP.NET Core Web API项目,在主目录下添加MyXMLConfig.xml文件。

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <ID>1</ID>
      <Title>MyXMLConfig Title</Title>
      <Name>MyXMLConfig Name</Name>
      <Logging>
        <LogLevel>
          <Default>Information</Default>
        </LogLevel>
      </Logging>
    </configuration>
    

    在Program类中读取配置文件

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                   config.Sources.Clear();
                   var env = hostingContext.HostingEnvironment;
                   config.AddXmlFile("MyXMLConfig.xml", optional: true, reloadOnChange: true);
                   config.AddEnvironmentVariables();
                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }
    

    新建一个名为SettingsController的控制器,读取配置文件。

        [Route("api/[controller]/[action]")]
        [ApiController]
        public class SettingsController : ControllerBase
        {
            private readonly IConfiguration Configuration;
            public SettingsController(IConfiguration configuration)
            {
                Configuration = configuration;
            }
            public ContentResult XmlSetting()
            {
                int id = Configuration.GetValue<int>("ID");
                var title = Configuration["Title"];
                var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
    
                return Content($"ID:{id}
    " + $"Title:{title}
    " +
                    $"Default Log Level: {defaultLogLevel}");
            }
        }
    

    利用PostMan可以看到已经读取到XML文件的配置。
    image

    读取配置项的方法

    说几个在读取配置项中比较常用的方法,大家可以根据上面例子,自己试一下,这里就不详细讲解了。

    GetValue

    ConfigurationBinder.GetValue 从配置中提取一个具有指定键的值,并将它转换为指定的类型。在上面的中int id = Configuration.GetValue("ID");就是利用这个方法获取指定类型。

    GetSection

    IConfiguration.GetSection 会返回具有指定子节键的配置子节。

    GetChildren

    IConfiguration.GetChildren 方法获取直接后代配置子节。

    Exists

    ConfigurationExtensions.Exists(IConfigurationSection)确定该部分是否具有 Value 或子级。

    将配置绑定到对象

    新建ASP.NET Core Web API项目,在主目录下添加MyArray.json文件。

    {
      "array": {
        "entries": {
          "0": "value0",
          "1": "value1",
          "2": "value2",
          "3": "value3"
        }
      }
    }
    

    创建一个model。

        public class Model
        {
            public string[] Entries { get; set; }
        }
    

    在Program类中读取配置文件

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                   config.Sources.Clear();
                   var env = hostingContext.HostingEnvironment;
                   config.AddJsonFile("MyArray.json",optional: true,reloadOnChange: true);
                   config.AddEnvironmentVariables();
                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }
    

    新建一个名为SettingsController的控制器,读取配置文件。

        [Route("api/[controller]/[action]")]
        [ApiController]
        public class SettingsController : ControllerBase
        {
            private readonly IConfiguration Configuration;
            public SettingsController(IConfiguration configuration)
            {
                Configuration = configuration;
            }
            public ContentResult ToModel()
            {
            array = Configuration.GetSection("array").Get<Model>();
                string modelStr = null;
                for (int j = 0; j < array.Entries.Length; j++)
                {
                    modelStr += $"Index: {j}  Value:  {array.Entries[j]} 
    ";
                }
    
                return Content(modelStr);
            }
        }
    

    利用PostMan可以看到已经读取到绑定到Model的配置。
    image

    自定义配置

    如果上面的方式还不能满足项目要求的话,还可以从数据库中读取配置信息。接下来我们通过实体框架(EF)读取数据库中配置信息(埋个伏笔,后续做个相关教程)。便于操作,这次使用内存数据库做配置源。
    首先做一个创建一个实体。

        public class EFModel
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Value { get; set; }
        }
    

    添加 EFConfigContext 以存储和访问配置的值。

        public class EFConfigContext:DbContext
        {
            public EFConfigContext(DbContextOptions options) : base(options)
            {
            }
    
            public DbSet<EFModel> Values { get; set; }
        }
    

    创建用于实现 IConfigurationSource 的类。

        public class EFConfigurationSource : IConfigurationSource
        {
            private readonly Action<DbContextOptionsBuilder> _optionsAction;
    
            public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
            {
                _optionsAction = optionsAction;
            }
    
            public IConfigurationProvider Build(IConfigurationBuilder builder)
            {
                return new EFConfigurationProvider(_optionsAction);
            }
        }
    

    通过从 ConfigurationProvider 继承来创建自定义配置提供程序。 当数据库为空时,配置提供程序将对其进行初始化。

        public class EFConfigurationProvider:ConfigurationProvider
        {
            Action<DbContextOptionsBuilder> OptionsAction { get; }
            public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
            {
                OptionsAction = optionsAction;
            }
    
            public override void Load()
            {
                var builder = new DbContextOptionsBuilder<EFConfigContext>();
    
                OptionsAction(builder);
    
                using (var dbContext =new EFConfigContext(builder.Options))
                {
                    dbContext.Database.EnsureCreated();
    
                    Data =!dbContext.Values.Any()?CreateAndSaveValues(dbContext) : dbContext.Values.ToDictionary(c => c.Name, c => c.Value);
                }
    
            }
    
            private static IDictionary<string, string> CreateAndSaveValues(EFConfigContext dbContext)
            {
                var configValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
                {
                    {"name1","value1" },
                    {"name2","value2" },
                    {"name3","value3" }
                };
    
                dbContext.Values.AddRange(configValues.Select(v => new EFModel
                {
                    Name = v.Key,
                    Value = v.Value
                }).ToArray());
    
                dbContext.SaveChanges();
                return configValues;
            }
        }
    

    使用 AddEFConfiguration 扩展方法将配置源添加到 ConfigurationBuilder。

        public static class EFExtensions
        {
            public static IConfigurationBuilder AddEFConfiguration(this IConfigurationBuilder builder,Action<DbContextOptionsBuilder> optionsAction)
            {
                return builder.Add(new EFConfigurationSource(optionsAction));
            }
        }
    

    在 Program.cs 中使用自定义的 EFConfigurationProvider:

        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.Sources.Clear();
                    var env = hostingContext.HostingEnvironment;
                    config.AddEFConfiguration(
                    options => options.UseInMemoryDatabase("InMemoryDb"));
                    config.AddEnvironmentVariables();
                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }
    

    在Startup中通过依赖注入添加据库上下文服务,向控制器提供服务。

        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<EFConfigContext>(opt => opt.UseInMemoryDatabase("InMemoryDb"));
                services.AddControllers();
            }
    
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
        }
    

    在控制器中注入服务,读取内存数据库中的数据。

        [Route("api/[controller]/[action]")]
        [ApiController]
        public class SettingsController : ControllerBase
        {
    
            private readonly EFConfigContext _efDbContext;
    
            public SettingsController( EFConfigContext efDbContext)
            {
                _efDbContext = efDbContext;
            }
    
            public ActionResult<IEnumerable<EFModel>> EFSetting()
            {
                List<EFModel> list = _efDbContext.Values.ToList();
    
                return list;
            }
        }
    

    利用PostMan可以看到已经读取到我们自定义的配置源。
    image
    加一张整体的项目结构,方便大家理解。
    image
    最近疫情有些反复,出门做好个人防护,玩耍时别忘记学习。最后祝大家周末愉快!

  • 相关阅读:
    MySQL之ORM
    MySQL之索引补充
    MySQL存储过程
    c primer plus 7编程练习
    c语言中统计单词数目程序
    c语言统计输入字符数及行数
    c语言中getchar()、putchar()函数例子
    c primer plus 6编程练习
    c语言 %c 一次输出多个字符 (特殊程序)
    c语言 复合赋值运算符的优先级低于算术运算符
  • 原文地址:https://www.cnblogs.com/gurenyumao/p/15471933.html
Copyright © 2020-2023  润新知