Angular 5:从自定义装饰器函数内部使用服务

Posted

技术标签:

【中文标题】Angular 5:从自定义装饰器函数内部使用服务【英文标题】:Angular 5: Using Service from inside Custom Decorator Function 【发布时间】:2018-07-15 21:58:17 【问题描述】:

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

我希望装饰器将它的一些逻辑委托给LoggingService,而这又依赖于应用程序中的其他服务...

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

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

有没有办法让我在那里使用该服务??

谢谢!

【问题讨论】:

问题should contain all related code。请更新它。链接可能会随着时间的推移而损坏。 【参考方案1】:

类装饰器在类定义上执行一次。为了避免在调用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;
  

【讨论】:

这个解决方案比我的好。 该死的我现在好想捂脸……! ? - 谢谢你让我大开眼界:) @estus 创建子模块的好点子,以摆脱循环依赖。但是如何访问InjectorContainerModule 中的根注入器呢?将根注入器显式分配给子模块,或者在InjectorContainerModule 中导入LoggingService 而不是AppModule 您不需要任何额外的措施来做到这一点。 Injector 是 InjectorContainerModule 中的根注入器,除非模块被延迟加载。 感谢这个例子。无论如何都可以在没有创建该装饰组件的实例的情况下调用注入服务?例如,我正在尝试创建一个装饰器,它将维护一个字符串字典到 Type (组件)。简单地说: "FooComponent": FooComponent, "BarComponent": BarComponent - 用于翻译数据库驱动的动态表单,其中字符串存储在数据库中。如果可能的话,我想使用注入,但使用 NgINit 挂钩仅在已经创建实例时才有效。我打算用它在我的动态表单服务中创建实例...【参考方案2】:

试试stackblitz fixed

这将打印出来

LoggingService: HelloComponent - 调用了 ngOnInit

微小的变化 - 基本上使用ReflectiveInjector,如angular Injector#example

import  ReflectiveInjector  from '@angular/core';

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

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

我相信您可以在您的应用模块中使用useExistingLoggingService 作为提供者。

【讨论】:

这种方法的问题是 ReflectiveInjector 创建了一个新的注入器。 OP 声明 LoggingService 又依赖于应用程序中的其他服务...。此要求未反映在示例中,但可能会产生问题,因为这些服务与应用注入器中的实例不同。 很好的评论和方法,但因为他的评论而选择了 Estus 的答案 - 感谢您的帮助!

以上是关于Angular 5:从自定义装饰器函数内部使用服务的主要内容,如果未能解决你的问题,请参考以下文章

闭包和装饰器

闭包和装饰器

什么是Python装饰器

装饰器

闭包和装饰器

python装饰器获取内部函数的变量值