【问题标题】:How to read instance decorators in typescript?如何阅读打字稿中的实例装饰器?
【发布时间】:2021-09-30 03:13:39
【问题描述】:

我可以使用reflect-metadata 创建自定义装饰器,它工作正常。

问题是,我不知道如何获取所有实例装饰器。

import 'reflect-metadata';

console.clear();

function readTypes() {
  const decorator: MethodDecorator = (target, propertyKey, description) => {
    const args = Reflect.getMetadata(
      'design:paramtypes',
      target,
      propertyKey
    ).map(c => c.name);
    const ret = Reflect.getMetadata('design:returntype', target, propertyKey);
    console.log(`Arguments type: ${args.join(', ')}.`);
    console.log(`Return type:    ${ret.name}.`);
  };
  return decorator;
}

class Foo {}

class Bar {
  @readTypes()
  public fn(a: number, b: string, c: Foo): boolean {
    return true;
  }
}

const barInstance = new Bar();

我想从barInstance 获取所有带有装饰器@readTypes 的函数。我该怎么做?

查看工作示例: https://stackblitz.com/edit/decorators-metadata-example-nakg4c

【问题讨论】:

    标签: javascript typescript decorator reflect-metadata


    【解决方案1】:

    首先,您没有编写任何元数据,而只是读取它。如果要查找哪些属性被修饰,则必须将元数据写入这些属性。

    为简单起见,让我们将装饰器简化为:

    // It's a best practice to use symbol as metadata keys.
    const isReadTypesProp = Symbol('isReadTypesProp')
    
    function readTypes() {
      const decorator: MethodDecorator = (target, propertyKey, description) => {
        Reflect.defineMetadata(isReadTypesProp, true, target, propertyKey);
      };
      return decorator;
    }
    

    现在,当使用装饰器时,它会在解析类时执行,而不是在创建实例时执行。这意味着装饰器函数中的target实际上是类构造函数的prototype

    换句话说,target 是同一个对象 Bar.prototypebarInstance.constructor.prototypebarInstance.__proto__

    知道我们可以遍历原型对象中的所有属性名称并查找我们之前设置的元数据:

    function getReadTypesPropsFromInstance(object: {
      constructor: {
        prototype: unknown;
      };
    }) {
      const target = object.constructor.prototype;
      const keys = Object.getOwnPropertyNames(target);
      return keys.filter(key => Reflect.getMetadata(isReadTypesProp, target, key));
    }
    

    现在返回装饰属性的名称:

    const barInstance = new Bar();
    console.log(getReadTypesPropsFromInstance(barInstance)); // ["fn"]
    

    Working example

    【讨论】:

      猜你喜欢
      • 2015-06-28
      • 2020-05-31
      • 2018-02-12
      • 2016-04-17
      • 2020-12-24
      • 2018-06-21
      • 2019-07-29
      • 2016-05-08
      • 1970-01-01
      相关资源
      最近更新 更多