• ABP官方文档翻译 4.5 特征管理


    特征管理

    介绍

      大多数的Saas(多租户)应用有不同的版本(包),不同的版本有不同的特征。因此,他们可以给他们的租户(客户)提供不同的价格和特征选项。

      ABP提供了特征系统,使特征管理变得容易。我们可以定义特征,检查一个特征对租户是否可用,集成特征系统到其他ABP概念中(如授权和导航)。

    关于IFeatureValueStore

      特征系统使用IFeatureValueStore获取特征值。你可以按照自己的方式实现,但在module-zero工程里已完全实现。如果它没被实现,将会使用NullFeatureValueStore,所有的特征它都返回null(这种情况下使用默认的特征值)。

    特征类型

    Boolean特征

      可以为“true”或“false”。这种特征类型可以为enableddisabled(对于一个版本或一个租户)。

    Value特征

      可以为任意的值。它存储并提取字符串,数字也可以以字符串的形式存储。

      例如,我们有一个task管理应用,这个应用在一个月内创建task的数量有限制。比方说,我们有两种不同的版本/包;一种允许一个月创建1000个任务,另一个允许创建5000个任务。所以,这种特征应该使用值存储,而不是简单的true/false。

    定义特征

      特征需先声明再检查。一个模块可以通过从FeatureProvider类继承来定义它自己的特征。这里,一个特征提供者定义了三个特征:

    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:一个唯一的名称(字符串)来标识特征。
    • Default Value:一个默认值。当我们需要特征值的时候使用这个值,对于当前租户它是不可用的。

      这里,我们定义了一个名为“SampleBooleanFeature”的布尔特征,默认值为“false”(不可用)。我们也定义了两个值特征(SampleNumericFeature定义为SampleBooleanFeature的子特征)。

      小提示:为特征名字创建静态字符串,并在任何需要的地方使用它,可以避免输入错误。

    其他特征属性

      除了唯一名称和默认值属性是必须的,还有其他一些可选属性用来更详细的控制:

    • Scope:FeatureScopes枚举的一个值。它可以为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不使用类型定义。当应用定义特征输入时可以使用他们。ABP提供基础设施使其简化。

    属性层级

      如在示例特征提供者中所示,特征可以有子特征。父特征通常定义为boolean特征。子特征只有在父特征可用时才可用。ABP不强制但推荐这样使用。应用应该关注它。

    检查特征

      对于每一个租户,我们在应用中定义特征并检查它的值来允许或阻止一些应用特征。这有两种不同的检查它的方式。

    使用RequiresFeature特性

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

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

      只有“ExportToExcel”对当前租户(当前租户从IAbpSession中获得)可用时,这个方法才能执行。如果它是不可用的,会自动抛出AbpAuthorizationException

      当然,RequiresFeature特性应用于boolean类型特征。否则会抛出异常。

    RequiresFeature特性注意点

      Abp使用动态方法拦截来实现特征检查。所以,对于使用RequiresFeature特性的方法有些限制:

    • 不能用于私有方法。
    • 不能用于静态方法。
    • 不能用于non-injected类的方法(我们必须使用依赖注入)。

      另外,

    • 可以用于任何public方法,如果这个方法是通过接口调用(如应用服务通过接口使用)。
    • 如果直接从引用类调用,方法需要为virtual。(如ASP.NET MVC或Web API控制器)。
    • 如果方法为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中实现。你可以使用它很容易的拥有一个版本系统,或者你可以完全由自己来实现。

     返回主目录

  • 相关阅读:
    导航栏的修改
    [题解](背包)luogu_P4095 eden的新背包问题
    [題解](貪心/堆)luogu_P2107小Z的AK計劃
    [題解](最短路)luogu_P2384最短路
    [題解](單調隊列dp)luogu_P1725琪露諾
    [題解](單調隊列/水)luogu_P3088擠奶牛
    [題解](單調隊列dp)【2016noip福建夏令營】探險
    [題解](水/最短路)出题人大战工作人员
    [题解](最短路)最短路点数
    [題解]luogu_P1613跑路(最短路/倍增)
  • 原文地址:https://www.cnblogs.com/xajh/p/6995424.html
Copyright © 2020-2023  润新知