Biwen.Settings如何添加對(duì)IConfiguration&IOptions的集成支持
Biwen.Settings 是一個(gè)簡(jiǎn)易的配置項(xiàng)管理模塊,主要的作用就是可以校驗(yàn)并持久化配置項(xiàng),比如將自己的配置存儲(chǔ)到數(shù)據(jù)庫(kù)中,JSON文件中等
使用上也是很簡(jiǎn)單,只需要在服務(wù)中注入配置,
比如我們有一個(gè)GithubSetting的配置項(xiàng),我們只需要定義好對(duì)象然后注入到Service中即可:
[Description("Github配置")]
public class GithubSetting : ValidationSettingBase<GithubSetting>
{
[Description("Github用戶名")]
public string? UserName { get; set; } = "vipwan";
[Description("Github倉(cāng)庫(kù)")]
public string? Repository { get; set; } = "Biwen.Settings";
[Description("Github Token")]
public string? Token { get; set; } = "";
public GithubSetting()
{
//驗(yàn)證規(guī)則
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;//直接對(duì)象注入
盡管這樣已經(jīng)足夠好用且便捷,但是對(duì)于習(xí)慣了使用IConfiguration和IOptions的朋友來(lái)說(shuō)還是有些不習(xí)慣,其實(shí)實(shí)現(xiàn)對(duì)IConfiguration的支持還是很簡(jiǎn)單的,實(shí)現(xiàn)一下IConfigurationProvider即可,我們來(lái)動(dòng)手實(shí)現(xiàn)一個(gè)名為BiwenSettingConfigurationProvider的Provider:
internal class Events
{
/// <summary>
/// Channel隊(duì)列
/// </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("必須首先注冊(cè)Biwen.Setting模塊,請(qǐng)調(diào)用: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中加載配置項(xiàng)
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;
}
}內(nèi)部通過(guò)Channel實(shí)現(xiàn)變更通知,
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;
}
}然后老規(guī)矩我們擴(kuò)展一下IServiceCollection:
public static class ServiceRegistration
{
internal static IServiceCollection AddBiwenSettingConfiguration(this IServiceCollection services)
{
//ConfigurationMediratorDoneHandler
services.AddSingleton<IMediratorDoneHandler, ConfigurationMediratorDoneHandler>();
return services;
}
/// <summary>
/// 提供對(duì)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("必須首先注冊(cè)Biwen.Setting模塊,請(qǐng)調(diào)用: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();
//注冊(cè)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>();
//使用緩存避免重復(fù)反射
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)!;
}
}最后在啟動(dòng)時(shí)調(diào)用AddBiwenSettingConfiguration擴(kuò)展即可
builder.Configuration.AddBiwenSettingConfiguration(builder.Services, true);
最后按下面的形式注冊(cè)就可以了:
@inject GithubSetting GithubSetting;//直接對(duì)象注入 @inject IOptions<GithubSetting> IOP; //通過(guò)IOptions注入 @inject IConfiguration Configuration;//IConfiguration ...
源代碼我發(fā)布到了GitHub,歡迎star!
https://github.com/vipwan/Biwen.Settings
https://github.com/vipwan/Biwen.Settings/tree/master/Biwen.Settings/Extensions/Configuration
到此這篇關(guān)于Biwen.Settings添加對(duì)IConfiguration&IOptions的集成支持的文章就介紹到這了,更多相關(guān)Biwen.Settings IConfiguration&IOptions集成內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用DataAdapter填充多個(gè)表(利用DataRelation)的實(shí)例代碼
使用DataAdapter填充多個(gè)表(利用DataRelation)的實(shí)例代碼,需要的朋友可以參考一下2013-03-03
ASP.NET Core 導(dǎo)入導(dǎo)出Excel xlsx 文件實(shí)例
本篇文章主要介紹了ASP.NET Core 導(dǎo)入導(dǎo)出Excel xlsx 文件,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12
ASP.NET MVC Webuploader實(shí)現(xiàn)上傳功能
這篇文章主要為大家詳細(xì)介紹了ASP.NET MVC Webuploader實(shí)現(xiàn)上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
ASP.NET中利用DataList實(shí)現(xiàn)圖片無(wú)縫滾動(dòng) 實(shí)例分享
這個(gè)問(wèn)題之前也困擾我,后來(lái)解決了,拿出來(lái)分享下,以后用也方便,代碼很容易看懂,不多說(shuō)什么了2013-06-06
總結(jié)ASP.NET C#中經(jīng)常用到的13個(gè)JS腳本代碼
本文總結(jié)了ASP.NET C#在實(shí)際開(kāi)發(fā)過(guò)程中13個(gè)JS腳本代碼,方便大家在開(kāi)發(fā)中使用,希望對(duì)大家有用。2016-04-04
CKEditor與dotnetcore實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了CKEditor與dotnetcore實(shí)現(xiàn)圖片上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
.NET Core WebApi中如何實(shí)現(xiàn)多態(tài)數(shù)據(jù)綁定實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于.NET Core WebApi中如何實(shí)現(xiàn)多態(tài)數(shù)據(jù)綁定的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),并給出來(lái)完整的實(shí)例代碼,需要的朋友可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
手動(dòng)把a(bǔ)sp.net的類(lèi)生成dll文件的方法
當(dāng)我們?cè)陂_(kāi)發(fā)的時(shí)候,有時(shí)會(huì)將一些方法封裝起來(lái)供別人調(diào)用,下面就是一種生成DLL的方法.2009-11-11

