Biwen.Settings如何添加對IConfiguration&IOptions的集成支持
Biwen.Settings 是一個簡易的配置項管理模塊,主要的作用就是可以校驗并持久化配置項,比如將自己的配置存儲到數(shù)據(jù)庫中,JSON文件中等
使用上也是很簡單,只需要在服務(wù)中注入配置,
比如我們有一個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; } = ""; public GithubSetting() { //驗證規(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;//直接對象注入
盡管這樣已經(jīng)足夠好用且便捷,但是對于習(xí)慣了使用IConfiguration
和IOptions
的朋友來說還是有些不習(xí)慣,其實實現(xiàn)對IConfiguration的支持還是很簡單的,實現(xiàn)一下IConfigurationProvider
即可,我們來動手實現(xiàn)一個名為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模塊,請調(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中加載配置項 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)部通過Channel實現(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ī)矩我們擴展一下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模塊,請調(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(); //注冊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)!; } }
最后在啟動時調(diào)用AddBiwenSettingConfiguration擴展即可
builder.Configuration.AddBiwenSettingConfiguration(builder.Services, true);
最后按下面的形式注冊就可以了:
@inject GithubSetting GithubSetting;//直接對象注入 @inject IOptions<GithubSetting> IOP; //通過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添加對IConfiguration&IOptions的集成支持的文章就介紹到這了,更多相關(guān)Biwen.Settings IConfiguration&IOptions集成內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用DataAdapter填充多個表(利用DataRelation)的實例代碼
使用DataAdapter填充多個表(利用DataRelation)的實例代碼,需要的朋友可以參考一下2013-03-03ASP.NET Core 導(dǎo)入導(dǎo)出Excel xlsx 文件實例
本篇文章主要介紹了ASP.NET Core 導(dǎo)入導(dǎo)出Excel xlsx 文件,非常具有實用價值,需要的朋友可以參考下。2016-12-12ASP.NET MVC Webuploader實現(xiàn)上傳功能
這篇文章主要為大家詳細(xì)介紹了ASP.NET MVC Webuploader實現(xiàn)上傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09ASP.NET中利用DataList實現(xiàn)圖片無縫滾動 實例分享
這個問題之前也困擾我,后來解決了,拿出來分享下,以后用也方便,代碼很容易看懂,不多說什么了2013-06-06總結(jié)ASP.NET C#中經(jīng)常用到的13個JS腳本代碼
本文總結(jié)了ASP.NET C#在實際開發(fā)過程中13個JS腳本代碼,方便大家在開發(fā)中使用,希望對大家有用。2016-04-04CKEditor與dotnetcore實現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了CKEditor與dotnetcore實現(xiàn)圖片上傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09.NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼
這篇文章主要給大家介紹了關(guān)于.NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),并給出來完整的實例代碼,需要的朋友可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08