|
实现自定义配置源至少需要添加如下成员:
- 实现IConfigurationSource接口的配置源;
- 实现IConfigurationProvider接口或虚基类ConfigurationProvider的配置提供程序;
- 添加配置源的IConfigurationBuilder扩展方法;
如自定义一个TXT文本文件配置源:
添加配置源
配置源负责创建配置提供程序,以及监听文件修改。监听文件修改可以使用FileSystemWatcher,通过监听Changed事件监听配置文件的修改。使用ConfigurationReloadToken作为IChangeToken,当监听到文件修改时调用取消令牌的取消操作,进而通知订阅者文件已更改。- public class TxtConfigurationSource : IConfigurationSource, IDisposable
- {
- private FileSystemWatcher? _fileWatcher;
- private ConfigurationReloadToken _reloadToken;
- public TxtConfigurationSource(string path, bool reloadOnChange = true)
- {
- FilePath = path;
- ReloadOnChange = reloadOnChange;
- _fileWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory());
- _fileWatcher.Filter = "*.txt";
- _fileWatcher.EnableRaisingEvents = true;
- _fileWatcher.Changed += _fileWatcher_Changed;
- _reloadToken = new ConfigurationReloadToken();
- }
- private void _fileWatcher_Changed(object sender, FileSystemEventArgs e)
- {
- if (e.FullPath != FilePath)
- return;
-
- if (_reloadToken.HasChanged)
- return;
- // 触发事件
- ConfigurationReloadToken previousToken = Interlocked.Exchange(ref _reloadToken,
- new ConfigurationReloadToken());
- previousToken.OnReload();
- }
- public bool ReloadOnChange { get; set; }
- public string FilePath { get; set; }
- public IConfigurationProvider Build(IConfigurationBuilder builder)
- {
- return new TxtConfigurationProvider(this);
- }
- public IChangeToken GetChangeToken() => _reloadToken;
- public void Dispose() => Dispose(true);
- protected virtual void Dispose(bool disposing)
- {
- _fileWatcher?.Dispose();
- }
- }
复制代码 添加配置提供程序
配置提供程序负责加载配置文件,并订阅配置源中的配置修改事件。通过ChangeToken.OnChange()方法进行事件订阅,当监听到文件改变时,重新加载文件:- public class TxtConfigurationProvider : ConfigurationProvider, IDisposable
- {
- private readonly IDisposable _changeTokenRegistration;
- public TxtConfigurationProvider(TxtConfigurationSource source)
- :base()
- {
- Source = source ?? throw new ArgumentNullException(nameof(source));
- if (Source.ReloadOnChange)
- {
- _changeTokenRegistration = ChangeToken.OnChange(
- () => Source.GetChangeToken(),
- () =>
- {
- Thread.Sleep(300);
- Load();
- });
- }
- }
- public TxtConfigurationSource Source { get; }
- public override void Load()
- {
- if (!File.Exists(Source.FilePath))
- return;
- else
- {
- Data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- var lines = File.ReadAllLines(Source.FilePath);
- foreach (var line in lines)
- {
- var array = line.Replace(":", ":").Split(':');
- if (array.Length < 2)
- continue;
- Data.Add(line.Substring(0, line.LastIndexOf(':')), array.Last());
- }
- }
- OnReload();
- }
- public void Dispose() => Dispose(true);
- protected virtual void Dispose(bool disposing)
- {
- _changeTokenRegistration?.Dispose();
- }
- }
复制代码 添加配置源扩展方法
添加IConfigurationBuilder扩展方法,方便将自定义配置源添加到IConfigurationBuilder中:- public static IConfigurationBuilder AddTxtFile(this IConfigurationBuilder builder,
- string path, bool reloadOnChange)
- {
- if (builder == null)
- throw new ArgumentNullException(nameof(builder));
- if (string.IsNullOrEmpty(path))
- throw new ArgumentException($"文件不能为空:{nameof(path)}");
- return builder.Add(new TxtConfigurationSource(path, reloadOnChange));
- }
复制代码 使用
首先通过扩展方法添加配置源,调用IConfigurationBuilder.Build()方法后即可通过IConfiguration获取配置项。通过ChangeToken.OnChange()方法订阅配置修改事件。- using ConfigurationTest;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.Primitives;
- IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
- .AddTxtFile(Path.Combine(Directory.GetCurrentDirectory(), "config.txt"), reloadOnChange: true);
- // 通过IConfiguration直接读取指定配置
- IConfiguration configuration = configurationBuilder.Build();
- Console.WriteLine($"FileProvider:Source:{configuration.GetSection("FileProvider:Source").Value}");
- Console.WriteLine($"Provider:{configuration["FileProvider:Provider"]}");
- Console.WriteLine();
- // 通过绑定选项获取配置
- FileProviderOptions fileProviderOptions = new FileProviderOptions();
- configuration.GetSection("FileProvider").Bind(fileProviderOptions);
- Console.WriteLine($"FileProvider.Source = {fileProviderOptions.Source}");
- Console.WriteLine($"FileProvider.Provider = {fileProviderOptions.Provider}");
- Console.WriteLine();
- // 监听配置修改
- var disable = ChangeToken.OnChange(() => configuration.GetReloadToken(),
- () =>
- {
- foreach (var section in configuration.GetChildren())
- {
- PrintAllConfig(section);
- }
-
- Console.WriteLine();
- Console.WriteLine("按“q”退出");
- });
- Console.WriteLine("按“q”退出");
- while (Console.ReadLine() != "q")
- {
- }
- disable.Dispose();
- void PrintAllConfig(IConfigurationSection config)
- {
- var sections = config.GetChildren();
- if(sections == null || sections.Count() == 0)
- Console.WriteLine($"{config.Key} : {config.Value}");
- else
- {
- foreach (var section in sections)
- {
- PrintAllConfig(section);
- }
- }
- }
- class FileProviderOptions
- {
- public string Source { get; set; }
- public string Provider { get; set; }
- }
复制代码- // config.txt
- FileProvider:Source:TxtSource
- FileProvider:Provider:TxtProvider
复制代码 来源:https://www.cnblogs.com/louzixl/archive/2023/12/02/17871159.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|