角 |将服务注入装饰器

Posted

技术标签:

【中文标题】角 |将服务注入装饰器【英文标题】:Angular | Inject service into decorator 【发布时间】:2019-03-10 22:47:35 【问题描述】:

我正在尝试将服务注入到我正在创建的装饰器函数中,这样我就可以获取存储在变量中的内容。

我目前有一个基本的装饰器设置。

export function canEdit(editName: string, service: Service) 
      return function (constructor: any) 
          console.log(constructor);
      

我在哪里使用它,它要求我输入第二个参数,显然需要注入依赖项。

我还尝试了函数中不允许的@Inject(Service)

有没有办法可以做到这一点?

或者是否可以在装饰器中获取父类变量?

【问题讨论】:

【参考方案1】:

我知道我迟到了,但是,还有另一种方法可以在装饰器中访问服务。

在需要必要服务的模块中暴露 Angular 的 Injector:

@NgModule(
  declarations: [],
  imports: [],
  providers: [SomeService]
)
export class SharedModule 
  static injector: Injector;

  constructor(injector: Injector) 
    SharedModule.injector = injector;
  

通过模块注入器属性从装饰器内部获取服务:

export const MyDecorator = (): any => 

  return (target: object, key: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor => 
    const originalMethod = descriptor.value;

    descriptor.value = function(...args: any[]): any 
      // access the service
      const service = SharedModule.injector.get<SomeService>(SomeService);

      // (...)
    ;

    return descriptor;
  ;
;

【讨论】:

【参考方案2】:

装饰器是在 Angular 的依赖注入系统之外工作的 TypeScript 功能。

我知道的唯一解决方案是创建一个特殊服务,将依赖项暴露给装饰器。

@Injectable()
export class DecoratorService 
     private static service: Service | undefined = undefined;
     public constructor(service: Service) 
         DecoratorService.service = service;
     
     public static getService(): Service 
         if(!DecoratorService.service) 
             throw new Error('DecoratorService not initialized');
         
         return DecoratorService.service;
     

您现在可以通过上述类访问注入的服务。

export function canEdit(editName: string) 
      return function (constructor: any) 
          const service = DecoratorService.getService();
          // ^^^ access dependency here
          console.log(constructor);
      

除非 Angular 应用程序中的某些内容依赖于 DecoratorService,否则上述内容将不起作用,因为 Angular 在需要时会创建实例。所以你可以将它注入到一个模块中来强制它被初始化。

@NgModule(
    provides: [
        DecoratorService
    ]
)
export class MainModule 
    public constructor(service: DecoratorService) 
                      // ^^^ forces an instance to be created
    

【讨论】:

嗨,我遇到的唯一问题是我收到此错误DecoratorService not initialized。我已经把它放在模块里了。 @tallent123 表示在模块加载之前正在执行装饰器。你是如何使用装饰器的? 我有一个服务,我在函数 `@CanEdit('this_function') 上方输入。据我所知,该功能是在应用程序初始化之后,因为它实际上并没有被调用,直到您单击主屏幕上的按钮 如果模块在检查装饰器后加载(所有服务定位器都是空的)我没有看到解决方案 =( @ShacharHar-Shuv 如果在依赖项初始化之前调用装饰器......这不会使答案无效吗?【参考方案3】:

Angular Dependancy 注入仅适用于依赖于另一个服务的组件类或 Angular 服务。

依赖的消费者,即角度组件,在其构造函数中声明它需要什么,并让框架提供它们。

有关依赖注入的更多信息,请参阅官方 Angular 文档:

Dependency Injection in action

https://next.angular.io/guide/dependency-injection-in-action

【讨论】:

那么有没有办法把这个放到装饰器里面呢?

以上是关于角 |将服务注入装饰器的主要内容,如果未能解决你的问题,请参考以下文章

将变量传递给注入的服务以用作装饰器参数

在装饰器中使用全局嵌套模块

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

quarkus依赖注入之八:装饰器(Decorator)

GetIt/Injectable 在抽象类上缺少可注入装饰器?

TypeScript(21): 装饰器