Nest.js如何创建支持自定义配置的@Injectable可注入Pipe?
NestJS Pipe同时支持依赖注入与自定义配置的实现方案
确实存在可以同时满足两个需求的实现方式,核心思路是通过静态工厂方法+闭包保留配置+内部可注入类的组合实现,不需要修改框架原有逻辑,完全兼容Nest的依赖注入体系。
实现步骤
- 为Pipe类编写静态工厂方法,用来接收自定义配置参数
- 在工厂方法内部定义加了
@Injectable装饰器的Pipe实现类,该类可以正常注入其他服务依赖 - 实现类的transform方法可以同时访问闭包中的自定义配置,以及注入的依赖实例
- 工厂方法返回内部定义的可注入类,交给Nest框架完成实例化
完整代码示例
import { Injectable, PipeTransform, ArgumentMetadata } from '@nestjs/common'; import { UserService } from './user.service'; export class UserValidationPipe { // 静态工厂方法,接收自定义配置 static create(config: { allowGuest: boolean, errorMsg?: string }) { @Injectable() class UserValidationPipeImpl implements PipeTransform { // 正常注入依赖,不受配置影响 constructor(private readonly userService: UserService) {} async transform(userId: number, metadata: ArgumentMetadata) { const user = await this.userService.findUserById(userId); // 同时使用外部配置和注入的依赖 if (!user && !config.allowGuest) { throw new Error(config.errorMsg ?? '用户不存在'); } return user ?? null; } } return UserValidationPipeImpl; } }
使用方式
直接在路由参数装饰器中调用工厂方法传入配置即可,框架会自动完成依赖注入和实例化:
import { Controller, Get, Param } from '@nestjs/common'; @Controller('user') export class UserController { @Get(':id') async getUser( // 传入自定义配置,同时框架会自动注入UserService @Param('id', UserValidationPipe.create({ allowGuest: false, errorMsg: '非法用户ID' })) user: any ) { return user; } }
原理解释
- 静态工厂的配置参数会被保存在闭包中,内部类在整个生命周期都可以访问
- 内部实现类添加了
@Injectable装饰器,Nest的DI容器可以正常扫描并注入所需的依赖 - 传入路由装饰器的是可注入类的构造函数,符合框架第一种Pipe实例化规则,依赖注入能力完全保留
如果需要全局复用带配置的Pipe,也可以在模块中使用useFactory自定义Provider的方式实现,本质逻辑和上述方案一致。
内容的提问来源于stack exchange,提问作者Łukasz Ostrowski
相关产品推荐
相关产品推荐

