上下文
我目前正在从事一个类型记录Lambda项目,我们计划重构我们的代码,以便使用Tsyringe库使用依赖注入。我们有一个典型的项目MVC结构,除了Repo/Database层之外,我们还有一个代理层,它通过rest调用第三方服务来获取所需数据。

问题是代理层将定义一个接口,并且它将有多个实现,其中一个需要根据业务决策进行注入。例如,AuthProxy是一个包含登录方法的接口,它有两个不同的实现类KeycloakAuthProxyImpl和AuthZeroAuthProxyImpl。这两个实现将位于两个单独的文件夹中,例如AuthZero和KeyCloak,在构建时我们传递一个参数,如--folderName,因此在运行时只有一个实现可以用于依赖项注入。
问题
Tsyringe (我也评估过其他一些库)面临的问题是,基于接口的依赖注入需要在ioc-container页面(在我的例子中是处理程序函数文件)中使用基于令牌的显式注册。因此,根据理论,我应该按以下方式注册。

。
但就我们而言,这是不可能的。因为假设我们将它作为参数构建为--keycloak,那么AuthZearoAuthProxyimpl在编译时将被忽略,因此代码将在运行时中断第14行。
我们试图将依赖项注册逻辑移动到相应的实现类,以便每个实现类都是独立的,这样就不会出现任何运行时问题。但是,它们甚至没有注册为依赖项注入,我们得到了一个错误,它是Attempted to resolve unregistered dependency token: "AuthProxy"。这与javascript的文件加载相同。

KeycloakImpl类。

。
我们甚至尝试使用@registry,它可以在图像中找到注释,但也没有产生任何区别。
尽管我没有尝试过任何其他类型记录的依赖注入库,但从我的小研究来看,它们中的大多数都或多或少遵循了基于接口的依赖注入的模式,而且我在这些方面也预期到了同样的问题。有没有其他解决办法可以解决这个问题,或者甚至可以用打字稿?
PS:我在js和类型记录方面没有太多的专业知识,上面的关键词是基于我在spring和java方面的经验。如果我在解释这个问题时误用了js的特定术语,请忽略它。
发布于 2022-10-08 21:18:45
我在tsyringe上也遇到了类似的问题,我发现了一种更好的方法。
下面是如何使用不同的DI库iti来解决这个问题,并删除许多代码行:
import { createContainer } from "iti"
import express from "express"
// import other deps
const container = createContainer()
.add({
authProxy: () =>
Math.random() > 0.5
? new KeycloakAuthProxyImpl()
: new AuthZearoAuthProxyImpl(),
})
.add((ctx) => ({
authService: () => new AuthServiceV3(ctx.authProxy),
}))
.add((ctx) => ({
server: () => {
const app = express()
app.all("/login", async (req, res) => handler(req, ctx.authService))
return app
},
}))
// start your server / lambda
const server = container.get("server")
server.listen(3000)我还重构了应用程序的其他部分,去掉了单板机,使代码(我)读起来更简单一些。
我创建了一个带有模拟应用程序的交互操场:https://stackblitz.com/edit/json-server-ntssfj?file=index.ts
下面是库的一些链接:

https://stackoverflow.com/questions/73928094
复制相似问题