在之前那章 midwayjs路由实现那章 我们看到过这样的代码
/*** save data to class* @param decoratorNameKey* @param data* @param target* @param mergeIfExist*/export function saveClassMetadata(decoratorNameKey: ObjectIdentifier,data: any,target: any,mergeIfExist?: boolean) {if (mergeIfExist && typeof data === 'object') {const originData = manager.getMetadata(decoratorNameKey, target);if (!originData) {return manager.saveMetadata(decoratorNameKey, data, target);}if (Array.isArray(originData)) {return manager.saveMetadata(decoratorNameKey,originData.concat(data),target);} else {return manager.saveMetadata(decoratorNameKey,Object.assign(originData, data),target);}} else {return manager.saveMetadata(decoratorNameKey, data, target);}}
其中 manager 就是我们最开始所描述的容器 下面阶段来介绍下 这个 manager
1. saveMetadata
这个看方法名 理解起来也不难 就是 元数据的存储 接下来就是解析下 源码的执行过程
export class DecoratorManager extends Map implements IModuleStore {/*** the key for method meta data store in method*/injectMethodKeyPrefix = 'INJECTION_METHOD_META_DATA';injectClassKeyPrefix = 'INJECTION_CLASS_META_DATA'static getDecoratorMethodKey(decoratorNameKey: ObjectIdentifier) {return decoratorNameKey.toString() + '_METHOD';}static getDecoratorMethod(decoratorNameKey: ObjectIdentifier,methodKey: ObjectIdentifier) {return (DecoratorManager.getDecoratorMethodKey(decoratorNameKey) +'_' +methodKey.toString());}// 静态方法 存储元数据static saveMetadata(metaKey: string,target: any,dataKey: string,data: any) {// filter Object.create(null)if (typeof target === 'object' && target.constructor) {target = target.constructor;}let m: Map<string, any>;// 如果 target 对应的 元key 存在 元数据if (Reflect.hasOwnMetadata(metaKey, target)) {// m 等于用户存储的元数据m = Reflect.getMetadata(metaKey, target);} else {// 否则 初始化一个新的 mapm = new Map<string, any>();}// 存储新的 属性值对应的数据m.set(dataKey, data);Reflect.defineMetadata(metaKey, m, target);}/*** save meta data to class or property* @param decoratorNameKey the alias name for decorator* @param data the data you want to store* @param target target class* @param propertyName*/// 存储元数据saveMetadata(decoratorNameKey: ObjectIdentifier,data,target,propertyName?) {if (propertyName) {// 假如 用户输入了 propertyName// saveMetadata('decoratorNameKey', {}, target, 'propertyKey')const dataKey = DecoratorManager.getDecoratorMethod(decoratorNameKey,propertyName);// dataKey 此时取到的值 为 'decoratorNameKey_METHOD_propertyKey'DecoratorManager.saveMetadata(this.injectMethodKeyPrefix,target,dataKey,data);} else {// 如果用户没有输入 propertyName// saveMetadata('decoratorNameKey', {}, target)const dataKey = DecoratorManager.getDecoratorClassKey(decoratorNameKey);// dataKey 此时取到的值 为 'decoratorNameKey_METHOD'DecoratorManager.saveMetadata(this.injectClassKeyPrefix,target,dataKey,data);}}}
执行流程如下
- 首先 我们根据 有没有 propertyName 入参 来生成一个 dataKey
- 执行 DecoratorManager的静态方法 saveMetadata 来存储元数据
如果 没有 输入的 propertyName 的话 说明存储 的一个类级别的元数据 用 INJECTION_CLASS_META_DATA 所为 key
否则 的话 用 INJECTION_METHOD_META_DATA
同时看静态方法 也知道 这两个key 下存的值是 Map 的格式 而 Map 的key 就是我们刚才得出来的 dataKey
2. getMetadata
有set的话 就有get 那么继续看代码了
export class DecoratorManager extends Map implements IModuleStore {// 静态方法 获取元数据static getMetadata(metaKey: string, target: any, dataKey?: string) {// filter Object.create(null)if (typeof target === 'object' && target.constructor) {target = target.constructor;}let m: Map<string, any>;if (!Reflect.hasOwnMetadata(metaKey, target)) {m = new Map<string, any>();Reflect.defineMetadata(metaKey, m, target);} else {m = Reflect.getMetadata(metaKey, target);}if (!dataKey) {return m;}return m.get(dataKey);}/*** get single data from class or property* @param decoratorNameKey* @param target* @param propertyName*/getMetadata(decoratorNameKey: ObjectIdentifier, target, propertyName?) {if (propertyName) {const dataKey = DecoratorManager.getDecoratorMethod(decoratorNameKey,propertyName);return DecoratorManager.getMetadata(this.injectMethodKeyPrefix,target,dataKey);} else {const dataKey = `${DecoratorManager.getDecoratorClassKey(decoratorNameKey)}`;return DecoratorManager.getMetadata(this.injectClassKeyPrefix,target,dataKey);}}}
