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


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

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

    扩展步骤

    1、实现 IConfigurationSource

    2、实现 IConfigurationProvider

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

    源码链接:
    https://github.com/witskeeper/geektime/tree/master/samples/ConfigurationCustom

    首先定义一个 MyConfigurationSource

    namespace ConfigurationCustom
    {
        class MyConfigurationSource : IConfigurationSource
        {
            public IConfigurationProvider Build(IConfigurationBuilder builder)
            {
                return new MyConfigurationProvider();
            }
        }
    }
    

    接着是 MyConfigurationProvider

    namespace ConfigurationCustom
    {
        // ConfigurationProvider 集成自 IConfigurationProvider
        class MyConfigurationProvider : ConfigurationProvider
        {
    
            Timer timer;
    
            public MyConfigurationProvider() : base()
            {
                // 用一个线程模拟配置发生变化,每三秒钟执行一次,告诉我们要重新加载配置
                timer = new Timer();
                timer.Elapsed += Timer_Elapsed;
                timer.Interval = 3000;
                timer.Start();
            }
    
            private void Timer_Elapsed(object sender, ElapsedEventArgs e) => Load(true);
    
            public override void Load() => Load(false);
    
            /// <summary>
            /// 加载数据
            /// </summary>
            /// <param name="reload">是否重新加载数据</param>
            void Load(bool reload)
            {
                // Data 表示 Key-value 数据,这是由 ConfigurationProvider 提供的一个数据承载的集合
                // 我们把最新的时间填充进去
                Data["lastTime"] = DateTime.Now.ToString();
                if (reload)
                {
                    base.OnReload();
                }
            }
        }
    }
    

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

    namespace ConfigurationCustom
    {
        class Program
        {
            static void Main(string[] args)
            {
                var builder = new ConfigurationBuilder();
                builder.Add(new MyConfigurationSource());
    
                var configRoot = builder.Build();
                Console.WriteLine($"lastTime:{configRoot["lastTime"]}");
    
                Console.ReadKey();
            }
        }
    }
    

    启动程序,输出如下:

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

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

    但是如果这样去分发配置源的包的话,需要把 MyConfigurationSource
    定义为 public,否则使用方式没办法引用到这个类

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

    定义一个扩展方法 AddMyConfiguration

    namespace Microsoft.Extensions.Configuration
    {
        public static class MyConfigurationBuilderExtensions
        {
            public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder)
            {
                builder.Add(new MyConfigurationSource());
                return builder;
            }
        }
    }
    

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

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

    class MyConfigurationProvider : ConfigurationProvider
    

    如何使用呢,其实很简单

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

    namespace ConfigurationCustom
    {
        class Program
        {
            static void Main(string[] args)
            {
                var builder = new ConfigurationBuilder();
                //builder.Add(new MyConfigurationSource());
                builder.AddMyConfiguration();
    
                var configRoot = builder.Build();
                Console.WriteLine($"lastTime:{configRoot["lastTime"]}");
    
                Console.ReadKey();
            }
        }
    }
    

    启动程序,输出如下:

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

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

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

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

    namespace ConfigurationCustom
    {
        class Program
        {
            static void Main(string[] args)
            {
                var builder = new ConfigurationBuilder();
                builder.AddMyConfiguration();
    
                var configRoot = builder.Build();
    
                ChangeToken.OnChange(() => configRoot.GetReloadToken(), () =>
                {
                    Console.WriteLine($"lastTime:{configRoot["lastTime"]}");
                });
    
                Console.WriteLine("开始了");
                Console.ReadKey();
            }
        }
    }
    

    启动程序,输出如下:

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

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

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

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

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

    知识共享许可协议

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

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

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

  • 相关阅读:
    Hbase常用Shell命令
    Hbase的安装与基本操作
    Unity3d 游戏设计(一)井字棋
    Unity3d 二、离散仿真引擎基础
    Unity3D 一、游戏
    String StringBuffer StringBulider
    Java日志记录log4j最简明教程
    使用PinYin4j.jar将汉字转换为拼音
    线性素数筛
    求一个数的约数个数 d(n)
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/12393150.html
Copyright © 2020-2023  润新知