基于的 ABP vNext 版本:1.0.0
创作日期:2019 年 10 月 23 日晚
更新日期:暂无
ABP vNext 针对用户可编辑的配置,提供了单独的 Volo.Abp.Settings 模块,本篇文章的后面都将这种用户可变更的配置,叫做 参数。所谓可编辑的配置,就是我们在系统页面上,用户可以动态更改的参数值。
例如你做的系统是一个门户网站,那么前端页面上展示的 Title ,你可以在后台进行配置。这个时候你就可以将网站这种全局配置作为一个参数,在程序代码中进行定义。通过 GlobalSettingValueProvider(后面会讲) 作为这个参数的值提供者,用户就可以随时对 Title 进行更改。又或者是某些通知的开关,你也可以定义一堆参数,让用户可以动态的进行变更。
二、源码分析 2.1 模块启动流程AbpSettingsModule 模块干的事情只有两件,第一是扫描所有 ISettingDefinitionProvider (参数定义提供者),第二则是往配置参数添加一堆参数值提供者(ISettingValueProvider)。
public class AbpSettingsModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { // 自动扫描所有实现了 ISettingDefinitionProvider 的类型。 AutoAddDefinitionProviders(context.Services); } public override void ConfigureServices(ServiceConfigurationContext context) { // 配置默认的一堆参数值提供者。 Configure<AbpSettingOptions>(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); } }); // 将扫描到的数据添加到 Options 中。 services.Configure<AbpSettingOptions>(options => { options.DefinitionProviders.AddIfNotContains(definitionProviders); }); } } 2.2 参数的定义 2.2.1 参数的基本定义ABP vNext 关于参数的定义在类型 SettingDefinition 可以找到,内部的结构与 PermissionDefine 类似。。开发人员需要先定义有哪些可配置的参数,然后 ABP vNext 会自动进行管理,在网站运行期间,用户、租户可以根据自己的需要随时变更参数值。
public class SettingDefinition { /// <summary> /// 参数的唯一标识。 /// </summary> [NotNull] public string Name { get; } // 参数的显示名称,是一个多语言字符串。 [NotNull] public ILocalizableString DisplayName { get => _displayName; set => _displayName = Check.NotNull(value, nameof(value)); } private ILocalizableString _displayName; // 参数的描述信息,也是一个多语言字符串。 [CanBeNull] public ILocalizableString Description { get; set; } /// <summary> /// 参数的默认值。 /// </summary> [CanBeNull] public string DefaultValue { get; set; } /// <summary> /// 指定参数与其参数的值,是否能够在客户端进行显示。对于某些密钥设置来说是很危险的,默认值为 Fasle。 /// </summary> public bool IsVisibleToClients { get; set; } /// <summary> /// 允许更改本参数的值提供者,为空则允许所有提供者提供参数值。 /// </summary> public List<string> Providers { get; } //TODO: 考虑重命名为 AllowedProviders。 /// <summary> /// 当前参数是否能够继承父类的 Scope 信息,默认值为 True。 /// </summary> public bool IsInherited { get; set; } /// <summary> /// 参数相关连的一些扩展属性,通过一个字典进行存储。 /// </summary> [NotNull] public Dictionary<string, object> Properties { get; } /// <summary> /// 参数的值是否以加密的形式存储,默认值为 False。 /// </summary> public bool IsEncrypted { get; set; } public SettingDefinition( string name, string defaultValue = null, ILocalizableString displayName = null, ILocalizableString description = null, bool isVisibleToClients = false, bool isInherited = true, bool isEncrypted = false) { Name = name; DefaultValue = defaultValue; IsVisibleToClients = isVisibleToClients; DisplayName = displayName ?? new FixedLocalizableString(name); Description = description; IsInherited = isInherited; IsEncrypted = isEncrypted; Properties = new Dictionary<string, object>(); Providers = new List<string>(); } // 设置附加数据值。 public virtual SettingDefinition WithProperty(string key, object value) { Properties[key] = value; return this; } // 设置 Provider 属性的值。 public virtual SettingDefinition WithProviders(params string[] providers) { if (!providers.IsNullOrEmpty()) { Providers.AddRange(providers); } return this; } }