typescript - 我可以直接访问 DI 注入(inject)器以使用 NestJS 实例化类吗

标签 typescript dependency-injection nestjs

我想知道是否有一种方法可以访问 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/

相关文章:

node.js - 如何在 Typescript 中指定我想要的重载函数?

C# Azure Function v3 依赖注入(inject) - 使用 Scrutor 进行程序集扫描

typescript - NestJS:如何将服务从 child 传递给 parent ?

node.js - NodeJS 将 Dtos 映射到 TypeORM 实体

javascript - 如何使用带有 expo 的 React-Navigation 正确键入作为 Prop 传递的导航

angular - 未定义列表对象的属性切片

ASP.net vnext 依赖注入(inject)

node.js - NestJs - 从自定义装饰器内的服务调用方法

Jquery 和 Typescript [ts] Argument of type 'string | number | string[]' is not assignable to parameter of type 'string' .

javascript - 使用 new 运算符时是否可以进行依赖注入(inject)?