前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Core开发实战(第14课:自定义配置数据源:低成本实现定制化配置方案)--学习笔记

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

作者头像
郑子铭
发布2021-01-13 15:24:24
3660
发布2021-01-13 15:24:24
举报

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

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

扩展步骤

1、实现 IConfigurationSource

2、实现 IConfigurationProvider

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

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

首先定义一个 MyConfigurationSource

代码语言:javascript
复制
namespace ConfigurationCustom
{
    class MyConfigurationSource : IConfigurationSource
    {
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new MyConfigurationProvider();
        }
    }
}

接着是 MyConfigurationProvider

代码语言:javascript
复制
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 注入进来

代码语言:javascript
复制
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();
        }
    }
}

启动程序,输出如下:

代码语言:javascript
复制
lastTime:2020/3/1 22:39:36

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

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

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

定义一个扩展方法 AddMyConfiguration

代码语言:javascript
复制
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 的类是不能被引用的,这样就意味着只需要暴露一个扩展方法,而不需要暴露具体的配置源的实现

代码语言:javascript
复制
class MyConfigurationProvider : ConfigurationProvider

如何使用呢,其实很简单

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

代码语言:javascript
复制
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();
        }
    }
}

启动程序,输出如下:

代码语言:javascript
复制
lastTime:2020/3/1 22:55:11

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

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

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

代码语言:javascript
复制
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();
        }
    }
}

启动程序,输出如下:

代码语言:javascript
复制
开始了
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 环境下面,就可以有完善的配置管理解决方案

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 14 | 自定义配置数据源:低成本实现定制化配置方案
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档