zoukankan      html  css  js  c++  java
  • Abp扩展之【配置功能】

    Abp的扩展功能非常强大,配合持久化可以很方便的配置系统、租户、用户的配置,关于ABP的配置请参考:

    http://www.cnblogs.com/farb/p/ABPSettingManagement.html

    虽然此方式配合静态KEY配置使用ISettingManager获取很方便,但是还是有很多不便,每个配置都需要去单独获取并指定类型

    并且一次只能获取一个配置值,那么我们能不能直接就像使用ISettingManager来直接注入我们的配置呢,今天的扩展将实现此

    功能以达到如下需求:

    配置:

     1     [AbpAuthorize]
     2     public class ConfigurationAppService : XAppServiceBase, IConfigurationAppService
     3     {
     9         public XSettings GetXSettings()
    10         {
    11             var obj = IocManager.Instance.Resolve<XSettings>();
    12             return obj;
    13         }
    14 
    15         public async Task SaveXSettings(XSettings setting)
    16         {
    17             await setting.SaveAsync();
    18         }
    19     }

    使用:

    1 public class DemoAppService : ApplicationService, IDemoAppService
    2     {
    3         public XSettings Settings { get; set; }
    4 
    5         public void Test()
    6         {
    7             var size = this.Settings.PageSize;
    8         }
    9     }

    上面代码的重点在XSettings这个类上,那么就从这个类说起,先看看这个配置类:

        public class XSettings : SettingBase
        {
            [SettingDefinition("XProject")]
            [Required(ErrorMessage = "系统名称不能为空!")]
            public string SystemName { get; set; }
    
            [SettingDefinition(20, true)]
            public int PageSize { get; set; }
    
            //[SettingDefinition(true)]
            public bool IsOpen { get; set; }
        }

    很简单的一个配置,但是有一个基类和一个特性,先看一下特性类

        public class SettingDefinitionAttribute : Attribute
        {
            public string DefaultValue { get; private set; }
    
            public bool IsVisibleToClients { get; private set; }
    
            public SettingScopes Scopes { get; private set; }
    
            public SettingDefinitionAttribute(object defaultValue, bool isVisibleToClients = true, SettingScopes scopes = SettingScopes.Application)
            {
                this.DefaultValue = defaultValue?.ToString();
                this.IsVisibleToClients = isVisibleToClients;
                this.Scopes = scopes;
            }
        }

    我们的特性定义了该配置项的ABP配置功能,包括了默认值、是否显示到客户端、和使用域,这样就表示了配置类中的属性相关的ABP配置了

    定义好了配置后,那我们怎么保存和获取呢?这就需要我们的基类出场了:

        public abstract class SettingBase : ITransientDependency
        {
            private ISettingManager _SettingManager;
            private IAbpSession _Session;
    
            public SettingBase()
            {
                this._SettingManager = IocManager.Instance.Resolve<ISettingManager>();
                this._Session = IocManager.Instance.Resolve<IAbpSession>();
                var t = this.GetType();
                var ps = t.GetProperties();
                foreach (var p in ps)
                {
                    var settingValue = _SettingManager.GetSettingValue($"{t.Name}.{p.Name}");
                    p.SetValue(this, Convert.ChangeType(settingValue, p.PropertyType));
                }
            }
    
            public async Task SaveAsync()
            {
                var t = this.GetType();
                var ps = t.GetProperties();
                foreach (var p in ps)
                {
                    var key = $"{t.Name}.{p.Name}";
                    var val = p.GetValue(this)?.ToString();
                    var attr = p.GetCustomAttribute<SettingDefinitionAttribute>();
    
                    if (attr != null)
                    {
    
                        if (attr.Scopes.HasFlag(SettingScopes.User) && this._Session.UserId.HasValue)
                            await _SettingManager.ChangeSettingForUserAsync(this._Session.ToUserIdentifier(), key, val);
                        else if (attr.Scopes.HasFlag(SettingScopes.Tenant) && this._Session.TenantId.HasValue)
                            await _SettingManager.ChangeSettingForTenantAsync(this._Session.TenantId.Value, key, val);       
                        else
                            await _SettingManager.ChangeSettingForApplicationAsync(key, val);
                    }
                    else
                        await _SettingManager.ChangeSettingForApplicationAsync(key, val);
                }
            }
    
            public void Save()
            {
                AsyncHelper.RunSync(() => { return this.SaveAsync(); });
            }
    
        }

    基类中也很简单,就是初始化的时候,从ISettingManager中加载相应的配置设置到对应的属性上,并定义了两个保存方法来保存我们修改后的配置

    这里我之前用过一种方式就是直接设置属性的时候就自动保存,不过后面又换成了现在需要调用一个save方法的方式了。

    定义好配置加载和保存了,就只剩下初始化了,我们希望我定义好配置类以后就能在启动的时候自动初始化,所以定义了一个AutoSettingProvider

        public class AutoSettingProvider : SettingProvider
        {
            public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context)
            {
                var settings = new List<SettingDefinition>();
    
                var types = this.GetType().Assembly
                                          .GetTypes()
                                          .Where(t => t.IsClass && typeof(SettingBase).IsAssignableFrom(t));
                foreach (var t in types)
                {
                    var scopes = SettingScopes.All;
                    foreach (var p in t.GetProperties())
                    {
                        var key = $"{t.Name}.{p.Name}";
                        var isVisibleToClients = false;
                        var defaultValue = p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType).ToString() : string.Empty;
                        var attr = p.GetCustomAttribute<SettingDefinitionAttribute>();
                        if (attr != null)
                        {
                            scopes = attr.Scopes;
                            defaultValue = attr.DefaultValue;
                            isVisibleToClients = attr.IsVisibleToClients;
                        }
                        settings.Add(new SettingDefinition(
                               name: key,
                               defaultValue: defaultValue,
                               scopes: scopes,
                               isVisibleToClients: isVisibleToClients
                                ));
                    }
                }
    
                return settings;
            }
        }

    到这里,我们的配置扩展就算完成了。在所有我们需要使用的地方都可以直接注入使用了。

  • 相关阅读:
    java中源代码和lib库中有包名和类名都相同的类(转)
    Python 入门之基本数据类型
    Python 学习经历分享
    String 与不可变对象
    String 的常用操作
    Java 中的国际化
    接口和工厂设计模式
    抽象类和模板设计模式
    Java中的访问控制权限
    Java 中类的初始化过程
  • 原文地址:https://www.cnblogs.com/crazyboy/p/8064387.html
Copyright © 2011-2022 走看看