我想知道是否有一种方法可以访问NestJS中的DI注入器并直接使用它来实例化类。这将类似于Angular或Inversify如何在特殊情况下直接暴露注入器。
多提供商可以解决我的用例。但是,在NestJS中支持多提供者之前,我正在尝试创建一个复合防护,将多个防护连接在一起,这样我就可以全局地应用需要访问DI的多个防护。我希望复合保护只接收一个类型数组,然后使用注入器来填充这些类型的对象。
我尝试将Injector指定为工厂依赖项,但Nest无法解析它。如果问题解决了,我不知道该如何使用注射器。
@Module({
providers: [{
provide: APP_GUARD,
inject: [Injector],
useFactory: (injector: Injector) => {
return new MultiGuard([AuthGuard, PermissionGuard], injector);
}
}]
})
class AppModule {}import { CanActivate, ExecutionContext, Type } from '@nestjs/common';
export class MultiGuard implements CanActivate {
constructor(
private readonly guards: Type<CanActivate>[],
private readonly injector: Injector
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const guards = this.guards.map(guard => {
return this.injector.get(guard);
});
const results = await Promise.all(guards);
return results.every(r => !!r);
}
}发布于 2019-10-19 20:51:34
我最近做了一些类似的事情,但并没有将不同类型的卫士传递给我的“多重卫士”,我只是在工厂中实例化了卫士,并传递了一组卫士实例。
这与NestJS执行守卫的方式非常相似。请看一下guard-consumer.ts文件。
https://github.com/nestjs/nest/blob/master/packages/core/guards/guards-consumer.ts
@Injectable()
export class GuardsCollection implements CanActivate {
public constructor(private readonly guards: CanActivate[]) {}
public async canActivate(context: ExecutionContext): Promise<boolean> {
for (const guard of this.guards) {
const result = guard.canActivate(context);
if (!(await this.pickResult(result))) {
return false;
}
}
return true;
}
private async pickResult(result: boolean | Promise<boolean> | Observable<boolean>): Promise<boolean> {
if (result instanceof Observable) {
return result.toPromise();
}
return result;
}
}在工厂中,我实例化我的守卫。如果我的守卫有任何依赖关系,我可以通过在Inject数组中指定依赖关系来解析它们。可选的inject属性接受一个提供程序数组,NestJS将在实例化过程中解析该数组并将其作为参数传递给工厂函数。
@Module({
providers: [
{
provide: APP_GUARD,
useFactory: (reflector: Reflector) => {
return new GuardsCollection([
new (AuthGuard('jwt'))(),
new RolesGuard(reflector),
]);
},
inject: [Reflector],
},
],
})
export class AuthModule {}另一种可能的选择是注入ModuleRef,并使用它来解析当前模块上下文中的项。您还应该能够从另一个模块获取项目,只要另一个模块被导入到当前模块中。
@Injectable()
export class MyGlobalGuard implements CanActivate {
public constructor(private readonly moduleRef: ModuleRef) {}
public async canActivate(context: ExecutionContext): Promise<boolean> {
// ... resolve items.
return true;
}
}
@Module({
providers: [
{
provide: APP_GUARD,
useClass: GlobalGuard,
},
],
})
export class AuthModule {}https://stackoverflow.com/questions/58034509
复制相似问题