有没有一种比下面更好的方法将服务或组件注入到导入的模块中?
export interface AmqpInterceptor{
after(message:any):Promise<void>;
}
export class AmqpInterceptors extends Array<AmqpInterceptor>{
}
//generic library module
@Module({
providers:[{
provide: AmqpInterceptors,
useValue: []
}]
}
export class AMQPModule implements OnModuleInit{
static register(options: AMQPOptions): DynamicModule {
const providers = options.providers || []
return {
module: AMQPModule,
providers: [
...providers,
OtherProvider
]
}
}
}
//end user module
@Module({
imports: [
AMQPModule.register(({
// I had to create a factory method to pass providers as an argument.
// I would think that it is not a good practice
providers: [{
provide:AmqpInterceptors,
useValue:[MyCustomInterceptor]
}]
})
],
providers: [
]
})
export class QueueModule {
}
当前有效的解决方案:我在通用模块中声明了一个默认的空数组,并在工厂方法中声明了允许在模块构造中传递自定义值的工厂方法。(在我最幸福的世界中,我声明了一个接口的多个实例,然后DI收集了所有这些实例,但是我认为这在NestJs中实际上是不可能的)
您可以使用@ golevelup / nestjs-discovery之类的软件包来帮助您。
基本上,您必须执行以下操作:
// AMQP模块
// amqp-interceptor.decorator.ts
import { SetMetadata } from '@nestjs/common';
export function AmqpInterceptor() {
return SetMetadata('AMQP_INTERCEPTOR', true)
}
// amqp-explorer.ts
import { OnModuleInit } from '@nestjs/common'
@Injectable()
export class AmqpExplorer implements OnModuleInit {
constructor(
private readonly discoveryService: DiscoveryService,
) {}
async onModuleInit(): Promise<void> {
const amqpInterceptorProviders = await this.discoveryService.providers('AMQP_INTERCEPTOR')
// you can store this list, to be queried by some
// other provider to use interceptors, etc.
}
}
// amqp.module.ts
@Module({ providers:[AmqpExplorer]})
export class AMQPModule { }
//最终用户模块
// end-user.module.ts
@Module({ imports:[AMQPModule], providers: [SomeAmqpInterceptor] })
export class EndUserModule { }
// some-amqp.interceptor.ts
@Injectable()
@AmqpInterceptor()
export class SomeAmqpInterceptor {
run(): void { console.log('intercepting') }
}
Obs:
AMQP_INTERCEPTOR
字符串可能会与其他一些元数据发生冲突,这是一个好习惯,在模块中添加更具体的内容以避免两个元数据具有相同的元数据import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator'
export class Runner {
constructor(
private readonly handler: DiscoveredMethodWithMeta,
private readonly externalContextCreator: ExternalContextCreator,
) { }
run(): void {
const handler = this.externalContextCreator.create(
this.handler.discoveredMethod.parentClass.instance,
this.handler.discoveredMethod.handler,
this.handler.discoveredMethod.methodName,
)
const handlerResult = await handler(content)
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句