如何从方法装饰器访问类装饰器定义的元数据?
为什么方法装饰器里读不到类装饰器定义的元数据?怎么解决?
这个问题我之前也踩过坑,核心原因很简单:你把元数据存在了类的构造函数上,但方法装饰器里却从类的原型对象上去读,这俩是完全不同的对象,自然拿不到数据!
具体原因拆解
咱们来捋清楚两个装饰器里target的区别:
- 类装饰器中的
target:是类本身(构造函数),比如你的LoginClass这个函数对象。你用Reflect.defineMetadata把topic存在了这个构造函数上。 - 方法装饰器中的
target:是类的原型对象(也就是LoginClass.prototype),这是另一个独立的对象,和构造函数不是一回事,所以读它上面的topic元数据自然返回undefined。
两种解决方案
方案一:把元数据存在类的原型上(修改类装饰器)
直接在类装饰器里把元数据绑定到原型对象上,这样方法装饰器的target就是原型,能直接读取:
function ClassDecorator(topic?: string): ClassDecorator { return (target) => { Reflect.defineMetadata('topic', topic, target.prototype); // 绑定到原型 return target; }; }
这时候方法装饰器里原有的代码就能正常输出metaData is: auth了。
方案二:从原型的构造函数上读取元数据(修改方法装饰器)
如果不想改动类装饰器的存储逻辑,也可以在方法装饰器里通过原型的constructor属性拿到类的构造函数,再读取元数据:
function MethodDecorator(options: methodDecoratorOptions) { return function (target, propertyKey: string, descriptor: PropertyDescriptor) { // 通过target.constructor获取类的构造函数,也就是类装饰器里的target console.log('metaData is: ', Reflect.getMetadata('topic', target.constructor)); } }
这种方式不需要修改类装饰器,同样能拿到正确的topic值。
额外提醒
Reflect.metadata的元数据是和具体对象绑定的,不同对象之间的元数据是完全独立的。所以一定要确保存储元数据的对象和读取元数据的对象是同一个,或者有明确的关联路径(比如原型和构造函数的关系)。
内容的提问来源于stack exchange,提问作者tmuecksch
相关产品推荐
相关产品推荐

