typescript Angular |将服务注入装饰器

x33g5p2x  于 2023-03-04  发布在  TypeScript
关注(0)|答案(4)|浏览(152)

我试图将一个服务注入到我正在创建的装饰器函数中,这样我就可以获得存储在变量内部的内容。
我目前有一个基本的装饰设置。

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

在我使用它的地方,它要求我输入第二个参数,这显然需要注入依赖项。
我还尝试了函数中不允许的@Inject(Service)
有什么办法能让我做到吗?
或者可以在装饰器中获得父类变量吗?

eqoofvh9

eqoofvh91#

装饰器是一个TypeScript特性,在Angular的依赖注入系统之外工作。
我所知道的唯一解决方案是创建一个特殊的服务,它将向装饰器公开依赖项。

@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
    }
}
oipij1gg

oipij1gg2#

我知道我迟到了,但是,还有另一种选择,以访问一个装饰服务。
在需要必要维修的模块中暴露Angular的注射器:

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

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

通过Module injector属性从Decorator内部获取服务:

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;
  };
};
vshtjzan

vshtjzan3#

Angular 依赖注入只在依赖于另一个服务的组件类或Angular 服务中起作用。
依赖项的消费者是Angular 组件,它在其构造函数中声明它需要什么,并让框架提供它们。
有关依赖注入的更多信息,请参考官方Angular 文档:
Dependency Injection in action
https://next.angular.io/guide/dependency-injection-in-action

jw5wzhpr

jw5wzhpr4#

改进/更新@Ricky的答案。
从Angular 14+工作,不需要在提供者列表中有服务。我也有很多懒惰加载模块的问题,所以我直接在我的AppModule中添加了注入器,现在可以从任何地方获得。
App.module.ts

export class AppModule {
  static injector: Injector;

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

my-decorator.ts

import { AppModule } from './app.module';
import { MyService } from './my.service';

export const MyDecorator = (params: unknown): any => {
  return (component: Function) => {
    const service = AppModule.injector.get<MyService>(
      MyService
    );

    console.log(component, params, service);
  };
}

相关问题