• ABP框架


    文档目录

    本节内容:

    简介

    大部分SaaS(多租户)应用有不同功能的版本(包),因此你可以提供不同价格和功能选项给租户(客户)。

    ABP提供了一个功能系统,使它易于使用,我们可以定义功能,检查一个功能对于一个租户是否可用,并把功能系统整合到其它ABP概念里(如授权导航)。

    关于 IFeatureValueStore

    功能系统使用IFeatureValueStore来获取功能的值。尽管你可以用自己的方式实现它,但在module-zero项目里已经完全实现。如果它没有被实现,NullFeatureValueStore用来为所有功能返回null(这种情况下使用默认功能值)。

    功能类型

    有两个基本的功能类型。

    Boolean 功能

    可以是“true”或“false”,一个这种类型的功能可以是启用或禁用(为一个版本或一个租户)。

    Value 功能

    可以是任意值,它保存和获取一个字符串,数字也保存成字符串。

    例如,我们的应用可能是一个任务管理应用,一个月只创建有限的几个任务,假设我们有两个不同的版本/包,有一个允许创建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:一个默认值,当我们需要这个功能的值而又不能从当前租户取得时,我们需要一个默认值。

    此处,我们定义了一个Boolean功能,名为“SampleBooleanFeature”,默认值为“false”(不可用),同时我们定义了两个值功能(SampleNumericFeature被定义成SampleBooleanFeature的子功能)。

    小建议:创建一个字符串常量作为一个功能名,不管在哪里使用都可避免输入错误。

    其它功能属性

    虽然唯一名称和默认值属性是必须的,但也有一可选的属性,提供细节控制。

    • Scope:一个FeatureScopes枚举值,它可以是Edition(如果这个功能只能设置版本级别),Tenant(如果这个功能只能设置租户级别)或All(如果这个功能可设置版本和租户,租户设置会覆盖版本设置)。默认值是All。
    • DisplayName:一个本地化的字符串,为用户显示这个功能的名称。
    • Description:一个本地化的字符串,为客户显示这个功能的细节描述。
    • InputType:这个功能的一个UI输入类型,这个可被定义,当创建一个自动功能屏幕时可以使用它。
    • Attribute:一个键值对的用户字典,关联这个功能。

    让我们看一下上面那个功能更多的细节定义:

    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所用,当创建功能的输入时,它可被应用使用,ABP只是提供基础框架,使它更易于使用。

    功能层次

    如上面所示的示例功能供应器,一个功能可以有子功能。一个父功能通常定义为Boolean功能,只有在父功能可用时,才能获取子功能。ABP不强制但建议这么做,应用应当小心处理它。

    检查功能

    我们定义一个功能来检查它的在应用里的值,从而为每个租户允许或阻止一些应用功能。有几种不同的检查方式。

    使用RequiresFeature特性

    我们可以为一个方法或类使用RequiredFeature,如下所示:

    [RequiresFeature("ExportToExcel")]
    public async Task<FileDto> GetReportToExcel(...)
    {
        ...
    }

    只有当前租户(从IAbpSession里获取)的“ExportToExcel”功能可用时,才能执行这个方法,如果不可用,就自动抛出一个AbpAuthorizationException。

    当然,RequiresFeature特性应该用在Boolean类型的功能上,否则,你会收到异常。

    RequiresFeature特性注意事项

    ABP为功能检查使用强大的动态方法拦截,所以在方法上使用RequiresFeature特性有些限制:

    • 不能用在private方法上。
    • 不能用在静态方法上。
    • 不能用在无注入类的方法上(我们必须使用依赖注入)。

    同时,可用于:

    • 任何通过接口调用的public方法(如通过接口使用应用服务)
    • 一个直接通过类引用(如Asp.Net 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方法应当被Boolean类型的功能使用,否则,你会得到异常。

    如果你只是想检查一个功能,并抛出异常,如上面例子所示那样,你可以使用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方法也提供了为一个指定tenantId工作的功能,不只是为当前tenantId。

    客户端

    在客户端(Javascript),我们可以使用abp.features命名空间来获取功能的当前值。

    isEnabled

    var isEnabled = abp.features.isEnabled('SampleBooleanFeature');

    getValue

    var value = abp.features.getValue('SampleNumericFeature');

    功能管理器

    如果你需要用到功能的定义,你可以注入IFeatureManager并使用它。

    对版本的一个提示

    ABP框架没有一个内容的版本系统,因为如此一个系统需要一个数据库(存储版本,版本功能,租户版本映射...),因此,版本系统在module zero里实现,你可以很容易的使用它并获取一个版本系统,或者你自己实现。

  • 相关阅读:
    [转]项目需求范围管理
    JavaScript 王者归来
    [转]大文件上传组件
    [转]使用vs2005自带的sql2005 express
    JS判断Caps Lock
    [转]Web项目管理思考
    [转]JS严格验证身份证
    两分钟用C#搭建IE BHO勾子, 窃取密码
    asp.net性能提升十个方法(Microsoft)
    [转]Asp.net 将js文件打包进dll 方法
  • 原文地址:https://www.cnblogs.com/kid1412/p/6008033.html
Copyright © 2020-2023  润新知