繁体   English   中英

可以使用typescript属性装饰器为类设置元数据吗?

[英]can typescript property decorators set metadata for the class?

在typescript中,是否可以使用属性装饰器为类设置元数据? 请考虑以下代码。 类装饰器的“目标”显然与属性装饰器的“目标”不同。 我可以从另一个中获得一个吗?

import 'reflect-metadata';


const MY_CLASS_DECORATOR_KEY = 'MyClassDecoratorKey';
const MY_PROPERTY_DECORATOR_KEY = 'MyPropertyDecoratorKey';

export const MyClassDecorator = options => {
    return function (target) {
      console.log('class target: ' , target);
      Reflect.defineMetadata(MY_CLASS_DECORATOR_KEY, options, target);
    };
};

export const MyPropertyDecorator = (options): PropertyDecorator => {
    return (target, property) => {
      console.log('property target: ' , target);
      const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, target) || {};
      metadata[property] = options;
      Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, target);
    };
};

@MyClassDecorator('my class decorator value')
class MyClass {
    @MyPropertyDecorator('first my property decorator value')
    myFirstProperty: any;

    @MyPropertyDecorator('second my property decorator value')
    mySecondProperty: any;
}

console.log('keys: ', Reflect.getMetadataKeys(MyClass));

注意输出:

property target:  MyClass {}
property target:  MyClass {}
class target:  function MyClass() {
    }
keys:  [ 'MyClassDecoratorKey' ]

如何获取元数据键以显示属性装饰器中的键?

是的,你可以自由地在你的装饰工作中做任何你想做的事情,但是当你发现时,你的问题就在于你正在通过的目标。

基本上,在属性装饰器中, target参数可以是两件事之一,具体取决于装饰器是用于静态属性还是实例属性:

在静态属性上, target属性将是类构造函数 这意味着在静态属性上,目标将与类装饰器完全相同。

但是,在实例属性上, target参数将是您创建的类的prototype ,而不是构造函数。 这就是你看到你所看到的行为的原因。 对于实例属性,您的元数据未附加到constructor就像类装饰器一样。

但仍然有希望,因为你可以很容易地获得给定一个原型实例的构造函数,因为它存储在一个名为constructor的属性中。 因此,在您的情况下,您可以通过执行以下操作获得您正在寻找的行为:

export const MyPropertyDecorator = (options): PropertyDecorator => {
    return (target, property) => {
      var classConstructor = target.constructor;
      console.log('property target: ' , classConstructor);
      const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, classConstructor) || {};
      metadata[property] = options;
      Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, classConstructor);
    };
};

注意:上述更改适用于实例属性,但不适用于静态属性。 如果需要处理这两种类型的属性,则需要添加一些额外的逻辑来确定是使用target还是target.constructor

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM