我想知道是否有一种方法可以访问 NestJS 中的 DI 注入(inject)器并直接使用它来实例化类。这类似于 Angular 或 Inversify 如何直接暴露注入(inject)器以用于特殊情况。
多供应商将解决我的用例。但是,在 NestJS 支持多提供者之前,我尝试创建一个复合保护,将多个保护连接在一起,以便我可以全局应用多个需要访问 DI 的保护。我希望复合保护只接收一个类型数组,然后使用注入(inject)器为这些类型填充对象。
我尝试指定 Injector
作为工厂依赖项,但 Nest 无法解决它。如果它确实解决了,我不知道我将如何使用注入(inject)器。
@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);
}
}
最佳答案
我最近做了类似的事情,但我没有将类型的守卫传递给我的“multiguard”,我只是在工厂中实例化守卫并传递一组守卫实例。
它与 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 {}
另一种可能的选择是注入(inject)
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 {}
关于typescript - 我可以直接访问 DI 注入(inject)器以使用 NestJS 实例化类吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58034509/