浅析.netcore中的Configuration


不管是.net还是.netcore项目,我们都少不了要读取配置文件,在.net中项目,配置一般就存放在web.config中,但是在.netcore中我们新建的项目根本就看不到web.config,取而代之的是appsetting.json。

新建一个webapi项目,可以在startup中看到一个IConfiguration,通过框架自带的IOC使用构造函数进行实例化,在IConfiguration中我们发现直接就可以读取到appsetting.json中的配置项了,如果在控制器中需要读取配置,也是直接通过构造

函数就可以实例化IConfiguration对象进行配置的读取。下面我们试一下运行的效果,在appsetting.json添加一个配置项,在action中可以进行访问。

 

添加其他配置文件

那我们的配置项是不是只能写在appsetting.json中呢?当然不是,下面我们看看如何添加其他的文件到配置项中,根据官网教程,我们可以使用ConfigureAppConfiguration实现。

首先我们在项目的根目录新建一个config.json,然后在其中随意添加几个配置,然后在program.cs中添加高亮显示的部分,这样很简单的就将我们新增的json文件中的配置加进来了,然后在程序中就可以使用IConfiguration进行访问config.json

中的配置项了。

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration(configure => {               
                configure.AddJsonFile("config.json");  //无法热修改

            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

但是这个无法在配置项修改后读取到最新的数据,我们可以调用重载方法configure.AddJsonFile("config.json",true,reloadOnChange:true)实现热更新。

除了添加json文件外,我们还可以使用AddXmlFile添加xml文件,使用AddInMemoryCollection添加内存配置

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context,configure) => {
            Dictionary<string, string> memoryConfig = new Dictionary<string, string>();
            memoryConfig.Add("memoryKey1", "m1");
            memoryConfig.Add("memoryKey2", "m2");
    
            configure.AddInMemoryCollection(memoryConfig);
    
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

 源码解读:

在自动生成的项目中,我们没有配置过如何获取配置文件,那.netcore框架是怎么知道要appsetting.json配置文件的呢?我们通过查看源码我们就可以明白其中的道理。

Host.CreateDefaultBuilder(args)    
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>();
    });


//CreateDefaultBuilder源码
public static IHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new HostBuilder();

    builder.UseContentRoot(Directory.GetCurrentDirectory());
    builder.ConfigureHostConfiguration(config =>
    {
        config.AddEnvironmentVariables(prefix: "DOTNET_");
        if (args != null)
        {
            config.AddCommandLine(args);
        }
    });

    builder.ConfigureAppConfiguration((hostingContext, config) =>
    {
        var env = hostingContext.HostingEnvironment;

        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

        if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
        {
            var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
            if (appAssembly != null)
            {
                config.AddUserSecrets(appAssembly, optional: true);
            }
        }

        config.AddEnvironmentVariables();

        if (args != null)
        {
            config.AddCommandLine(args);
        }
    });
    
    ....

    return builder;
}

 

怎么样?是不是很有意思,在源码中我们看到在Program中构建host的时候就会调用ConfigureAppConfiguration对应用进行配置,会读取appsetting.json文件,并且会根据环境变量加载不同环境的appsetting,同时还可以看到应用不仅添加了

appsetting的配置,而且添加了从环境变量、命令行传入参数的支持,对于AddUserSecrets支持读取用户机密文件中的配置,这个在存储用户机密配置的时候会用到。

那为什么我们可以通过再次调用ConfigureAppConfiguration去追加配置信息,而不是覆盖呢?我们同样可以在源码里面找到答案。

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

//以下为部分源码
private List<Action<HostBuilderContext, IConfigurationBuilder>> _configureAppConfigActions = new List<Action<HostBuilderContext, IConfigurationBuilder>>();
private IConfiguration _appConfiguration;
public IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate) { _configureAppConfigActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); return this; } public IHost Build() { ... BuildAppConfiguration(); ... } private void BuildAppConfiguration() { var configBuilder = new ConfigurationBuilder() .SetBasePath(_hostingEnvironment.ContentRootPath) .AddConfiguration(_hostConfiguration, shouldDisposeConfiguration: true); foreach (var buildAction in _configureAppConfigActions) { buildAction(_hostBuilderContext, configBuilder); } _appConfiguration = configBuilder.Build(); _hostBuilderContext.Configuration = _appConfiguration; }

框架声明了一个List<Action<HostBuilderContext, IConfigurationBuilder>>,我们每次调用ConfigureAppConfiguration都是往这个集合中添加元素,等到Main函数调用Build的时候会触发ConfigurationBuilder,将集合中的所有元素进行循环追加

到ConfigurationBuilder,最后就形成了我们使用的IConfiguration,这样一看对于.netcore中IConfiguration是怎么来的就很清楚了。

 

读取层级配置项

