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;//直接对象注入

尽管这样已经足够好用且便捷,但是对于习惯了使用IConfigurationIOptions的朋友来说还是有些不习惯,其实实现对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的集成支持的更多相关文章

  1. Webstorm添加新建.vue文件功能并支持高亮vue语法和es6语法

    转载:https://blog.csdn.net/qq_33008701/article/details/56486893 Webstorm 添加新建.vue文件功能并支持高亮vue语法和es6语法 ...

  2. 一般源码安装添加的GD库 是不支持 jpeg 格式的图片的

    一般源码安装添加的GD库 是不支持 jpeg 格式的图片的,只支持如下格式 GD Support enabled GD Version bundled (2.0.34 compatible) GIF ...

  3. 为 WPF 程序添加 Windows 跳转列表的支持

    原文:为 WPF 程序添加 Windows 跳转列表的支持 Windows 跳转列表是自 Windows 7 时代就带来的功能,这一功能是跟随 Windows 7 的任务栏而发布的.当时应用程序要想用 ...

  4. sublime使用技巧之添加到右键菜单、集成VI

    熟悉开发工具,减少多余的操作流程有助于提高开发效率,而Sublime Text 2是sublime产品的经典版本,因此本文基于Sublime Text 2讲解sublime的使用技巧. VI的主要作用 ...

  5. 为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 ...

  6. [OIDC in Action] 3. 基于OIDC(OpenID Connect)的SSO(添加Github OAuth 2.0的支持)

    在上上一篇基于OIDC的SSO的登录页面的截图中有出现QQ登录的地方.这个其实是通过扩展OIDC的OpenID Provider来实现的,OpenID Provider简称OP,OP是OIDC的一个很 ...

  7. 自己动手为Spark 2.x添加ALTER TABLE ADD COLUMNS语法支持

    SparkSQL从2.0开始已经不再支持ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment], .. ...

  8. Webstorm 添加新建.vue文件功能并支持高亮vue语法和es6语法

    添加新建.vue文件功能 ①Webstorm 右上角File-Plugins 搜索vue如果没有就去下载 点击serch in repositories ②点击安装vue.js ③安装成功后点击右下角 ...

  9. springboot添加对listener,servlet,filter的支持

    比较常用的方式就是使用注解来添加对 监听器,过滤器,servlet的支持. 1.首先在启动类上添加  @ServletComponentScan  开启 对监听器,过滤器,servlet的注解扫描. ...

  10. 如果给IIS添加防火墙入站配置,支持外部或者局域网访问

    背景简介 也许你试着在本机IIS运行了一些网站,但是奇怪的是,同网络的终端却无法访问你,这时候极有可能被防火墙拦截了,所以我们要找到正确的姿势来开启魔法了. 找到入站规则设置 不管你是Win7还是Wi ...

随机推荐

  1. OpenCV一句话将彩色图片(Mat)转换为灰度

    auto in_gray=cv::imdecode(in, cv::IMREAD_GRAYSCALE);

  2. Go 语言学习:了解 const 关键字及常量声明

    如果一个变量应该有一个固定的.不能改变的值,你可以使用const关键字. const关键字将变量声明为"常量",这意味着它是不可改变和只读的. 语法 const CONSTNAME ...

  3. 大奖升级!HMS Core线上Codelabs挑战赛第3期:用3D建模构建元宇宙

    "元宇宙"概念风生水起,在AR.VR等技术构建的虚拟世界里,3D模型担当重要角色,无论是为玩家提供更丰富更真实游戏体验的3D游戏领域,还是各大电商平台正在启用并不断完善的3D虚拟购 ...

  4. Discovery直播 | 移动应用“通行证”——钥匙环,解锁管家式安全出行服务

    用户在登录环节的直接诉求是:别让我等.别让我想.别让我烦.而帐号输入.繁琐验证,以及由此带来的安全风险,总会让很多人望而却步. 如何在简化登录流程的同时保障登录凭证安全?如何帮助用户一键免密登录同一开 ...

  5. Kubernetes Pod配置:从基础到高级实战技巧

    本文深入探讨了Kubernetes Pod配置的实战技巧和常见易错点. 关注[TechLeadCloud],分享互联网架构.云服务技术的全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团 ...

  6. mysql 必知必会整理—组合查询与全文搜索[九]

    前言 简单整理一下组合查询与全文搜索. 正文 什么是组合查询,就是我们常说的交并补集. 直接上例子. 举一个例子,假如需要价格小于等于5的所有物品的一个列表,而且还想包括供应商1001和1002生产的 ...

  7. Flask、Tornado、Nginx搭建Https服务

    其实Flask可以直接用tornado部署就行: # coding=utf-8 from tornado.wsgi import WSGIContainer from tornado.httpserv ...

  8. few-shot-learning for object detection

    github  https://github.com/LiuXinyu12378/few-shot-learning-for-object-detection train.py from __futu ...

  9. 第五課-Channel Study TCP Listener & Web Service Listener

    示例描述: 我们将研究如何获取相当常见的HL7 v2消息并将其映射到自定义Web Service接口服务.在许多实际情况下,当我们要连接到HIE,EMPI,数据仓库或数据存储库时,必须这样做.此用例说 ...

  10. GaussDB SQL查询语句执行过程解析

    本文分享自华为云社区<[GaussTech第2期]GaussDB SQL查询语句执行过程解析>,作者: GaussDB 数据库. SQL于关系型数据库而言,重要性不言而喻.就像一个乐团的指 ...