Abp扩展之【配置功能】
Abp的扩展功能非常强大,配合持久化可以很方便的配置系统、租户、用户的配置,关于ABP的配置请参考:
http://www.cnblogs.com/farb/p/ABPSettingManagement.html
虽然此方式配合静态KEY配置使用ISettingManager获取很方便,但是还是有很多不便,每个配置都需要去单独获取并指定类型
并且一次只能获取一个配置值,那么我们能不能直接就像使用ISettingManager来直接注入我们的配置呢,今天的扩展将实现此
功能以达到如下需求:
配置:
[AbpAuthorize]
public class ConfigurationAppService : XAppServiceBase, IConfigurationAppService
{
public XSettings GetXSettings()
{
var obj = IocManager.Instance.Resolve<XSettings>();
return obj;
} public async Task SaveXSettings(XSettings setting)
{
await setting.SaveAsync();
}
}
使用:
public class DemoAppService : ApplicationService, IDemoAppService
{
public XSettings Settings { get; set; } public void Test()
{
var size = this.Settings.PageSize;
}
}
上面代码的重点在XSettings这个类上,那么就从这个类说起,先看看这个配置类:
public class XSettings : SettingBase
{
[SettingDefinition("XProject")]
[Required(ErrorMessage = "系统名称不能为空!")]
public string SystemName { get; set; } [SettingDefinition(, 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;
}
}
到这里,我们的配置扩展就算完成了。在所有我们需要使用的地方都可以直接注入使用了。
Abp扩展之【配置功能】的更多相关文章
- Spring Boot2.0+中,自定义配置类扩展springMVC的功能
在spring boot1.0+,我们可以使用WebMvcConfigurerAdapter来扩展springMVC的功能,其中自定义的拦截器并不会拦截静态资源(js.css等). @Configur ...
- 使用C++扩展Python的功能 转自:http://blog.csdn.net/magictong/article/details/8897568#comments
使用C++扩展Python的功能 环境 VS2005Python2.5.4 Windows7(32位) 简介 长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python ...
- kindeditor扩展粘贴图片功能&修改图片上传路径并通过webapi上传图片到图片服务器
前言 kindeditor是一个非常好用的富文本编辑器,它的简单使用我就不再介绍了. 而kindeditor却对图片的处理不够理想. 本篇博文需要解决的问题有两个: kindeditor扩展粘贴图片功 ...
- kindeditor扩展粘贴截图功能&修改图片上传路径并通过webapi上传图片到图片服务器
前言 kindeditor是一个非常好用的富文本编辑器,它的简单使用我就不再介绍了. 而kindeditor却对图片的处理不够理想. 本篇博文需要解决的问题有两个: kindeditor扩展粘贴图片功 ...
- WCF学习之旅—WCF4.0中的简化配置功能(十五)
六 WCF4.0中的简化配置功能 WCF4.0为了简化服务配置,提供了默认的终结点.绑定和服务行为.也就是说,在开发WCF服务程序的时候,即使我们不提供显示的 服务终结点,WCF框架也能为我们的服务提 ...
- Rest Client(Rest接口调试工具,有保存功配置功能) chrome浏览器插件
Rest Client(Rest接口调试工具,有保存功配置功能) chrome浏览器插件 下载地址 插件的操作很简单,下面是一些简单的实例. 1.安装 在谷歌应用商城搜索postman,如下图1-1所 ...
- Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试
Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试 需要FQ才能安装,使用时应该不用FQ了,除非使用postman的历史记录功能: 非常棒的C ...
- qmake的配置功能(Configuration Features)
Configuration Features qmake can be set up with extra configuration features that are specified in f ...
- windows下安装MongoDB扩展和配置
windows下安装MongoDB扩展和配置 1.下载mongoDB扩展,根据当前php版本进行下载 地址如下:http://pecl.php.net/package/mongo 我本地php版本是 ...
随机推荐
- 349B - Color the Fence
Color the Fence Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Su ...
- Color the Ball(懵逼题)
Color the Ball Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- css设置黑体宋体等(转)
代码如下: .selector{ font-family:"Microsoft YaHei",微软雅黑,"MicrosoftJhengHei",华文细黑,STH ...
- java 操作格子问题(线段树)
很久之前做过线段树的问题(操作格子),时间长了之后再次接触到,发现当初理解的不是很透彻,然后代码冗长,再遇到的时候发现自己甚至不能独立地完成这个问题. 所以算法这个东西啊, 第一,是要经常练习(我个人 ...
- struts2运行过程(图解)
.................................................................................................... ...
- Netty(二)——TCP粘包/拆包
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7814644.html 前面讲到:Netty(一)--Netty入门程序 主要内容: TCP粘包/拆包的基础知 ...
- Python 解LeetCode:654. Maximum Binary Tree
用一个整型数组构建一个二叉树,根结点是数组中的最大值,左右子树分别是根结点的值在数组中左右两边的部分. 分析,这是二叉树中比较容易想到的问题了,直接使用递归就行了,代码如下: class Soluti ...
- 手工搭建基于ABP的框架(2) - 访问数据库
为了防止不提供原网址的转载,特在这里加上原文链接: http://www.cnblogs.com/skabyy/p/7517397.html 本篇我们实现数据库的访问.我们将实现两种数据库访问方法来访 ...
- 设计模式的征途—10.装饰(Decorator)模式
虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...
- Linux命令kill和signal
Linux命令kill和signal kill命令用于终止指定的进程(terminate a process),是Unix/Linux下进程管理的常用命令.通常,我们在需要终止某个或某些进程时,先使用 ...