Biwen.Settings添加对IConfiguration&IOptions的集成支持
Biwen.Settings 是一个简易的配置项管理模块,主要的作用就是可以校验并持久化配置项,比如将自己的配置存储到数据库中,JSON文件中等
使用上也是很简单,只需要在服务中注入配置即可,
比如我们有一个GithubSetting的配置项,我们只需要定义好对象然后注入到Service中即可:
[Description("Github配置")]
public class GithubSetting : ValidationSettingBase<GithubSetting>
{
[Description("Github用户名")]
public string? UserName { get; set; } = "vipwan";
[Description("Github仓库")]
public string? Repository { get; set; } = "Biwen.Settings";
[Description("Github Token")]
public string? Token { get; set; } = "";
/// <summary>
/// 短名称
/// </summary>
public override string? SettingName => this.GetType().Name;
public GithubSetting()
{
//验证规则
RuleFor(x => x.UserName).NotEmpty().Length(3, 128);
RuleFor(x => x.Repository).NotNull().NotEmpty().Length(3, 128);
RuleFor(x => x.Token).NotNull().NotEmpty().Length(3, 128);
}
}
@inject GithubSetting GithubSetting;//直接对象注入
尽管这样已经足够好用且便捷,但是对于习惯了使用IConfiguration和IOptions的朋友来说还是有些不习惯,其实实现对IConfiguration的支持还是很简单的,实现一下IConfigurationProvider即可,我们来动手实现一个名为BiwenSettingConfigurationProvider的Provider:
internal class Events
{
/// <summary>
/// Channel队列
/// </summary>
public static readonly Channel<(bool IsChanged, string? SettingName)> ConfigrationChangedChannel = Channel.CreateUnbounded<(bool IsChanged, string? SettingName)>();
}
internal sealed class BiwenSettingConfigurationSource(bool autoRefresh = true) : IConfigurationSource
{
public IConfigurationProvider Build(IConfigurationBuilder builder) => new BiwenSettingConfigurationProvider(autoRefresh);
}
internal class BiwenSettingConfigurationProvider : ConfigurationProvider, IDisposable, IAsyncDisposable
{
public BiwenSettingConfigurationProvider(bool autoRefresh)
{
if (Settings.ServiceRegistration.ServiceProvider is null)
{
throw new BiwenException("必须首先注册Biwen.Setting模块,请调用:services.AddBiwenSettings()");
}
if (autoRefresh)
{
StartAlertAsync(cts.Token);
}
}
private CancellationTokenSource cts = new();
/// <summary>
/// 使用Channel通知配置变更,如果有事件更新则重新加载
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StartAlertAsync(CancellationToken cancellationToken)
{
_ = Task.Run(async () =>
{
while (!cancellationToken.IsCancellationRequested)
{
_ = await Events.ConfigrationChangedChannel.Reader.ReadAsync(cancellationToken);
Load();
//通知配置变更
OnReload();
}
}, cancellationToken);
return Task.CompletedTask;
}
//从SettingManager中加载配置项
public override void Load()
{
Dictionary<string, string?> dics = [];
using var scope = Settings.ServiceRegistration.ServiceProvider.CreateScope();
var settingManager = scope.ServiceProvider.GetRequiredService<ISettingManager>();
var settings = settingManager.GetAllSettings()!;
foreach (var setting in settings)
{
if (setting.SettingContent is null) continue;
if (JsonNode.Parse(setting.SettingContent) is not JsonObject json) continue;
foreach (var item in json)
{
dics.TryAdd($"{setting.SettingName}:{item.Key}", item.Value?.ToString());
}
}
Data = dics;
}
public void Dispose()
{
cts.Cancel();
Events.ConfigrationChangedChannel.Writer.Complete();
}
public ValueTask DisposeAsync()
{
cts.Cancel();
Events.ConfigrationChangedChannel.Writer.Complete();
return ValueTask.CompletedTask;
}
}
内部通过Channel实现变更通知,
internal class ConfigurationMediratorDoneHandler(ILogger<ConfigurationMediratorDoneHandler> logger) : IMediratorDoneHandler
{
public Task OnPublishedAsync<T>(T @event) where T : ISetting, new()
{ Events.ConfigrationChangedChannel.Writer.TryWrite((true, typeof(T).Name));
logger.LogInformation($"Setting Changed: {typeof(T).Name},并通知Configuration刷新!");
return Task.CompletedTask;
}
}
然后老规矩我们扩展一下IServiceCollection:
public static class ServiceRegistration
{
internal static IServiceCollection AddBiwenSettingConfiguration(this IServiceCollection services)
{
//ConfigurationMediratorDoneHandler
services.AddSingleton<IMediratorDoneHandler, ConfigurationMediratorDoneHandler>();
return services;
}
/// <summary>
/// 提供对IConfiguration,IOptions的支持
/// </summary>
/// <param name="manager"></param>
/// <param name="autoRefresh"></param>
/// <returns></returns>
public static ConfigurationManager AddBiwenSettingConfiguration(
this ConfigurationManager manager, IServiceCollection serviceDescriptors, bool autoRefresh = true)
{
var sp = Settings.ServiceRegistration.ServiceProvider ?? throw new BiwenException("必须首先注册Biwen.Setting模块,请调用:services.AddBiwenSettings()");
//添加订阅
if (autoRefresh)
{
serviceDescriptors.AddBiwenSettingConfiguration();
}
IConfigurationBuilder configBuilder = manager;
configBuilder.Add(new BiwenSettingConfigurationSource(autoRefresh));
var settings = ASS.InAllRequiredAssemblies.ThatInherit(typeof(ISetting)).Where(x => x.IsClass && !x.IsAbstract).ToList();
//注册ISetting
settings.ForEach(x =>
{
//IOptions DI
manager?.GetSection(x.Name).Bind(GetSetting(x, sp));
});
return manager;
}
static object GetSetting(Type x, IServiceProvider sp)
{
var settingManager = sp.GetRequiredService<ISettingManager>();
var cache = sp.GetRequiredService<IMemoryCache>();
//使用缓存避免重复反射
var md = cache.GetOrCreate($"GenericMethod_{x.FullName}", entry =>
{
MethodInfo methodLoad = settingManager.GetType().GetMethod(nameof(settingManager.Get))!;
MethodInfo generic = methodLoad.MakeGenericMethod(x);
return generic;
});
return md!.Invoke(settingManager, null)!;
}
}
最后在启动时调用AddBiwenSettingConfiguration扩展即可
builder.Configuration.AddBiwenSettingConfiguration(builder.Services, true);
最后按下面的形式注册就可以了:
@inject GithubSetting GithubSetting;//直接对象注入
@inject IOptions<GithubSetting> IOP; //通过IOptions注入
@inject IConfiguration Configuration;//IConfiguration
...
源代码我发布到了GitHub,欢迎star! https://github.com/vipwan/Biwen.Settings
https://github.com/vipwan/Biwen.Settings/tree/master/Biwen.Settings/Extensions/Configuration
Biwen.Settings添加对IConfiguration&IOptions的集成支持的更多相关文章
- Webstorm添加新建.vue文件功能并支持高亮vue语法和es6语法
转载:https://blog.csdn.net/qq_33008701/article/details/56486893 Webstorm 添加新建.vue文件功能并支持高亮vue语法和es6语法 ...
- 一般源码安装添加的GD库 是不支持 jpeg 格式的图片的
一般源码安装添加的GD库 是不支持 jpeg 格式的图片的,只支持如下格式 GD Support enabled GD Version bundled (2.0.34 compatible) GIF ...
- 为 WPF 程序添加 Windows 跳转列表的支持
原文:为 WPF 程序添加 Windows 跳转列表的支持 Windows 跳转列表是自 Windows 7 时代就带来的功能,这一功能是跟随 Windows 7 的任务栏而发布的.当时应用程序要想用 ...
- sublime使用技巧之添加到右键菜单、集成VI
熟悉开发工具,减少多余的操作流程有助于提高开发效率,而Sublime Text 2是sublime产品的经典版本,因此本文基于Sublime Text 2讲解sublime的使用技巧. VI的主要作用 ...
- 为Github仓库添加Github Actions实现持续集成: Android apk自动编译发布以及github pages同步推送coding.net
内容转载自我的博客 目录 说明 1. 编写Android项目的CI配置文件 2. 编写Jekyll项目的CI配置文件 2.1 配置coding.net 2.2 配置github 2.3 自动部署到co ...
- [OIDC in Action] 3. 基于OIDC(OpenID Connect)的SSO(添加Github OAuth 2.0的支持)
在上上一篇基于OIDC的SSO的登录页面的截图中有出现QQ登录的地方.这个其实是通过扩展OIDC的OpenID Provider来实现的,OpenID Provider简称OP,OP是OIDC的一个很 ...
- 自己动手为Spark 2.x添加ALTER TABLE ADD COLUMNS语法支持
SparkSQL从2.0开始已经不再支持ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment], .. ...
- Webstorm 添加新建.vue文件功能并支持高亮vue语法和es6语法
添加新建.vue文件功能 ①Webstorm 右上角File-Plugins 搜索vue如果没有就去下载 点击serch in repositories ②点击安装vue.js ③安装成功后点击右下角 ...
- springboot添加对listener,servlet,filter的支持
比较常用的方式就是使用注解来添加对 监听器,过滤器,servlet的支持. 1.首先在启动类上添加 @ServletComponentScan 开启 对监听器,过滤器,servlet的注解扫描. ...
- 如果给IIS添加防火墙入站配置,支持外部或者局域网访问
背景简介 也许你试着在本机IIS运行了一些网站,但是奇怪的是,同网络的终端却无法访问你,这时候极有可能被防火墙拦截了,所以我们要找到正确的姿势来开启魔法了. 找到入站规则设置 不管你是Win7还是Wi ...
随机推荐
- Mogdb - 安装报错Failed to encrypt the password for databaseError
Mogdb - 安装报错 Failed to encrypt the password for databaseError 本文出处:https://www.modb.pro/db/418363 版本 ...
- HarmonyOS智能座舱体验是怎样炼成的?立即查看
原文链接:https://mp.weixin.qq.com/s/AGY2hAeXngtRrZFk0FXe5g,点击链接查看更多技术内容: 随着AITO问界M5热卖以及M7.M5 EV版本的陆续交付,A ...
- Python根据主播直播时间段判定订单销售额归属
写在前面:最近在群里看到一个这样的直播电商的场景觉得还是挺有趣的,于是就想用Python来实现. 需求描述:根据主播直播时间段结合销售订单的付款时间判断所属销售的归属 生成主播在线直播时间段数据 fr ...
- Unable to determine application id: com.android.tools.idea.run.ApkProvisionException: No outputs for the main artifact of variant: debug
前言 遇到这种情况极大可能属于gradle 与 android studio版本不匹配的情况. 因为我是在升级android studio遇到的这个问题. 方法 一个方法是:降低android stu ...
- 力扣20(java)-有效的括号(简单)
题目: 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合.左括号必须以正确的顺序闭合.每个右括 ...
- 15M安装包就能玩《原神》,带你了解云游戏背后的技术秘密
简介:对于大多数玩家来说,云游戏已经不是一个陌生的概念,它经常和秒玩.不吃设备.大屏临场感.上手门槛低.真香等字眼一起出现在评论留言区.的确,对于既想尝试高品质游戏大作又不想一直卷装备的玩家来说,云游 ...
- 云效DevOps实践-如何基于云效实现测试自动化集成和分析
简介: 对于现代软件研发来说,持续.快速.高质量.低风险地交付需求特性,是业务对研发的主要诉求.而要做到这一点,除了要有良好的架构设计.卓越的工程能力,快速可靠的测试反馈也是其非常重要的一环,达到这一 ...
- 面向B端算法实时业务支撑的工程实践
简介:在营销场景下,算法同学会对广告主提供个性化的营销工具,帮助广告主更好的精细化营销,在可控成本内实现更好的ROI提升.我们在这一段时间支持了多个实时业务场景,比如出价策略的实时化预估.关键词批量服 ...
- 代码安全无忧—云效Codeup代码加密技术发展之路
简介: 从代码服务及代码安全角度出发,看看云效代码加密技术如何解决这一问题 代码数据存在云端,如何保障它的安全? 部分企业管理者对于云端代码托管存在一丝担心:我的代码存在云端服务器,会不会被泄露? 接 ...
- 获国际架构顶会ATC2021最佳论文!Fuxi2.0去中心化的调度架构详解
简介: 近日,在国际体系架构顶会USENIX ATC2021上,阿里云飞天伏羲团队与香港中文大学合作的一篇论文<Scaling Large Production Clusters with Pa ...