设置模块

配置系统(Configuration System)是一个不错方式在应用 Startup配置,ABP提供另一种方式获取和配置应用设置

配置是一个Name-Vaule键值对,设置系统是可扩展,内置提供 user, a tenant, global and default等方式,

ISettingProvider,通常用于获取和设置设置值,常用方法:GetOrNullAsync,GetAllAsync

在IApplicationService已经属性注入

        string userName = await _settingProvider.GetOrNullAsync("Smtp.UserName");

        //Get a bool value and fallback to the default value (false) if not set.
        bool enableSsl = await _settingProvider.GetAsync<bool>("Smtp.EnableSsl");

        //Get a bool value and fallback to the provided default value (true) if not set.
        bool enableSsl = await _settingProvider.GetAsync<bool>(
            "Smtp.EnableSsl", defaultValue: true);
        
        //Get a bool value with the IsTrueAsync shortcut extension method
        bool enableSsl = await _settingProvider.IsTrueAsync("Smtp.EnableSsl");
        
        //Get an int value or the default value (0) if not set
        int port = (await _settingProvider.GetAsync<int>("Smtp.Port"));

        //Get an int value or null if not provided
        int? port = (await _settingProvider.GetOrNullAsync("Smtp.Port"))?.To<int>();

一、配置的初始化

SettingOptions有集合列表:DefinitionProviders,ValueProviders,配置方法见下

1、在模块PreConfigureServices只需实现了ISettingDefinitionProvider,自动添加到设置的定义DefinitionProviders里。是自定义配置定义的settingdefinition的方法

2、ISettingValueProvider 提供了4个自定义的获取设置值的提供方法,实现基类SettingValueProvider,分别是默认值提供者,全局值提供者,租户值提供,用户值提供;是获取提供参数的ProviderName = Global,Tenant,User(取第一个字母)给SettingStore,而providerKey分别是,null,CurrentTenant.Id?.ToString(),CurrentUser.Id.ToString()

     public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            AutoAddDefinitionProviders(context.Services);
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {          
            Configure(options =>
            {
                options.ValueProviders.Add();
                options.ValueProviders.Add();
                options.ValueProviders.Add();
                options.ValueProviders.Add();
            });
        }
private static void AutoAddDefinitionProviders(IServiceCollection services) { var definitionProviders = new List(); services.OnRegistred(context => { if (typeof(ISettingDefinitionProvider).IsAssignableFrom(context.ImplementationType)) { definitionProviders.Add(context.ImplementationType); } }); services.Configure(options => { options.DefinitionProviders.AddIfNotContains(definitionProviders); }); }

3、settingdefinition配置定义,如名字(唯一、强制属性),默认值,显示值(本地化在UI显示),描述,是否对客户端可显示,是否继承,

提供列表(掼定提供者),用户自定义属性,是否加密

4、SettingDefinitionProvider提供者,定义配置的上下文Define(ISettingDefinitionContext context),存储配置字典的定义   Dictionary 

key值为definition.Name,value值为definition。比如邮件设置的上下文  

 internal class EmailSettingProvider : SettingDefinitionProvider
    {
        public override void Define(ISettingDefinitionContext context)
        {
            context.Add(
                new SettingDefinition(EmailSettingNames.Smtp.Host, "127.0.0.1"),
                new SettingDefinition(EmailSettingNames.Smtp.Port, "25"),
                new SettingDefinition(EmailSettingNames.Smtp.UserName),
                new SettingDefinition(EmailSettingNames.Smtp.Password, isEncrypted: true), new SettingDefinition(EmailSettingNames.Smtp.Domain), new SettingDefinition(EmailSettingNames.Smtp.EnableSsl, "false"), new SettingDefinition(EmailSettingNames.Smtp.UseDefaultCredentials, "true"), new SettingDefinition(EmailSettingNames.DefaultFromAddress, "[email protected]"), new SettingDefinition(EmailSettingNames.DefaultFromDisplayName, "ABP application") ); } }

 5、在SettingDefinitionManager的构造函数,遍历Options.DefinitionProviders,填充成字典new Dictionary()

用于AbpApplicationConfigurationAppService生成所有设置字段

用于ISettingProvider,得到SettingDefinition

 public SettingDefinitionManager(
            IOptions options,
            IServiceProvider serviceProvider)
        {
            ServiceProvider = serviceProvider;
            Options = options.Value;
            SettingDefinitions = new Lazy>(CreateSettingDefinitions, true);
        }

 protected virtual IDictionary CreateSettingDefinitions()
        {
            var settings = new Dictionary();

            using (var scope = ServiceProvider.CreateScope())
            {
                var providers = Options
                    .DefinitionProviders
                    .Select(p => scope.ServiceProvider.GetRequiredService(p) as ISettingDefinitionProvider)
                    .ToList();

                foreach (var provider in providers)
                {
                    provider.Define(new SettingDefinitionContext(settings));
                }
            }
            return settings;
        }

 6、ISettingValueProviderManager,使用List Providers

public SettingValueProviderManager(
            IServiceProvider serviceProvider,
            IOptions options)
        {
            Options = options.Value;
            _lazyProviders = new Lazy>(
                () => Options
                    .ValueProviders
                    .Select(type => serviceProvider.GetRequiredService(type) as ISettingValueProvider)
                    .ToList(),
                true
            );
        }

二、ISettingProvider是提供获取设置值方法服务,其实现构造函数有options,serviceProvider,settingDefinitionManager,settingEncryptionService

ISettingValueProvider的Reverse,表明顺序是:用户》租户》全局》默认;setting.Providers是允许的提供者

       public virtual async Task GetOrNullAsync(string name)
        {
//获取属性值 var setting = SettingDefinitionManager.Get(name); var providers = Enumerable .Reverse(Providers.Value);
if (setting.Providers.Any()) { providers = providers.Where(p => setting.Providers.Contains(p.Name)); } //TODO: How to implement setting.IsInherited? var value = await GetOrNullValueFromProvidersAsync(providers, setting);
//加密 if (setting.IsEncrypted) { value = SettingEncryptionService.Decrypt(setting, value); } return value; }

  

  protected virtual async Task GetOrNullValueFromProvidersAsync(
            IEnumerable providers,
            SettingDefinition setting)
        {
//遍历对应值提供Providers,获取对应的值 foreach (var provider in providers) { var value = await provider.GetOrNullAsync(setting); if (value != null) { return value; } } return null; }

配置值的提供者ISettingValueProvider,有多个提供者,

     1)默认提供者,获取配置定义的值,即SettingDefinition.DefaultValue

     2)全局提供者,从ISettingStore获取值,ProviderName = "Global"

     3)租户提供者,从ISettingStore获取值,providerName=Tenant,providerKey=CurrentTenant.Id?.ToString()

     4)用户提供者,从ISettingStore获取值,providerName=User,providerKey=CurrentUser.Id.ToString() 

 

ISettingStore的实现在 Volo.Abp.SettingManagement,使用ISettingManagementStore得GetOrNullAsync方法

优先从获取IDistributedCache Cache 里面缓存,若没有则设置缓存

 public async Task GetOrNullAsync(string name, string providerName, string providerKey)
        {
            var cacheItem = await GetCacheItemAsync(name, providerName, providerKey);
            return cacheItem.Value;
        }
 protected virtual async Task GetCacheItemAsync(string name, string providerName, string providerKey)
        {
            var cacheKey = CalculateCacheKey(name, providerName, providerKey);
            var cacheItem = await Cache.GetAsync(cacheKey);

            if (cacheItem != null)
            {
                return cacheItem;
            }

            var setting = await SettingRepository.FindAsync(name, providerName, providerKey);

            cacheItem = new SettingCacheItem(setting?.Value);

            await Cache.SetAsync(
                cacheKey,
                cacheItem
            );

            return cacheItem;
        }

   protected virtual string CalculateCacheKey(string name, string providerName, string providerKey)
        {
            return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey);
        }

    public static string CalculateCacheKey(string name, string providerName, string providerKey)
        {
            return "pn:" + providerName + ",pk:" + providerKey + ",n:" + name;
        }

Volo.Abp.SettingManagement.EntityFrameworkCore

public async Task FindAsync(string name, string providerName, string providerKey)
        {
            return await DbSet
                .FirstOrDefaultAsync(
                    s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey
                );
        }

 

你可能感兴趣的:(设置模块)