欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Biwen.Settings如何添加對IConfiguration&IOptions的集成支持

 更新時間:2024年05月22日 09:38:07   作者:萬雅虎  
Biwen.Settings?是一個簡易的配置項管理模塊,主要的作用就是可以校驗并持久化配置項,比如將自己的配置存儲到數(shù)據(jù)庫中,JSON文件中等,這篇文章主要介紹了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í)慣了使用IConfigurationIOptions的朋友來說還是有些不習(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&amp;IOptions的集成支持的文章就介紹到這了,更多相關(guān)Biwen.Settings IConfiguration&amp;IOptions集成內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論