• 设置模块


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

    配置是一个Name-Vaule键值对,设置系统是可扩展,内置提供 user, a tenant, global and default等方式,其中global,user,tenant是使用SettingStore来持久化,因此要引用settingmanagemententityframeworkcore,它引用了相应domain。

    ISettingProvider,通常用于获取设置值,常用GetOrNullAsync方法,它是先通过SettingDefinitionManager创建所有settingDefinitions,settingValueProviderManager使用GetRequiredService创建type实例,然后通过遍历SettingValueProvider获取需要的值。

    ISettingProvider 是非常常用的服务,一些基类中(如IApplicationService)已经将其属性注入. 这种情况下可以直接使用SettingProvider.

            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 提供了5个自定义的获取设置值的提供方法,实现基类SettingValueProvider,扩展方法public abstract Task<string> GetOrNullAsync(SettingDefinition setting),分别是默认值提供者(D),configuration提供者(C),全局值提供者(G),租户值提供(T),用户值(U)提供;

    其中,默认提供使用SettingDefinition.DefaultValue,而configuration提供者使用是IConfiguration获取,其它三个是使用数据库获取

    SettingStore是获取提供参数的ProviderName = G,T,U ,而providerKey分别是,null,CurrentTenant.Id?.ToString(),CurrentUser.Id.ToString()

         public override void PreConfigureServices(ServiceConfigurationContext context)
            {
                AutoAddDefinitionProviders(context.Services);
            }
            public override void ConfigureServices(ServiceConfigurationContext context)
            {          
                Configure<SettingOptions>(options =>
                {
                    options.ValueProviders.Add<DefaultValueSettingValueProvider>();
                    options.ValueProviders.Add<GlobalSettingValueProvider>();
                    options.ValueProviders.Add<TenantSettingValueProvider>();
                    options.ValueProviders.Add<UserSettingValueProvider>();
                });
            }
    private static void AutoAddDefinitionProviders(IServiceCollection services) { var definitionProviders = new List<Type>(); services.OnRegistred(context => { if (typeof(ISettingDefinitionProvider).IsAssignableFrom(context.ImplementationType)) { definitionProviders.Add(context.ImplementationType); } }); services.Configure<SettingOptions>(options => { options.DefinitionProviders.AddIfNotContains(definitionProviders); }); }

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

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

    • Name: 应用程序中设置的唯一名称. 是具有约束的唯一属性, 在应用程序获取/设置此设置的值 (设置名称定义为常量而不是magic字符串是个好主意).
    • DefaultValue: 设置的默认值.
    • DisplayName: 本地化的字符串,用于在UI上显示名称.
    • Description: 本地化的字符串,用于在UI上显示描述.
    • IsVisibleToClients: 布尔值,表示此设置是否在客户端可用. 默认为false,避免意外暴漏内部关键设置.
    • IsInherited: 布尔值,此设置值是否从其他提供程序继承. 如果没有为请求的提供程序设置设定值,那么默认值是true并回退到下一个提供程序 (参阅设置值提供程序部分了解更多).
    • IsEncrypted: 布尔值,表示是否在保存值是加密,读取时解密. 在数据库中存储加密的值.
    • Providers: 限制可用于特定的设置值提供程序(参阅设置值提供程序部分了解更多).
    • Properties: 设置此值的自定义属性 名称/值 集合,可以在之后的应用程序代码中使用

    4、定义配置的上下文Define(ISettingDefinitionContext context),存储配置字典的定义   Dictionary<string, SettingDefinition> key值为definition.Name,value值为definition。使用处:在SettingDefinitionManager的构造函数,遍历Options.DefinitionProviders,填充成字典new Dictionary<string, SettingDefinition>()

    SettingDefinitionProvider提供者,比如邮件设置的上下文  

     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, "noreply@abp.io"),
                    new SettingDefinition(EmailSettingNames.DefaultFromDisplayName, "ABP application")
                );
            }
        }

    在某些情况下,你可能希望更改应用程序/模块所依赖的其他模块中定义的设置的某些属性. 设置定义提供程序可以查询和更新设置定义.

    public class MySettingDefinitionProvider : SettingDefinitionProvider
    {
        public override void Define(ISettingDefinitionContext context)
        {
            var smtpHost = context.GetOrNull("Abp.Mailing.Smtp.Host");
            if (smtpHost != null)
            {
                smtpHost.DefaultValue = "mail.mydomain.com";
                smtpHost.DisplayName =
                    new LocalizableString(
                        typeof(MyLocalizationResource),
                        "SmtpServer_DisplayName"
                    );
            }
        }
    }
     public SettingDefinitionManager(
                IOptions<SettingOptions> options,
                IServiceProvider serviceProvider)
            {
                ServiceProvider = serviceProvider;
                Options = options.Value;
                SettingDefinitions = new Lazy<IDictionary<string, SettingDefinition>>(CreateSettingDefinitions, true);
            }
    
     protected virtual IDictionary<string, SettingDefinition> CreateSettingDefinitions()
            {
                var settings = new Dictionary<string, SettingDefinition>();
    
                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<ISettingValueProvider> Providers实例

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

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

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

           public virtual async Task<string> 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<string> GetOrNullValueFromProvidersAsync(
                IEnumerable<ISettingValueProvider> 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<SettingCacheItem> Cache 里面缓存,若没有则设置缓存

     public async Task<string> GetOrNullAsync(string name, string providerName, string providerKey)
            {
                var cacheItem = await GetCacheItemAsync(name, providerName, providerKey);
                return cacheItem.Value;
            }
     protected virtual async Task<SettingCacheItem> 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<Setting> FindAsync(string name, string providerName, string providerKey)
            {
                return await DbSet
                    .FirstOrDefaultAsync(
                        s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey
                    );
            }
    

     在IApplicationService已经属性注入

  • 相关阅读:
    Ubuntu18.04 Redis主从复制
    解决:git push error: failed to push some refs to
    手把手安装Laravel框架(permissions扩展包)实现RBAC权限---以及一些安装时的ERROR
    linux-Navicat 连接数据库 报错10060 & Navicat连接报错1146
    composer PHP Fatal error致命错误
    Yii框架基础增删查改
    cookie和session的区别
    mysql的索引优化
    什么是B+Tree
    螺旋矩阵
  • 原文地址:https://www.cnblogs.com/cloudsu/p/11161834.html
Copyright © 2020-2023  润新知