如何在可注入构造函数中添加参数,但仍然让Nest管理依赖注入



我创建了一个自定义保护,如下所示:

@Injectable()
export class MyCustomGuard implements CanActivate {
constructor(
private reflector: Reflector,
private myService: MyService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const idParam = request.params.id;
...
}
}

我在我的控制器中这样使用它:

@UseGuards(MyCustomGuard)
@Controller('my-controller')
export class MyController {
...
}

它工作正常,但我想在实例化保护时将idparam键设置为参数,如下所示:

@Injectable()
export class MyCustomGuard implements CanActivate {
constructor(
private idKey: string,
private reflector: Reflector,
private myService: MyService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const idParam = request.params[idKey];
...
}
}

然后我将不得不在我的控制器中手动实例化防护:

@UseGuards(new MyCustomGuard('id', ...?))
@Controller('my-controller')
export class MyController {
...
}

我的问题是,如果我这样做,那么我将不得不手动实例化我的卫士的其他构造函数参数:反射器和服务。这是可能的,但出于简单性和性能的原因,我宁愿让Nest来管理。那么我的问题是:有没有办法手动实例化保护(这样我就可以给它idKey参数(,但仍然让Nest管理其他参数的依赖注入?在这里,使用ModuleRef似乎可行,但我真的不知道这是否是正确的方法

与其将idKey作为构造函数参数传递,我建议将其反映为类的元数据。这样,你可以做一些类似的事情

@IdKey('id')
@UseGuards(MyCustomGuard)
@Controller('my-controller')
export class MyController {
...
}

在你的护卫下,你会做一些类似的事情

@Injectable()
export class MyCustomGuard implements CanActivate {
constructor(
private reflector: Reflector,
private myService: MyService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const idParam = request.params.id;
const idKey = this.getIdKey(context);
...
}
getIdKey(context: ExecutionContext) {
return this.reflector.get('id-key', context.getClass());
}
}

这是假设你的@IdKey()看起来有点像

export const IdKey = (key: string) => SetMetadata(key);

其中SetMetadata来自@nestjs/common

你可以在这里阅读更多关于@SetMetadata()和元数据反射

最新更新