搜索

查看: 3115|回复: 11

[ASP.NET] .NET 中配置从xml转向json方法示例详解

[复制链接]
发表于 2023-5-4 11:25:25 | 显示全部楼层 |阅读模式
Editor 2023-5-4 11:25:25 3115 11 看全部
目录
  • 一、配置概述
  • 二、配置初识
  • 三、选项模式
  • 四、选项依赖注入
  • 五、其它配置
  • 六、托管模式
    一、配置概述
    在.net framework平台中我们常见的也是最熟悉的就是.config文件作为配置,控制台桌面程序是App.config,Web就是web.config,里面的配置格式为xml格式。

    20221103084444026.png

    20221103084444026.png


    在xml里面有系统生成的配置项,也有我们自己添加的一些配置,最常用的就是appSettings节点,用来配置数据库连接和参数。
    使用的话就引用包System.Configuration.ConfigurationManager 之后取里面的配置信息:
    System.Configuration.ConfigurationManager.AppSettings["ConnectionString"]

    随着技术的发展这种配置方式显得冗余复杂,如果配置项太多层级关系参数表达凌乱,在.net core开始也将配置的格式默认成了json格式,包括现在很多的其它配置也是支持的,比如java中常用的yaml格式,为什么能支持这么多读取源和格式,其实质在于配置提供程序。
    目前.NET 中的配置是使用一个或多个配置提供程序执行的。 配置提供程序使用各种配置源从键值对读取配置数据,这些配置程序稍后我们会看到,读取的配置源可以是如下这些:
  • 设置文件,appsettings.json
  • 环境变量
  • Azure Key Vault
  • Azure 应用配置
  • 命令行参数
  • 已安装或已创建的自定义提供程序
  • 目录文件
  • 内存中的 .NET 对象
  • 第三方提供程序
    二、配置初识
    IConfiguration 接口是所有配置源的单个表示形式,给定一个或多个配置源,IConfiguration 类型提供配置数据的统一视图。

    20221103084444027.png

    20221103084444027.png


    上图我们可能没有直观的感受,现在写一个例子来看看
    (1). 新建控制台应用程序:创建控制台使用的是.net 6.0 框架,vs 2022。
    安装 Microsoft.Extensions.Configuration.Json NuGet 包,该包提供json配置文件读取。
    Install-Package Microsoft.Extensions.Configuration.Json

    20221103084444028.png

    20221103084444028.png


    (2). 添加appsettings.json 文件
    {
      "person": {
        "name": "XSpringSun",
        "age": 18
      }
    }
    (3). 使用json提供程序读取json配置new一个ConfigurationBuilder,添加json配置,AddJsonFile是在包中的IConfigurationBuilder扩展方法,其它配置提供程序也是用这种扩展方法实现。
            static void Main(string[] args)
            {
                IConfiguration configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json")
                    .Build();
                Console.WriteLine(configuration["person:name"]);
                Console.WriteLine(configuration["person:age"]);
                Console.WriteLine("Hello, World!");
                Console.ReadLine();
            }

    20221103084444029.png

    20221103084444029.png


    可以看到已经取到json配置文件中的值了,配置值可以包含分层数据。 分层对象使用配置键中的 : 分隔符表示。在下面的调试对象中我们可以看到实际configuration的Providers 提供程序数组有一个值,就是我们的JsonConfigurationProvider,并且JsonConfigurationProvider里面已经读取了json的数据存储在Data数组中。
    对于如上几行代码干了什么呢:
  • 将 ConfigurationBuilder 实例化(new ConfigurationBuilder)。
  • 添加 "appsettings.json" 文件,由 JSON 配置提供程序识别(AddJsonFile("appsettings.json"))。
  • 使用 configuration 实例获取所需的配置
    三、选项模式
    这样已经实现json进行配置读取,但是取值的方式似乎和以前没什么太大变法,所以.net提供了选项模式,选项模式就是使用类来提供对相关设置组的强类型访问。
    我们创建一个Config类用来转换json:
    namespace ConfigDemo
    {
        public class Config
        {
            public Person? person { get; set; }
        }
        public class Person {
            public string? name { get; set; }
            public int age { get; set; }
        }
    }
    绑定配置
    IConfiguration configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json")
                    .Build();
                Config options = new Config();
                ConfigurationBinder.Bind(configuration, options);
                Person person = configuration.GetSection("person").Get();
                Console.WriteLine(options.person.name);
                Console.WriteLine(options.person.age);
                Console.WriteLine("-----------GetSection获取-------------");
                Console.WriteLine(person.name);
                Console.WriteLine(person.age);

    20221103084444030.png

    20221103084444030.png


    用了两种方式获取配置,第一种使用ConfigurationBinder.Bind()将整个配置绑定到对象Config上,另外一种是使用IConfiguration的GetSection().Get()并返回指定的类型。两种方式都可以使用,看实际需求和用途。

    四、选项依赖注入
    在控制台程序中我们引用DI注入包,然后演示下如何进行配置的注入。关于DI和IOC不清楚的看我上篇文章.net 温故知新:【7】IOC控制反转,DI依赖注入
  • 新建一个测试类TestOptionDI
        public class TestOptionDI
        {
            private readonly IOptionsSnapshot _options;
            public TestOptionDI(IOptionsSnapshot options)
            {
                _options = options;
            }
            public void Test()
            {
                Console.WriteLine("DI测试输出:");
                Console.WriteLine($"姓名:{_options.Value.person.name}");
                Console.WriteLine($"年龄:{_options.Value.person.age}");
            }
        }
    在测试类中我们使用IOptionsSnapshot接口作为依赖注入,还有其它不同定义的接口用来配置注入,关于选项接口:。

    20221103084444031.png

    20221103084444031.png


    不同接口可以配合读取配置的不同方式起作用,IOptionsSnapshot接口可以在配置文件改变后不同作用域进行刷新配置。接着我们修改main方法,引入DI,并将AddJsonFile方法的参数reloadOnChange设置为true,optional参数是否验证文件存在,建议开发时都设置为true,这样如果文件有问题会进行报错。
    注入配置这句services.AddOptions().Configure(e=>configuration.Bind(e))是关键,通过容器调用AddOptions方法注册,然后Configure方法里面是一个委托方法,该委托的作用就是将配置的信息绑定到Config类型的参数e上。注册到容器的泛型选项接口,这样在TestOptionDI类构造函数注入就能注入IOptionsSnapshot了,这里有点绕。
            static void Main(string[] args)
            {
                IConfiguration configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json",optional:true,reloadOnChange:true)
                    .Build();
                //IServiceCollection 服务
                ServiceCollection services = new ServiceCollection();
                //注入配置
                services.AddOptions().Configure(e=>configuration.Bind(e));
                //注入TestOptionDI
                services.AddScoped();
                using (var provider = services.BuildServiceProvider())
                {
                    //获取服务
                    var testOption = provider.GetRequiredService();
                    testOption.Test();
                }
                Console.ReadLine();
            }

    20221103084444032.png

    20221103084444032.png


    为了测试IOptionsSnapshot接口在不同作用域会刷新配置,我们修改下main方法,用一个while循环在ReadLine时修改json文件值,不同的Scope里进行打印。
                using (var provider = services.BuildServiceProvider())
                {
                    while (true)
                    {
                        using (var scope = provider.CreateScope())
                        {
                            //获取服务
                            var testOption = scope.ServiceProvider.GetRequiredService();
                            testOption.Test();
                        }
                        Console.ReadLine();
                    }
                }

    20221103084444033.png

    20221103084444033.png


    这个功能在web中使用很方便,因为框架的一次请求就是一个作用域,所以我们修改了配置,下次请求就能生效了,而不用重启服务。

    五、其它配置
    如最开始所说,不仅能配置json文件,由于各种提供程序,还可以配置其它的,但是根据配置的顺序会进行覆盖。我们只添加一个环境变量配置演示下:
    首先添加提供程序包:Install-Package Microsoft.Extensions.Configuration.EnvironmentVariables。
    然后添加环境变量配置代码AddEnvironmentVariables():
    IConfiguration configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json",optional:true,reloadOnChange:true)
                    .AddEnvironmentVariables()
                    .Build();
    在VS中配置临时环境变量

    20221103084444034.png

    20221103084444034.png


    这里有个扁平化配置,就是表示层级用冒号person:age

    20221103084444035.png

    20221103084444035.png


    六、托管模式
    对于web项目我们没有进行这么多操作它是怎么配置的呢,其实框架已经自动帮我们做了,其它非web项目也可以使用这种托管模式,在Microsoft.Extensions.Hosting 包中,只需要使用简单的代码就能配置好。
    IHost host = Host.CreateDefaultBuilder(args).Build();
    await host.RunAsync();
    其加载配置的优先级:

    20221103084444036.png

    20221103084444036.png


    通过分析我们对整个配置如何运行的机制有了一个大体的了解,如果想详细了解托管模式的还是建议看官方文档:.NET配置
    以上就是.NET 中配置从xml转向json方法示例详解的详细内容,更多关于.NET配置xml转向json的资料请关注知鸟论坛其它相关文章!
  • 回复

    使用道具 举报

    发表于 2023-6-29 20:01:30 | 显示全部楼层
    伊索谗言 2023-6-29 20:01:30 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    回复

    使用道具 举报

    发表于 2023-6-30 00:30:08 | 显示全部楼层
    贺老师 2023-6-30 00:30:08 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-30 01:19:54 | 显示全部楼层
    麻辣鸡翅 2023-6-30 01:19:54 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    回复

    使用道具 举报

    发表于 2023-6-30 21:57:29 | 显示全部楼层
    123456865 2023-6-30 21:57:29 看全部
    其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
    回复

    使用道具 举报

    发表于 2023-6-30 23:59:00 | 显示全部楼层
    123456833 2023-6-30 23:59:00 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    发表于 2023-7-4 02:22:41 | 显示全部楼层
    术数古籍专卖疤 2023-7-4 02:22:41 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    回复

    使用道具 举报

    发表于 2023-7-5 06:09:50 | 显示全部楼层
    墙和鸡蛋 2023-7-5 06:09:50 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    回复

    使用道具 举报

    发表于 2023-7-6 02:48:51 | 显示全部楼层
    戏做顿 2023-7-6 02:48:51 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    回复

    使用道具 举报

    发表于 2023-7-6 02:50:54 | 显示全部楼层
    丁侦球 2023-7-6 02:50:54 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    • 您可能感兴趣
    点击右侧快捷回复 【请勿灌水】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| SiteMap| 小黑屋| 知鸟论坛
    联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表