这玩意儿光看着头还是有点疼的,其实就是关于功能的基础定义,他为啥附带了一个附加描述字典,因为可以存储一些额外的信息,比如说一个短信功能,他的配额和到期时间,至于他的 Scope 则说明了它的生效范围。
2.2.2 功能管理器接着看看 GetValueAsync(int tenantId, string name) 方法的第一句:
var feature = _featureManager.Get(name);emmm,我要从 IFeatureManager 根据权限名称取得一个具体的 Feature 对象,那我们继续来看一下 IFeatureManager 接口。
public interface IFeatureManager { // 根据名称获得一个具体的功能,这个名称应该是唯一的 Feature Get(string name); // 根据一个名称获得一个具体的功能,如果没找到则返回 NULL Feature GetOrNull(string name); // 获得所有定义的功能 IReadOnlyList<Feature> GetAll(); } 2.2.3 功能管理器实现在看具体实现的时候,我们先不慌,先看一下它实现类所继承的东西。
internal class FeatureManager : FeatureDefinitionContextBase, IFeatureManager, ISingletonDependencyWTF,他又继承了什么奇奇怪怪的东西。我们又在此来到 FeatureDefinitionContextBase ,经过一番探查总算知道这玩意儿实现自 IFeatureDefinitionContext,看看他的定义:
// 功能定义上下文,主要功能是提供给 FeatureProvider 来创建功能的 public interface IFeatureDefinitionContext { // 创建一个功能 Feature Create(string name, string defaultValue, ILocalizableString displayName = null, ILocalizableString description = null, FeatureScopes scope = FeatureScopes.All, IInputType inputType = null); // 根据名称获得一个功能 Feature GetOrNull(string name); // 移除一个功能 void Remove(string name); }所以,你要把这些功能存放在哪些地方呢?
其实看到这个玩意儿 name-value,答案呼之欲出,其实现内部肯定是用的一个字典来存储数据的。
接着我们来到了 FeatureDefinitionContextBase 的默认实现 FeatureDefinitionContextBase,然后发现里面也是别有洞天,Abp 又把字典再次封装了一遍,这次字典的名字叫做 FeatureDictionary,你只需要记住他只提供了一个作用,就是将字典内部的所有功能项与其子功能项按照平级关系存放在字典当中。
除了内部封装了一个字典之外,在这个上下文当中,实现了创建,获取,和移除功能的方法,然后就没有了。我们再次回到功能管理器,
功能管理器集成了这个上下文基类,集合之前 IFeatureManager 所定义的接口,它就具备了随时可以修改功能集的权力。那么这些功能是什么时候被定义的,而又是什么时候被初始化到这个字典的呢?
在前面我们已经说过,Feature 的增加与之前文章所讲的系统设置是一样的,他们都是通过集成一个 Provider ,然后在模块预加载的时候,通过一个 IFeatureConfiguration 的东西被添加到 Abp 系统当中的。所以在 FeatureManager 内部注入了 IFeatureConfiguration 用来拿到用户在模块加载时所配置的功能项集合。
public interface IFeatureConfiguration { /// <summary> /// Used to add/remove <see cref="FeatureProvider"/>s. /// </summary> ITypeList<FeatureProvider> Providers { get; } }