.NET Core开发实战课程备忘(9) -- 自定义配置数据源:低成本实现定制配置方案

拓展步骤

  • 实现IConfigurationSource
  • 实现IConfigurationProvider
  • 实现AddXXX扩展方法

代码实现

创建项目

创建名字为ConfigurationCustomDemo控制台应用,通过nuget引入以下两个包:

1
2
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Abstractions

创建自定义数据源Provider

创建MyConfigurationProvider,继承ConfigurationProvider这个抽象类,调用基类的OnReload方法能触发重新加载配置,这里因为要自动修改和触发配置,所以这个类里用了Timer对象来模拟配置变化的操作,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Timers;
using Microsoft.Extensions.Configuration;

namespace ConfigurationCustomDemo
{
internal class MyConfigurationProvider:ConfigurationProvider
{
private 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);
}

void Load(bool reload)
{
this.Data["lastTime"] = DateTime.Now.ToString();
if (reload)
{
base.OnReload();
}
}
}
}

创建自定义数据源Source

创建MyConfigurationSource,实现IConfigurationSource接口,在Build方法直接返回上面创建的Provider,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
using Microsoft.Extensions.Configuration;

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

创建IConfigurationBuilder扩展方法

可以看到上面两个类的都是用internal的访问修饰符,这是因为一般在ProviderSource都是通过拓展方法来调用,而不会将自己直接暴露被调用者,所以接下来要创建一个IConfigurationBuilder的扩展方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
using Microsoft.Extensions.Configuration;

namespace ConfigurationCustomDemo
{
public static class MyConfigurationBuilderExtension
{
public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder)
{
builder.Add(new MyConfigurationSource());
return builder;
}
}
}

引用自定义配置源并监听配置源变化

Program.Main方法修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;

namespace ConfigurationCustomDemo
{
class Program
{
static void Main(string[] args)
{
var builder = new ConfigurationBuilder();
builder.AddMyConfiguration();
var configurationRoot = builder.Build();

ChangeToken.OnChange(() => configurationRoot.GetReloadToken(), () =>
{
var lastTime = configurationRoot["lastTime"];
Console.WriteLine($"lastTime={lastTime}");
Console.WriteLine("======");
});

Console.ReadKey();
}
}
}

运行代码,可以看到控制台3秒钟打印一次当前时间的效果