@inject()在tsyringe的依赖项注入中做了什么



我正在用tsyringe学习DI。我对DI的概念也完全陌生。

以下代码段有效,container.resolve(Foo)正确地实例化了依赖项。

import "reflect-metadata";
import { injectable, container } from "tsyringe";
class Database {
get() {
return "got-stuff-from-database";
}
}
@injectable()
class Foo {
constructor(private database: Database) {}
checkDb() {
return this.database.get();
}
}
const fooInstance = container.resolve(Foo);
console.log(fooInstance.checkDb());
//=> got-stuff-from-database

这是可以理解的。但是下面的片段(大部分取自他们的自述(对我来说不起作用,我也不能理解,也不能理解为什么我们有了上面的injectable装饰器就需要inject。很抱歉,我在网上搜索了一下,发现每个人都在使用它,就像每个人都知道的一样。

interface Database {}
@injectable()
class Foo {
constructor(@inject("Database") private database?: Database) {}
checkDb() {
return 'stuff';
}
}
const fooInstance = container.resolve(Foo);
console.log(fooInstance.checkDb());

所以需要记住的主要一点是tsyringe是一个Typescript库。当Typescript被编译为Javascript时,接口基本上不再存在(就像您的示例中的Database接口(,所以类中发生的DI魔法不能像往常一样完成。文档是这样解释的:

接口在运行时没有类型信息,因此我们需要用@inject(…(装饰它们,这样容器就知道如何解决他们

它仍然不适用于您的原因是,您只告诉DI框架,它必须查找在令牌"Database"下注册的东西的实例,但实际上没有在那里注册任何东西。因此,要使其工作,您仍然需要告诉tsyringe"Database"有一个类或实例与之关联,如下所示:

container.register("Database", {
useClass: SomeDatabaseImplementation
});

请注意,您仍然必须创建所述实现,因为您无法实例化接口。为了更深入地理解,我建议你看一下库的源代码,它很容易理解,让你更好地了解内部工作原理。

相关内容

  • 没有找到相关文章

最新更新