14 | 自定义配置数据源:低成本实现定制化配置方案

这一节讲解如何定义自己的数据源,来扩展配置框架

扩展步骤

1、实现 IConfigurationSource

2、实现 IConfigurationProvider

3、实现 AddXXX 扩展方法,用来作为注入的快捷方式

引用以下两个包:

  • Microsoft.Extensions.Configuration
  • Microsoft.Extensions.Configuration.Abstractions

首先定义一个 MyConfigurationSource

  1. namespace ConfigurationCustom
  2. {
  3. class MyConfigurationSource : IConfigurationSource
  4. {
  5. public IConfigurationProvider Build(IConfigurationBuilder builder)
  6. {
  7. return new MyConfigurationProvider();
  8. }
  9. }
  10. }

接着是 MyConfigurationProvider

  1. namespace ConfigurationCustom
  2. {
  3. // ConfigurationProvider 集成自 IConfigurationProvider
  4. class MyConfigurationProvider : ConfigurationProvider
  5. {
  6. Timer timer;
  7. public MyConfigurationProvider() : base()
  8. {
  9. // 用一个线程模拟配置发生变化,每三秒钟执行一次,告诉我们要重新加载配置
  10. timer = new Timer();
  11. timer.Elapsed += Timer_Elapsed;
  12. timer.Interval = 3000;
  13. timer.Start();
  14. }
  15. private void Timer_Elapsed(object sender, ElapsedEventArgs e) => Load(true);
  16. public override void Load() => Load(false);
  17. /// <summary>
  18. /// 加载数据
  19. /// </summary>
  20. /// <param name="reload">是否重新加载数据</param>
  21. void Load(bool reload)
  22. {
  23. // Data 表示 Key-value 数据,这是由 ConfigurationProvider 提供的一个数据承载的集合
  24. // 我们把最新的时间填充进去
  25. Data["lastTime"] = DateTime.Now.ToString();
  26. if (reload)
  27. {
  28. base.OnReload();
  29. }
  30. }
  31. }
  32. }

实际上到此扩展就已经完成了,可以通过 builder.AddXXX 这个方法来把 source 注入进来

  1. namespace ConfigurationCustom
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. var builder = new ConfigurationBuilder();
  8. builder.Add(new MyConfigurationSource());
  9. var configRoot = builder.Build();
  10. Console.WriteLine($"lastTime:{configRoot["lastTime"]}");
  11. Console.ReadKey();
  12. }
  13. }
  14. }

启动程序,输出如下:

  1. lastTime:2020/3/1 22:39:36

这里可以看到,输出最新的时间

但是如果这样去分发配置源的包的话,需要把 MyConfigurationSource

定义为 public,否则使用方式没办法引用到这个类

那么就可以通过扩展方法的方式来保障不需要暴露 ConfigSource

定义一个扩展方法 AddMyConfiguration

  1. namespace Microsoft.Extensions.Configuration
  2. {
  3. public static class MyConfigurationBuilderExtensions
  4. {
  5. public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder)
  6. {
  7. builder.Add(new MyConfigurationSource());
  8. return builder;
  9. }
  10. }
  11. }

首先把扩展方法的命名空间放在 config 的命名空间,而不是自己的命名空间,这样方便在引用的时候直接使用而无需加载具体的命名空间

另外一个可以把 Provider 定义为 internal 的,默认是 internal,如果说分发到第三方的话,internal 的类是不能被引用的,这样就意味着只需要暴露一个扩展方法,而不需要暴露具体的配置源的实现

  1. class MyConfigurationProvider : ConfigurationProvider

如何使用呢,其实很简单

只需要在 builder.Add 的时候使用 builder.AddMyConfiguration 就可以了,这样达到的效果是一样的

  1. namespace ConfigurationCustom
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. var builder = new ConfigurationBuilder();
  8. //builder.Add(new MyConfigurationSource());
  9. builder.AddMyConfiguration();
  10. var configRoot = builder.Build();
  11. Console.WriteLine($"lastTime:{configRoot["lastTime"]}");
  12. Console.ReadKey();
  13. }
  14. }
  15. }

启动程序,输出如下:

  1. lastTime:2020/3/1 22:55:11

在定义扩展的时候,都推荐这样去做,把具体实现都定义为私有的,然后通过扩展方法的方式暴露出去

刚才实际上还定义了一个 timer 来模拟配置的变更,这里可以监听一下它的变更,看是否生效

上一节讲到 ChangeToken 的方式,这里还是用 ChangeToken 的 OnChange 方法

  1. namespace ConfigurationCustom
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. var builder = new ConfigurationBuilder();
  8. builder.AddMyConfiguration();
  9. var configRoot = builder.Build();
  10. ChangeToken.OnChange(() => configRoot.GetReloadToken(), () =>
  11. {
  12. Console.WriteLine($"lastTime:{configRoot["lastTime"]}");
  13. });
  14. Console.WriteLine("开始了");
  15. Console.ReadKey();
  16. }
  17. }
  18. }

启动程序,输出如下:

  1. 开始了
  2. lastTime:2020/3/1 22:59:25
  3. lastTime:2020/3/1 22:59:28
  4. lastTime:2020/3/1 22:59:31

每个三秒钟输出一次,这说明我们定义的配置变更的通知已经生效了

MyConfigurationProvider 中我们只是通过赋值一个 DateTime 来模拟配置源

