Angular 5:在Custom Decorator函数中使用Service

时间:2018-02-05 22:56:24

标签: javascript angular typescript dependency-injection decorator

我正在为调试目的创建一个@Log()装饰器函数;

我希望Decorator将其中的一些逻辑委托给LoggingService,而{{1}}依赖于应用程序中的其他服务......

我一直在尝试很多不同的东西,最简单/最直接的方法是将主(或共享)模块的Injector缓存为模块本身的静态道具(参见下面链接的StackBlitz示例),对于延迟加载的模块,但不适用于急切加载的模块...

非工作poc:https://stackblitz.com/edit/angular-j1bpvx?file=app%2Fdecorator.ts

有没有办法可以在那里使用那个服务?

谢谢!

2 个答案:

答案 0 :(得分:6)

类装饰器在类定义上执行一次。为了在调用AppModule.injector.get(LoggingService)时避免竞争条件,应将其移动到已定义AppModule.injector的位置,即类方法。

should be

constructor.prototype[hook] = function (args) {
  const loggingService = AppModule.injector.get(LoggingService);

  loggingService.log({ ... })
  ...

这也会与AppModule产生紧密耦合,并阻止单元重复使用或单独测试。建议使用另一个对象来保存injector属性,例如分配injector不在主要但在导入到AppModule的子模块中:

export class InjectorContainerModule { 
  static injector: Injector;

  constructor(injector: Injector) {
    InjectorContainerModule.injector = injector;
  }
}

答案 1 :(得分:2)

尝试stackblitz fixed

这将打印

  

LoggingService:HelloComponent - 调用了ngOnInit

轻微更改 - 基本上使用angular Injector#example

中的ReflectiveInjector
import { ReflectiveInjector } from '@angular/core';

const injector = ReflectiveInjector.resolveAndCreate([
  {provide: 'loggingService', useClass: LoggingService}
]);

const loggingService = injector.get('loggingService');

我确信您可以在应用模块中使用useExisting并使用LoggingService作为提供商。