InjectRepository 在 NestJS 内部如何工作?

Mis*_*r M 16 dependency-injection node.js typeorm nestjs

在nestjs中,我明白

imports: [
    TypeOrmModule.forFeature([TaskRepository]),
],
Run Code Online (Sandbox Code Playgroud)

创建某种类型的提供者令牌,这样我就可以使用此令牌将存储库注入我的服务(在同一模块中)。

我不明白的是@InjectRepository()内部是如何工作的,例如:

constructor(
    @InjectRepository(TaskRepository)
    private taskRepository: TaskRepository,
  ) {}
Run Code Online (Sandbox Code Playgroud)

InjectRepository自定义装饰器(应该使用 创建的)如何createParamDecorator能够注入在模块中注册的提供者?我研究了一下,发现createParamDecorator没有能力使用DI。如果createParamDecorator只是创建一个新TaskRepository实例并返回它,那么为什么我需要TypeOrmModule.forFeature在模块中导入?有人可以解释一下这在内部是如何工作的吗?谢谢!

Jay*_*iel 20

您走在正确的道路上,但是@InjectRespoitory()createParamDecorator()通常是两种不同的装饰器类型。是的,它们都适用于参数,但它们通常有不同的用例。

createParamDecorator适用于控制器、解析器和网关路由处理程序,以便 Nest 可以知道reqcontextpayload对象的哪一部分(或您想要获取的任何其他部分ExecutionContext)应放入路由处理程序的参数位置。其背后的代码有点复杂,但如果您真的很好奇,我可以向您指出。

@InjectRepository()另一方面是@Inject()它的扩展,它采用当前传递的实体/存储库并使用一些逻辑来创建新的注入令牌。一般来说,这个逻辑<EntityName>Repository有时会被connection添加到其中。TypeormModule.forFeature()该令牌与为同一实体创建的令牌相匹配。(旁注:如果传递的实体是存储库,则令牌仅<EntityName>包含可选连接(如果不是默认连接)。

您可以尝试一下,但摆脱@InjectRepository()@Inject()仅用于测试目的,但我不建议在生产服务器实例中这样做。出错的机会太多了。

这里需要注意的真正重要的事情是它@InjectRepository()实际上并没有注入任何东西。它只是设置元数据供 Nest 读取并匹配自定义提供程序。TypeormModule.forFeature()实际上,这里的繁重工作是创建一个具有匹配注入令牌的自定义提供程序,并为该提供程序提供正确的值。

顺便说一句,@InjectRepository()并且TypeormModule.forFeature()必须一起工作,因为 Typescript 无法正确反映泛型。通常,使用 Nest,我们可以使用类名作为注入令牌,但类似的东西Repository<TaskEntity>会返回Repository,因此 Nest 不知道要注入哪个存储库。通过使用@InjectRepository()装饰器,我们可以设置注入令牌元数据并覆盖反射的类值。