访问类内的元注释(TypeScript)

Hof*_*off 16 typescript angular

当我在TypeScript中使用元数据注释类时,例如创建一个Angular2组件,我可以访问该类中的元数据吗?

import {Component} from 'angular2/core';

@Component({
    selector: 'app',
    templateUrl: '/app/components/app/app.component.html'
})
export class AppComponent {

    // can I access 'templateUrl' from above annotation here?

}
Run Code Online (Sandbox Code Playgroud)

Pie*_*Duc 20

您可以将注释/装饰器视为普通函数调用.对于此函数,"类/函数"对象(非实例)将在第一个参数中发送,而参数(元数据)在第二个参数中发送.

但是,如果将某些内容添加到类的原型(糟糕的做法/暴露属性),它将取决于该函数的实现.TypeScript编译器和Angular2的工作方式不同.

它们使用由TypeScript编译器生成的Reflect和__decorate函数.使用Object.defineProperty()函数添加数据.对此负责的包是Reflect.(引擎盖下使用的__metadata功能与a组合Object.defineProperty()).

该函数WeakMap用于设置注释,并获得明显的注释Reflect.defineMetadata().

TLDR;


Jef*_*ley 6

@PierreDuc的答案在Angular 5中对我不起作用。我做了一些进一步的阅读(很抱歉,我找不到共享的所有相关链接),并提出了以下内容:

let decorator: Type<any>;
// you can cast the component class
decorator = (<any>AppComponent).__annotations__[0];
// or use with lodash.get
decorator = get(AppComponent, '__annotations__[0]');

//
// obviously, this is an array, and based on your app,
// you may have multiple decorators on one class, so iterate them
//


// if you want to just grab some data from the @Component:
const templateUrl: string = decorator.templateUrl;
// or from a @NgModule:
const declarations: Type<any>[] = decorator.declarations;


// or if you're trying to decide whether this is in fact a component:
if (decorator instanceof Component) {
  // do things
}
// or a provider
if (decorator instanceof Injectable) {
  // do different things
}
// or a module:
if (decorator instanceof NgModule) {
  // do things
}

// etc...
Run Code Online (Sandbox Code Playgroud)

我尚未将我的应用程序升级到Angular 6,因此我还没有验证这没有更改。

有关:


Joh*_*aus 6

我们正在使用这个解决方案,发现 AOT 被删除了__annotations__(这也是--prod构建的默认值),这对我们来说是不行的。

幸运的是,如果您正在处理组件,那么有一种替代方案可以在这两种组件中工作并且不使用字符串:

const components = [ MyComponent ];
/*
  ...
  Anything that can be injected into
*/
constructor(private componentFactoryResolver: ComponentFactoryResolver) {
  // For each component
  components.forEach(element => {
    // Get its resolved factory
    const factory = this.componentFactoryResolver.resolveComponentFactory(element);

    console.log('Factory:', factory);
    console.log('Selector:', factory.selector);
  });
}
Run Code Online (Sandbox Code Playgroud)

由于它处理正确的类型和接口,因此它也得到了 linter 的批准!