如果需要读取配置文件中某个层级的配置应该怎么做呢?也很简单,使用IConfiguration["key:childKey..."]

比如有这样一段配置:

"config_key2": {
    "config_key2_1": "config_key2_1",
    "config_key2_2": "config_key2_2"
  }

 可以使用IConfiguration["config_key2:config_key2_1"]来获取到config_key2_1的配置项,如果config_key2_1下还有子配置项childkey,依然可以继续使用:childkey来获取

 

选项模式获取配置项

选项模式使用类来提供对相关配置节的强类型访问,将配置文件中的配置项转化为POCO模型,可为开发人员编写代码提供更好的便利和易读性

我们添加这样一段配置:

"Student": {
    "Sno": "SNO",
    "Sname": "SNAME",
    "Sage": 18,
    "ID": "001"
  }

 接下来我们定义一个Student的Model类

public class Student
{
    private string _id;
    public const string Name = "Student";
    private string ID { get; set; }
    public string Sno { get; set; }
    public string Sname { get; set; }
    public int Sage { get; set; }
}

可以使用多种方式来进行绑定: 

1、使用Bind方式绑定

Student student = new Student();
_configuration.GetSection(Student.Name).Bind(student);

 2、使用Get方式绑定

var student1 = _configuration.GetSection(Student.Name).Get<Student>(binderOptions=> {
binderOptions.BindNonPublicProperties = true;
});

 Get方式和Bind方式都支持添加一个 Action<BinderOptions>的重载,通过这个我们配置绑定时的一些配置,比如非公共属性是否绑定(默认是不绑定的),但是Get比BInd使用稍微方便一些,如果需要绑定集合也是一样的道理,将Student

替换成List<Student>。

3、全局方式绑定

前两种方式只能在局部生效,要想做一次配置绑定,任何地方都生效可用,我们可以使用全局绑定的方式,全局绑定在Startup.cs中定义

services.Configure<Student>(Configuration.GetSection(Student.Name));

此方式会使用选项模式进行配置绑定,并且会注入到IOC中,在需要使用的地方可以在构造函数中进行实例化

private readonly ILogger<WeatherForecastController> _logger;
private readonly IConfiguration _configuration;
private readonly Student _student;

public WeatherForecastController(ILogger<WeatherForecastController> logger, IConfiguration configuration, IOptions<Student> student)
{
    _logger = logger;
    _configuration = configuration;
    _student = student.Value;
}

 

命名选项的使用

对于不同的配置节,包含的配置项一样时,我们在使用选项绑定的时候无需定义和注入两个类,可以在绑定时指定名称,比如下面的配置:

"Root": {
  "child1": {
    "child_1": "child1_1",
    "child_2": "child1_2"
  },
  "child2": {
    "child_1": "child2_1",
    "child_2": "child2_2"
  }
}

public class Root
{
  public string child_1{get;set;}
  public string child_2{get;set;}
} services.Configure
<Root>("Child1",Configuration.GetSection("Root:child1")); services.Configure<Root>("Child2", Configuration.GetSection("Root:child2")); private readonly ILogger<WeatherForecastController> _logger; private readonly IConfiguration _configuration; private readonly Student _student; private readonly Root _child1; private readonly Root _child2; public WeatherForecastController(ILogger<WeatherForecastController> logger, IConfiguration configuration, IOptions<Student> student,IOptionsSnapshot<Root> root) { _logger = logger; _configuration = configuration; _student = student.Value; _child1 = root.Get("Child1"); _child2 = root.Get("Child2"); }

 

文章来源:https://www.cnblogs.com/XFlyMan/p/15720303.html

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
管理员
上一篇:Dotfuscator Professional Edition 4.96 版的使用教程
下一篇:使用.NET 6开发TodoList应用(7)——使用AutoMapper实现GET请求
评论列表

发表评论

评论内容
昵称:
关联文章

浅析.netcoreConfiguration
在Winform项目和Web API.NetCore项目使用Serilog 来记录日志信息
使用.NET 6开发TodoList应用(26)——实现Configuration和Option强类型绑定
.NETCore和.NET5 MVC 控制器判断是否登录
.NETCore动态解析Razor代码cshtml代码解析RazorEngine.NetCore
.NETCore和.NET5 MVC使用 Session
.NETCore和.NET5 MVC解析获取appsettings.json数据
.NETCore用Process.Start打开网址出现异常
.NET6一些常用组件配置及使用记录,持续更新。。。
.NETCore IIS应用程序池事件监听
.NETCore-winform 判断是否设计模式
Asp.NetCore3.1开源项目升级为.Net6.0
ASP.NET Core MVC路由约束
ABP VNext框架Winform终端开发和客户端授权信息处理
维护项目iconfont图标库
javascriptlet和var区别
深入理解jsyield
Quartz在.NET使用
关于RazorEngine研究过程记录
javascript删除html字符串空行

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码