首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我是否可以直接访问DI注入器以使用NestJS实例化类

我是否可以直接访问DI注入器以使用NestJS实例化类
EN

Stack Overflow用户
提问于 2019-09-21 04:01:42
回答 1查看 1.9K关注 0票数 4

我想知道是否有一种方法可以访问NestJS中的DI注入器并直接使用它来实例化类。这将类似于Angular或Inversify如何在特殊情况下直接暴露注入器。

多提供商可以解决我的用例。但是,在NestJS中支持多提供者之前,我正在尝试创建一个复合防护,将多个防护连接在一起,这样我就可以全局地应用需要访问DI的多个防护。我希望复合保护只接收一个类型数组,然后使用注入器来填充这些类型的对象。

我尝试将Injector指定为工厂依赖项,但Nest无法解析它。如果问题解决了,我不知道该如何使用注射器。

代码语言:javascript
复制
@Module({
    providers: [{
        provide: APP_GUARD,
        inject: [Injector],
        useFactory: (injector: Injector) => {
            return new MultiGuard([AuthGuard, PermissionGuard], injector);
        }
    }]
})
class AppModule {}
代码语言:javascript
复制
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);
    }
}
EN

回答 1

Stack Overflow用户

发布于 2019-10-19 20:51:34

我最近做了一些类似的事情,但并没有将不同类型的卫士传递给我的“多重卫士”,我只是在工厂中实例化了卫士,并传递了一组卫士实例。

这与NestJS执行守卫的方式非常相似。请看一下guard-consumer.ts文件。

https://github.com/nestjs/nest/blob/master/packages/core/guards/guards-consumer.ts

代码语言:javascript
复制
@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将在实例化过程中解析该数组并将其作为参数传递给工厂函数。

代码语言:javascript
复制
@Module({
  providers: [
    {
      provide: APP_GUARD,
      useFactory: (reflector: Reflector) => {
        return new GuardsCollection([
          new (AuthGuard('jwt'))(),
          new RolesGuard(reflector),
        ]);
      },
      inject: [Reflector],
    },
  ],
})
export class AuthModule {}

另一种可能的选择是注入ModuleRef,并使用它来解析当前模块上下文中的项。您还应该能够从另一个模块获取项目,只要另一个模块被导入到当前模块中。

代码语言:javascript
复制
@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 {}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58034509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档