访问类内的元注释(TypeScript)

时间:2015-12-25 18:10:31

标签: 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?

}

4 个答案:

答案 0 :(得分:20)

使用新的角度版本,您应该使用本机Reflect对象。没有IE11的支持:

const annotations = Reflect.getOwnPropertyDescriptor(MyModule, '__annotations__').value;

阅读Jeff Fairley关于如何处理数据之后的答案

<击> 您可以将注释/装饰器视为普通函数调用。对于此功能,&#39;类/功能&#39;对象(非实例)在第一个参数中发送,而参数(元数据)在第二个参数中发送。

然而,如果某些东西被添加到类的原型(糟糕的做法/暴露属性),它依赖于该函数的实现。 TypeScript编译器和Angular2虽然做了不同的事情。

他们使用由TypeScript编译器生成的__decorate__metadata函数。数据将添加Object.defineProperty()函数。负责此事件的包是Reflect。 (引擎盖下使用Object.defineProperty()函数和WeakMap)。

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

TLDR;

    <击>
  • 要从angular2中的类/组件中获取注释,您就可以了 使用:

    Reflect.getMetadata('annotations', ComponentClass); //@Component({}), @Pipe({}), ...
    
  • 要从angular2中的构造函数参数获取注释,您必须使用:

    Reflect.getMetadata('parameters', ComponentClass); //@Inject()
    
  • 要从angular2中的类中的属性获取注释, 必须使用:

    Reflect.getMetadata('propMetadata', ComponentClass); //@HostBinding(), @Input(), ...
    

    <击>

答案 1 :(得分:2)

@PierreDuc's answer 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...

我还没有将我的应用升级到Angular 6,所以我没有确认这没有改变。

相关:

答案 2 :(得分:0)

我们正在使用此解决方案,发现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);
  });
}

由于它处理的是正确的类型和接口,因此也获得了林特批准!

答案 3 :(得分:0)

正如John Neuhaus所说,角度翻译在aot编译时只删除 annotations 属性。因此,我们可以执行ng serve --aot=false,现在您执行console.dir(AppComponent);

时可能会显示注释