如何从方法装饰器访问 class 元数据
How to access class metadata from method decorator
我有两个装饰器。一个 class 装饰器和一个方法装饰器。
class 装饰器定义了我想在方法装饰器中访问的元数据。
Class装饰者:
function ClassDecorator(topic?: string): ClassDecorator {
return (target) => {
Reflect.defineMetadata('topic', topic, target);
// I've also tried target.prototype instead of target
return target;
};
}
方法装饰器:
interface methodDecoratorOptions {
cmd: string
}
function MethodDecorator(options: decoratorOptions) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
// HERE IS MY PROBLEM
console.log('metaData is: ', Reflect.getMetadata('topic', target));
}
}
这是我的 Class 定义:
@ClassDecorator('auth')
export class LoginClass {
@MethodDecorator({
cmd: 'login'
})
myMethod() {
console.log('METHOD CALLED');
}
}
问题:
MethodDecorator 的下面一行 returns metaData is: undefined
。为什么未定义?
console.log('metaData is: ', Reflect.getMetadata('topic', target));
问题:
如何从 MethodDecorator 访问由 ClassDecorator 定义的元数据?
问题在于装饰器的执行顺序。方法装饰器先执行, class 装饰器在后执行。如果您考虑一下,这是有道理的,class 装饰器需要完整的 class 来执行,而创建 class 涉及创建方法并首先调用它们的装饰器。
一个简单的解决方法是让方法装饰器注册一个回调,然后在设置主题后由 class 装饰器调用:
function ClassDecorator(topic?: string): ClassDecorator {
return (target) => {
Reflect.defineMetadata('topic', topic, target.prototype);
let topicFns: Array<() => void> = Reflect.getMetadata("topicCallbacks", target.prototype);
if (topicFns) {
topicFns.forEach(fn => fn());
}
return target;
};
}
interface methodDecoratorOptions {
cmd: string
}
function MethodDecorator(options: methodDecoratorOptions) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let topicFns: Array<() => void> = Reflect.getMetadata("topicCallbacks", target);
if (!topicFns) {
Reflect.defineMetadata("topicCallbacks", topicFns = [], target);
}
topicFns.push(() => {
console.log('metaData is: ', Reflect.getMetadata('topic', target));
});
}
}
@ClassDecorator('auth')
class LoginClass {
@MethodDecorator({
cmd: 'login'
})
myMethod() {
console.log('METHOD CALLED');
}
}
我有两个装饰器。一个 class 装饰器和一个方法装饰器。 class 装饰器定义了我想在方法装饰器中访问的元数据。
Class装饰者:
function ClassDecorator(topic?: string): ClassDecorator {
return (target) => {
Reflect.defineMetadata('topic', topic, target);
// I've also tried target.prototype instead of target
return target;
};
}
方法装饰器:
interface methodDecoratorOptions {
cmd: string
}
function MethodDecorator(options: decoratorOptions) {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
// HERE IS MY PROBLEM
console.log('metaData is: ', Reflect.getMetadata('topic', target));
}
}
这是我的 Class 定义:
@ClassDecorator('auth')
export class LoginClass {
@MethodDecorator({
cmd: 'login'
})
myMethod() {
console.log('METHOD CALLED');
}
}
问题:
MethodDecorator 的下面一行 returns metaData is: undefined
。为什么未定义?
console.log('metaData is: ', Reflect.getMetadata('topic', target));
问题:
如何从 MethodDecorator 访问由 ClassDecorator 定义的元数据?
问题在于装饰器的执行顺序。方法装饰器先执行, class 装饰器在后执行。如果您考虑一下,这是有道理的,class 装饰器需要完整的 class 来执行,而创建 class 涉及创建方法并首先调用它们的装饰器。
一个简单的解决方法是让方法装饰器注册一个回调,然后在设置主题后由 class 装饰器调用:
function ClassDecorator(topic?: string): ClassDecorator {
return (target) => {
Reflect.defineMetadata('topic', topic, target.prototype);
let topicFns: Array<() => void> = Reflect.getMetadata("topicCallbacks", target.prototype);
if (topicFns) {
topicFns.forEach(fn => fn());
}
return target;
};
}
interface methodDecoratorOptions {
cmd: string
}
function MethodDecorator(options: methodDecoratorOptions) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let topicFns: Array<() => void> = Reflect.getMetadata("topicCallbacks", target);
if (!topicFns) {
Reflect.defineMetadata("topicCallbacks", topicFns = [], target);
}
topicFns.push(() => {
console.log('metaData is: ', Reflect.getMetadata('topic', target));
});
}
}
@ClassDecorator('auth')
class LoginClass {
@MethodDecorator({
cmd: 'login'
})
myMethod() {
console.log('METHOD CALLED');
}
}