如何在 Angular 中检索组件的元数据

How to retrieve a component's metadata in Angular

一个 Angular 组件有装饰器:

@Component({ ... })
export class MyAngularComponent {
  @Input() myInputParam: MyType;
  @Input() myOtherInputParam: MyOtherType;
  @Output() myOutputParam: MyOtherOutputType;
}

我有一个 Angular 库,如果我能以编程方式检索其中的 Angular 的 @Input() 装饰器,可以避免大量代码重复(并减少包大小)给定的组件 class (虽然属于库).

但我对这种实现的可移植性存有疑虑。我在某处读到,如果 Angular 应用程序是在启用 AoT 的情况下构建的(并且假定仅使用 Angular 装饰器),则不需要 Reflect polyfill(需要在运行时读取装饰器)。所以我想我不能只使用 Reflect.*。 Angular 如何存储装饰器?是否有一种可靠的、面向未来的方式来阅读它们?

缩小应该不是问题,因为它只用于读取库组件的装饰器,所以我可以控制它。

那么,如果这可以以一种可移植的方式实现(或者不可行,否则我仍然感兴趣),我该如何阅读这些装饰器?

I've read somewhere that the Reflect polyfill (needed to read decorators at runtime) isn't needed if the Angular app has been built with AoT enabled... How does Angular stores the decorators?

事实上,Angular 计划甚至在 运行时 中删除对 Reflect 对象的依赖。因此,在最新的 v5 中,Reflect.defineMetadata 已被替换为 makeDecorator 中的 Object.defineProperty,后者负责将元数据附加到 class。这是相关代码:

export const ANNOTATIONS = '__annotations__';
export function makeDecorator(
    ...
    const TypeDecorator: TypeDecorator = <TypeDecorator>function TypeDecorator(cls: Type<any>) {
      // Use of Object.defineProperty is important since it creates non-enumerable property which
      // prevents the property is copied during subclassing.
      const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
          (cls as any)[ANNOTATIONS] :
          Object.defineProperty(cls, ANNOTATIONS, {value: []})[ANNOTATIONS]; <-----
      annotations.push(annotationInstance);
      return cls;
    };

这意味着在 v5 中,您可以像这样访问组件 class 上的装饰器:

export class AppComponent {
    constructor() {
        console.log((<any>AppComponent).__annotations__);
    }

Is there a reliable, future-proof way to read them? I don't think there's anything future-proof with Angular.

使用 AOT 编译应用程序时 Angular 使用静态代码分析并严重依赖 TS 编译器生成的 AST。如果您有兴趣在构建时访问装饰器,我想这是可行的方法,我将其称为最有前途的解决方案。