ABP理论学习之功能管理
本篇目录
介绍###
大多数的Saas(多租户)应用都有不同 功能的 版本(包)。因此,他们可以给租户(客户)提供不同的 价格和功能选项。
ABP提供了功能系统使得这个更简单。我们可以 定义功能,然后检查某个功能是否对一个租户 开启了,最后将功能系统 集成到其他的ABP概念中(如权限和菜单)。
关于IFeatureValueStore
功能系统使用了IFeatureValueStore来获得功能的值。虽然你可以用自己的方式实现该接口,但是它已经完全实现在了 module-zero项目中。如果没有实现该接口,那么默认会使用NullFeatureValueStore对所有的功能返回null(此时使用默认的功能值)。
功能类型###
有两种基本功能类型。
布尔功能
可以是"true"或"false"。这种类型的功能(对于一个版本或者一个租户)可能是开启的或者 关闭的。
值功能
可以是任意值。虽然它是以字符串存储和检索的,但是数值也可以轻松地存储为字符串。
比如,我们的应用程序可能是一个任务管理应用,我们可能在一个月内对于创建任务会有限制。假如说我们有两个不同的版本:一个版本每个月允许创建1000个任务,但是另一个每个月允许创建5000个任务。因此,这个功能应该存储为值,而不是简单的true或false。
定义功能###
在检查功能之前应该先定义功能。一个模块可以通过从FeatureProvider类派生来定义自己的功能。这里有一个定义了3个功能的非常简单的功能提供者:
public class AppFeatureProvider : FeatureProvider
{
public override void SetFeatures(IFeatureDefinitionContext context)
{
var sampleBooleanFeature = context.Create("SampleBooleanFeature", defaultValue: "false");
sampleBooleanFeature.CreateChildFeature("SampleNumericFeature", defaultValue: "10");
context.Create("SampleSelectionFeature", defaultValue: "B");
}
}
创建功能提供者之后,我们应该在模块的PreInitialize方法中注册,如下所示:
Configuration.Features.Providers.Add<AppFeatureProvider>();
基本功能属性
一个功能的定义至少要求两个属性:
- Name:识别该功能唯一的名字(字符串)。
- DefaultValue:默认值。当我们需要该功能的值时会用到该属性,而且对于当前的租户不可用。
上面的代码样例中,我们定义了一个名为"SampleBooleanFeature"布尔功能,它的默认值是"false"(不可用)。我们也定义了两个值功能(SampleNumericFeature定义为SampleBooleanFeature的孩子)。
提示:为功能名称创建一个常量字符串,然后在任何地方使用时会防止拼写失误。
其他功能属性
虽然对于ABP来说一个唯一的名称和默认值属性已经足够了,但是对于细节的控制还有许多其他的功能属性。
- Scope:FeatureScope枚举值之一。它可以是Edition(如果只为版本级别设置该功能), Tenant(如果只为租户级别设置该功能),或者 All(如果为版本和租户都可以设置该功能,这种情况下,租户的设置会覆盖版本的设置)。默认值是All。
- DisplayName:给用户显示该功能名称的本地化字符串。
- Description:给用户显示该功能细节描述的本地化字符串。
- InputType:该功能的UI输入类型。
- Attributes:任意的自定义键值对字典,可以和该功能关联起来。
让我们看一下该功能的细节定义:
public class AppFeatureProvider : FeatureProvider
{
public override void SetFeatures(IFeatureDefinitionContext context)
{
var sampleBooleanFeature = context.Create(
AppFeatures.SampleBooleanFeature,
defaultValue: "false",
displayName: L("Sample boolean feature"),
inputType: new CheckboxInputType()
);
sampleBooleanFeature.CreateChildFeature(
AppFeatures.SampleNumericFeature,
defaultValue: "10",
displayName: L("Sample numeric feature"),
inputType: new SingleLineStringInputType(new NumericValueValidator(1, 1000000))
);
context.Create(
AppFeatures.SampleSelectionFeature,
defaultValue: "B",
displayName: L("Sample selection feature"),
inputType: new ComboboxInputType(
new StaticLocalizableComboboxItemSource(
new LocalizableComboboxItem("A", L("Selection A")),
new LocalizableComboboxItem("B", L("Selection B")),
new LocalizableComboboxItem("C", L("Selection C"))
)
)
);
}
private static ILocalizableString L(string name)
{
return new LocalizableString(name, AbpZeroTemplateConsts.LocalizationSourceName);
}
}
注意:ABP没有使用这里的InputType。当为功能创建输入时,应用程序会使用它们。ABP只是提供了这些选项使得它更容易。
功能层次
正如样例功能提供者所示,一个功能可以有子功能。一个父母功能一般定义为 布尔功能。只有父母功能可用时,孩子功能才可用。ABP不强制这样做,但是建议这样做。
检查功能###
使用RequireFeature特性
我们可以为方法或类使用RequiredFeature特性,如下所示:
[RequiresFeature("ExportToExcel")]
public async Task<FileDto> GetReportToExcel(...)
{
...
}
该方法只有在"ExportToExcel"功能对当前租户开启时才会执行(当前租户从IAbpSession中获得)。如果没有开启该功能,那么就会自动抛出 AbpAuthorizationException。
当然,RequiresFeature特性应该用于布尔类型功能。否则,你会得到异常。
RequiresFeature特性注意点
ABP对于功能检查使用了强大的动态方法拦截(interception)。因此,为方法使用RequiresFeature特性时有一些限制条件:
- 不能用于私有方法。
- 不能用于静态方法。
- 不能用于非注入类的方法(我们必须使用DI)。
此外,
- 如果该方法是通过一个接口(如应用服务通过接口调用)调用的,那么我们可以将它用于任何 public的方法。
- 如果一个方法直接从类的引用调用(如MVC或Web API控制器),那么它应该是virtual的。
- 如果一个方法是protected,那么该方法应该是 virtual。
使用IFeatureChecker
我们可以注入并使用IFeatureChecker来手动检查一个功能(对于应用服务,MVC和Web API控制器,它会自动注入而且直接可以使用)。
IsEnabled
用于简单地检查给定的功能是否开启。例子:
public async Task<FileDto> GetReportToExcel(...)
{
if (await FeatureChecker.IsEnabledAsync("ExportToExcel"))
{
throw new AbpAuthorizationException("You don't have this feature: ExportToExcel");
}
...
}
IsEnabledAsync和其他方法都有同步版本。
当然,IsEnabled方法应该用于布尔类型功能。否则可能会抛异常。
如果你只想检查一个功能,然后抛出例子中的异常,那么你只需要使用CheckEnabled方法就行了。
GetValue
用于获得值类型功能的当前值,例子:
var createdTaskCountInThisMonth = GetCreatedTaskCountInThisMonth();
if (createdTaskCountInThisMonth >= FeatureChecker.GetValue("MaxTaskCreationLimitPerMonth").To<int>())
{
throw new AbpAuthorizationException("You exceed task creation limit for this month, sorry :(");
}
FeatureChecker方法也有对于特定租户的重载,不仅仅只对于当前的租户。
客户端
在客户端,我们使用abp.features命名空间来获得该功能的当前值。
isEnabled
var isEnabled = abp.features.isEnabled('SampleBooleanFeature');
getValue
var value = abp.features.getValue('SampleNumericFeature');
功能管理者###
如果需要定义功能,可以注入并使用IFeatureManager。
版本说明###
ABP没有内置的版本系统,因为这么个系统要求数据库(存储版本,版本功能,租户-版本映射等等)。因此,版本系统实现在了module-zero中了。使用它你可以轻松地拥有一个版本系统,要不然你可以自己实现。
ABP理论学习之功能管理的更多相关文章
- ABP理论学习之设置管理
返回总目录 本篇目录 介绍 定义设置 获取设置值 更改设置 关于缓存 介绍 每个应用程序都需要存储一些设置信息,然后在应用程序中的某个地方使用这些设置.ABP提供了健壮的基础设施来存储或检索服务端和客 ...
- ABP框架 - 功能管理
文档目录 本节内容: 简介 关于 IFeatureValueStore 功能类型 Boolean 功能 Value 功能 定义功能 基本功能属性 其它功能属性 功能层次 检查功能 使用Requires ...
- ABP理论学习之MVC视图
返回总目录 本篇目录 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc Nuget包集成了MVC视图.因此你可以像常规那样创建MVC视图. AbpWebViewPage基 ...
- ABP理论学习之Javascript API(理论完结篇)
返回总目录 本篇目录 Ajax Notification Message UI block和busy 事件总线 Logging 其他工具功能 说在前面的话 不知不觉,我们送走了2015,同时迎来了20 ...
- AspnetBoilerplate (ABP) Organization Units 组织结构管理
ABP是一个成熟的.NET框架,功能完善.目前由于项目需要正在自学中. ABP对于组织节点管理这一基本上每个项目都要反复重复开发的内容,进行了自己的实现. 主要包括这些常用功能: 多租户 树结构管理的 ...
- X-Admin&ABP框架开发-设置管理
在网站开发中,设置是不可缺少的一环,如用户设置.系统设置.甚至是租户设置等.ABP对于设置的管理已经做了很好的处理,我们可以借助巨人的力量来完成我们的冒险. ABP官网地址:https://aspne ...
- Asp.Net Core 项目实战之权限管理系统(6) 功能管理
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- ABP理论学习之仓储
返回总目录 本篇目录 IRepository接口 查询 插入 更新 删除 其他 关于异步方法 仓储实现 管理数据库连接 仓储的生命周期 仓储最佳实践 Martin Fowler对仓储的定义 位于领域层 ...
- Xianfeng轻量级Java中间件平台:功能管理
功能管理:从功能类型来看,不属于用户使用的功能,而属于系统维护使用的功能,因为对于用户来说,是不可见的.功能管理的作用是定义一套规则,用来处理权限等业务,比如常见的菜单权限控制.按钮权限控制等情景 在 ...
随机推荐
- Dapper入门学习
今天了解并学习了下Dapper的用法,这里简单介绍下 1.安装Nuget Dapper Package包 2.代码 using (IDbConnection connection = new SqlC ...
- 【DWR系列06】- DWR日志及js压缩
img { border: solid 1px } 一.日志 DWR依赖 Apache Commons Logging,可以使用log4j实现日志记录功能. 1.1 日志简介 和其他日志框架一样,当设 ...
- NFC读写实例
package com.sy.nfc.test; import java.io.IOException; import android.nfc.NdefMessage; import android. ...
- VS Code 配置Python
1. 安装VS Code的Python插件,选择安装次数最多的那个 2. 点击用户设置菜单,在settings.json中添加 "python.pythonPath": " ...
- 关于 js 一些基本的东西
r.js 可以打包(可以实现前端文件的压缩与合并). 客户端尽量遵循 amd 规范. 推荐使用 requirejs 规范. requirejs 简单教程: http://www.runoob.com/ ...
- dos下对mysql的简单操作(linux类似)
>>>>>>>>>>>>>>>>>>>> 基础入门语句10条 1. 连接服务器 ...
- Linux学习笔记(12)-进程间通信|匿名管道
Linux的进程间通信有几种方式,包括,管道,信号,信号灯,共享内存,消息队列和套接字等-- 现在一个个的开始学习! ----------------------------------------- ...
- hive学习笔记
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- 一些VS2013的使用技巧
作者:h46incon的Blog 1. Peek View 可以在不新建TAB的情况下快速查看.编辑一个函数的代码. 用法:在光标移至某个函数下,按下alt+F12. 然后在Peek窗口里可以继续按a ...
- curl模拟post,get,put,delete
安装curl:https://curl.haxx.se/download.html 测试:tomcat默认禁用put,delete返回403 GET curl -HAccept:text/plain ...