实际上可以从远程来说,比如阿波罗的配置中心,Kazoo,这些地方远程的读取配置,结合着命令行和环境变量配置,就可以完成配置中心的远程方案,意味着可以版本化的管理配置

这样子在 Docker 容器环境下面,Kubernetes 环境下面,就可以有完善的配置管理解决方案

GitHub源码链接:

https://github.com/MingsonZheng/DotNetCoreDevelopmentActualCombat/tree/main/ConfigurationCustom

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

.NET Core开发实战(第14课:自定义配置数据源:低成本实现定制化配置方案)--学习笔记的更多相关文章

  1. 2月送书福利:ASP.NET Core开发实战

    大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...

  2. [ASP.NET Core开发实战]基础篇01 Startup

    Startup,顾名思义,就是启动类,用于配置ASP.NET Core应用的服务和请求管道. Startup有两个主要作用: 通过ConfigureServices方法配置应用的服务.服务是一个提供应 ...

  3. [ASP.NET Core开发实战]开篇词

    前言 本系列课程文章主要是学习官方文档,再输出自己学习心得,希望对你有所帮助. 课程大纲 本系列课程主要分为三个部分:基础篇.实战篇和部署篇. 希望通过本系列课程,能让大家初步掌握使用ASP.NET ...

  4. [ASP.NET Core开发实战]基础篇06 配置

    配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...

  5. 【.NET Core项目实战-统一认证平台】第二章网关篇-定制Ocelot来满足需求

    [.NET Core项目实战-统一认证平台]开篇及目录索引 这篇文章,我们将从Ocelot的中间件源码分析,目前Ocelot已经实现那些功能,还有那些功能在我们实际项目中暂时还未实现,如果我们要使用这 ...

  6. ASP.NET Core应用的错误处理[3]:ExceptionHandlerMiddleware中间件如何呈现“定制化错误页面”

    DeveloperExceptionPageMiddleware中间件利用呈现出来的错误页面实现抛出异常和当前请求的详细信息以辅助开发人员更好地进行纠错诊断工作,而ExceptionHandlerMi ...

  7. .NET Core开发实战(第11课:文件配置提供程序)--学习笔记

    11 | 文件配置提供程序:自由选择配置的格式 文件配置提供程序 Microsoft.Extensions.Configuration.Ini Microsoft.Extensions.Configu ...

  8. 2、SpringBoot接口Http协议开发实战8节课(1-6)

    1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...

  9. [ASP.NET Core开发实战]基础篇03 中间件

    什么是中间件 中间件是一种装配到应用管道,以处理请求和响应的组件.每个中间件: 选择是否将请求传递到管道中的下一个中间件. 可在管道中的下一个中间件前后执行. ASP.NET Core请求管道包含一系 ...

  10. Swing应用开发实战系列之一:自定义JdbcTemplate

    笔者本人真正意义上接触编程开发是在2004年,最早用的就是VB,然后是Delphi等,后来转到.Net,中间断断续续还用过PowerBuilder等,无一例外,所研发设计的项目或系统都是WinForm ...

随机推荐

  1. element-ui实现部分引用

    1.首先安装 babel-plugin-component组件: 2.修改babel.js配置 1 module.exports = { 2 presets: [ 3 '@vue/app', 4 [' ...

  2. HOMER docker版本配置优化

    概述 HOMER是一款100%开源的针对SIP/VOIP/RTC的抓包工具和监控工具. HOMER是一款强大的.运营商级.可扩展的数据包和事件捕获系统,是基于HEP/EEP协议的VoIP/RTC监控应 ...

  3. freeswitch的3XX重定向

    概述 sip协议标准RFC3261中,对3XX重定向有明确的定义. freeswitch中如何使用3XX redirect的特性,如何落地,应用场景有哪些? 环境 centos:CentOS  rel ...

  4. 图片与Base64编码相互转换、优势分析和技术实现

    在Web开发中,图片与Base64编码的相互转换是一个非常实用的技能.图片 Base64编码是将图片文件转换为字符串格式,以便于在网络上传输和存储.本文将详细介绍图片与Base64编码的转换方法,以及 ...

  5. BFS 广搜

    HDU 2612 #include<stdio.h> #include<string.h> #include<iostream> #include<queue ...

  6. Liunx常用操作(四)-快速清空文件内容的方法(baseshell与vim)

    一.baseshell下操作 1. $ : > filename #其中的 : 是一个占位符, 不产生任何输出. 2. $ > filename 3. $ echo "" ...

  7. 解决ssh远程登录Too many authentication failures报错

    远程登录失败,报错,造成无法登录的情况,原因为:多次输入密码失败导致登录异常. 解决方案: 1.登录主机:vi /etc/ssh/sshd_config 2.找到MaxAuthTries,修改数值变大 ...

  8. java进阶(25)--泛型

    一.泛型基本概念 JDK5.0后新特性:Generic 1.不使用泛型举例

  9. SD Host控制器的系统集成

    控制器集成需求 SD Host可以从外部读取数据存储到SRAM和eFlash或者可以从内部读取数据输出到外部存储 AHB Bus slave接口用于配置 master接口作为主设备,DMA可以控制总线 ...

  10. Go-选择排序

    // SelectionSort 选择排序 // 思路: // 1. 遍历整个元素集合,将最小值取出追加到一个有序的元组 // 2. 重复遍历剩余元素集合,取出最小值追加到一个有序元组 // 选择排序 ...