npm地址:https://www.npmjs.com/package/reflect-metadata
一、安装
1 |
npm install reflect-metadata |
二、背景
- 装饰器通过声明式语法在定义类时添加增强类及其成员的能力;
- 示踪器将注释附加到类的静态属性上;
-
诸如C#(.NET)和Java之类的语言支持将元数据添加到类型的属性或注释,以及用于读取元数据的反射API。
三、目标
- 许多用例(组合/依赖注入,运行时类型断言,反射/镜像,测试)都希望能够以一致的方式向类中添加其他元数据;
-
为了使各种工具和库能够推理出元数据,需要一种一致的方法;
-
产生元数据的修饰器(nee。“ Annotations”)通常需要与可变修饰器组合在一起;
- 元数据不仅可以用在对象上,也可以通过相关捕获器用在Proxy上;
- 对开发人员来说,定义新的元数据生成装饰器应该简洁易用;
- 元数据应该与ECMAScript的其他语言和运行效果一致;
四、语法
运行命令行:tsc index.ts –target ES5 -w –experimentalDecorators –emitDecoratorMetadata
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import 'reflect-metadata' /** * Declarative definition of metadata * 元数据的声明式定义 * class C { * @Reflect.metadata(metadataKey, metadataValue) * method() {} * } */ class C1 { @Reflect.metadata('key1', 'value1') name: string = 'hello' @Reflect.metadata('key2', 'value2') method() {} } const value1 = Reflect.getMetadata('key1', new C1(), 'name') const value2 = Reflect.getMetadata('key2', new C1(), 'method') console.log('Syntax.1', value1, value2) // value1 value2 /** * Imperative definition of metadata * 元数据的命令式定义 * Reflect.defineMetadata(metadataKey, metadataValue, C.prototype, 'method') */ Reflect.defineMetadata('key3', 'value3', C1.prototype, 'name') const value3 = Reflect.getMetadata('key3', C1.prototype, 'name') console.log('Syntax.2', value3) // value3 /** * Imperative introspection of metadata * 元数据的命令自省 * let obj = new C() * let metadataValue = Reflect.getMetadata(metadataKey, obj, 'method') */ class A { @Reflect.metadata('A-key1', 'A-value1') method() {} } let obj = new A() let AMetadataValue1 = Reflect.getMetadata('A-key1', obj, 'method') console.log('AMetadataValue1', AMetadataValue1) |
五、API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
/** * define metadata on an object or property * 在对象或属性上定义元数据 * Reflect.defineMetadata(metadataKey, metadataValue, target) * Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey) */ class A1 { method() {} } Reflect.defineMetadata('A1-key1', 'A1-value1', A1) Reflect.defineMetadata('A1-key2', 'A1-value2', A1, 'method') let A1Result1 = Reflect.getMetadata('A1-key1', A1) let A1Result2 = Reflect.getMetadata('A1-key2', A1, 'method') console.log('A1Result1', A1Result1) console.log('A1Result2', A1Result2) /** * check for presence of a metadata key on the prototype chain of an object or property * 检查对象或属性的原型链上是否存在元数据键 * let result = Reflect.hasMetadata(metadataKey, target) * let result = Reflect.hasMetadata(metadataKey, target, propertyKey) */ @Reflect.metadata('c2-key1', 'c2-value1') class C2 { @Reflect.metadata('c2-key2', 'c2-value2') name: string = 'bob' } let c2Result1 = Reflect.hasMetadata('c2-key1', C2) // true let c2Result2 = Reflect.hasMetadata('c2-key2', C2.prototype, 'name') // true let c2Result3 = Reflect.hasMetadata('c2-key3', C2.prototype, 'name') // false console.log('hasMetadata', c2Result1, c2Result2, c2Result3) class C21 extends C2 { method() {} } let c2Result4 = Reflect.hasMetadata('c2-key1', C21) // true let c2Result5 = Reflect.hasMetadata('c2-key2', C21.prototype, 'name') // true console.log('hasMetadata', c2Result4, c2Result5) /** * check for presence of an own metadata key of an object or property * 检查对象或属性是否存在自己的元数据键值 * let result = Reflect.hasOwnMetadata(metadataKey, target) * let result = Reflect.hasOwnmetadata(metadataKey, target, propertyKey) */ function age(age: number) { console.log('age') return function (target: any, propertyKey: string) { Reflect.defineMetadata('c3-key3', age, target, propertyKey) } } @Reflect.metadata('c3-key1', 'c3-value1') class C3 { @Reflect.metadata('c3-key2', 'c3-key2') name: string = 'bob' @age(18) age: number = 18 } let c3Result1 = Reflect.hasOwnMetadata('c3-key1', C3) // true let c3Result2 = Reflect.hasOwnMetadata('c3-key2', C3.prototype, 'name') // true let c3Result3 = Reflect.hasOwnMetadata('c3-key3', C3.prototype, 'age') // true let c3Result4 = Reflect.hasOwnMetadata('c3-key3', new C3(), 'age') // false console.log('hasOwnMetadata', c3Result1, c3Result2, c3Result3, c3Result4) class C31 extends C3 { method() {} } let c3Result5 = Reflect.hasOwnMetadata('c3-key1', C31) // false let c3Result6 = Reflect.hasOwnMetadata('c3-key2', C31, 'name') // false console.log('hasOwnMetadata', c3Result5, c3Result6) /** * get metadata value of a metadata key on the prototype chain of an object or property * 在对象或属性的原型链上获取元数据键的元数据值 * let result = Reflect.getMetadata(metadataKey, target) * let result = Reflect.getMetadata(metadataKey, target, propertyKey) */ /** * get metadata value of an own metadata key of an object or property * 获取对象或属性自己的元数据键的元数据值 * let result = Reflect.getOwnMetadata(metadataKey, target) * let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey) */ /** * get all metadata keys on the prototype chain of an object or property * 获取对象或属性上所有原型链上的元数据键值 * let result = Reflect.getMetadataKeys(target) * let result = Reflect.getMetadataKeys(target, propertyKey) */ @Reflect.metadata('c4-key2', 'c4-value2') class C4 { @Reflect.metadata('c4-key3', 'c4-value3') name: string = 'bob' @Reflect.metadata('c4-key1', 'c4-value1') method() { return 'hello' } } let c4Result1 = Reflect.getMetadataKeys(new C4(), 'method') let c4Result2 = Reflect.getMetadataKeys(C4) let c4Result3 = Reflect.getMetadataKeys(new C4(), 'name') let c4Result4 = Reflect.getMetadataKeys(C4.prototype, 'method') console.log('c4Result1', c4Result1) // [ 'design:returntype', 'design:paramtypes', 'design:type', 'c4-key1' ] console.log('c4Result2', c4Result2) // [ 'c4-key2' ] console.log('c4Result3', c4Result3) // [ 'design:type', 'c4-key3' ] console.log('c4Result4', c4Result4) // [ 'design:returntype', 'design:paramtypes', 'design:type', 'c4-key1' ] class C41 extends C4 {} let c41Result1 = Reflect.getMetadataKeys(C41) let c41Result2 = Reflect.getMetadataKeys(C41.prototype, 'method') console.log('C41Result1', c41Result1) // [ 'c4-key2' ] console.log('c41Result2', c41Result2) // [ 'design:returntype', 'design:paramtypes', 'design:type', 'c4-key1' ] /** * get all own metadata keys of an object or property * 获取对象或属性的所有自有元数据键 * let result = Reflect.getOwnMetadataKeys(target) * let result = Reflect.getOwnMetadataKeys(target, propertyKey) */ @Reflect.metadata('c5-key2', 'value2') class C5 { @Reflect.metadata('c5-key4', 'value4') name: string = 'bob' @Reflect.metadata('c5-key1', 'value1') method() { return 'hello' } } let c5Result1 = Reflect.getOwnMetadataKeys(C5.prototype, 'method') let c5Result2 = Reflect.getOwnMetadataKeys(new C5(), 'method') let c5Result3 = Reflect.getOwnMetadataKeys(C5) let c5Result4 = Reflect.getOwnMetadataKeys(C5.prototype, 'name') let c5Result5 = Reflect.getOwnMetadataKeys(new C5(), 'name') console.log('c5Result1', c5Result1) // [ 'design:returntype', 'design:paramtypes', 'design:type', 'c5-key1' ] console.log('c5Result2', c5Result2) // [] console.log('c5Result3', c5Result3) // [ 'c5-key2' ] console.log('c5Result4', c5Result4) // [ 'design:type', 'c5-key4' ] console.log('c5Result5', c5Result5) // [] class C51 extends C5 {} let c51Result1 = Reflect.getOwnMetadataKeys(C51) console.log('c51Result1', c51Result1) // [] /** * delete metadata from an object or property * 从对象或属性上删除元数据 * let result = Reflect.deleteMetadata(metadataKey, target) * let result = Reflect.deleteMetadata(metadataKey, target, propertyKey) */ |