如何从方法装饰器访问类元数据
Posted
技术标签:
【中文标题】如何从方法装饰器访问类元数据【英文标题】:How to access class metadata from method decorator 【发布时间】:2018-06-28 18:52:33 【问题描述】:我有两个装饰器。一个类装饰器和一个方法装饰器。 类装饰器定义了我想在方法装饰器中访问的元数据。
类装饰器:
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));
这是我的类定义:
@ClassDecorator('auth')
export class LoginClass
@MethodDecorator(
cmd: 'login'
)
myMethod()
console.log('METHOD CALLED');
问题:
MethodDecorator 的以下行返回metaData is: undefined
。为什么未定义?
console.log('metaData is: ', Reflect.getMetadata('topic', target));
问题:
如何从 MethodDecorator 访问 ClassDecorator 定义的元数据?
【问题讨论】:
【参考方案1】:问题在于装饰器的执行顺序。首先执行方法装饰器,然后执行类装饰器。如果您考虑一下,这是有道理的,类装饰器需要完整的类来操作,而创建类涉及创建方法并首先调用它们的装饰器。
一个简单的解决方法是方法装饰器注册一个回调,然后在设置主题后由类装饰器调用:
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');
【讨论】:
但老实说,我不喜欢这种解决方法。对我来说似乎不太可读。希望能找到更好的解决方案。 我不知道另一种解决方法,它确实使代码更难阅读.. 但是装饰器再次成为您的基础架构的一部分,您将编写一次并使用多次,以及使用的装饰器没有改变,我认为这是更重要的部分 您可以取消标记答案并等待更好的解决方法,我不介意:)。但是我已经看到并使用了类似的解决方法来解决这个问题,但还没有找到更好的解决方法,只是这个主题的变体(例如使用静态类字段而不是 Reflect` api) 我不是故意冒犯你的。我非常感谢我现在确实理解了这个问题。我不明白为什么开发人员选择了装饰器执行的顺序。也许他们有这样做的原因,但对我来说这很不方便。 @tmuecksch 没有冒犯,真的:)。我确信某处有一个标准可以强制执行此操作。而且我相信他们考虑了另一种方式,但是对于大多数用例来说,这种顺序更有意义,不幸的是不适合你以上是关于如何从方法装饰器访问类元数据的主要内容,如果未能解决你的问题,请参考以下文章