InversifyJS:用于 TypeScript 应用的 IoC 容器

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

InversifyJS:强大的 TypeScript IoC 容器



InversifyJS 是一个轻量级但极其强大的 IoC(控制反转)容器,适用于 TypeScript 和 JavaScript 应用。它实现了 依赖注入(DI) 模式,使开发者能够创建低耦合、可测试且可扩展的系统。该库充分利用 TypeScript 的特性(装饰器、类型)来确保严格的类型检查和开发便利性。



InversifyJS 非常适合 Node.js 上的服务器端应用,以及使用 Angular、React 或 Vue 等框架的客户端项目。在本概述中,我们将解析关键概念并展示如何快速上手。



InversifyJS 的核心概念



在编写代码之前,理解该库的三个主要实体很重要:



  • 容器(Container) — 管理所有依赖关系的核心对象。您在其中注册抽象及其实现。
  • 服务标识符(Service Identifiers) — 容器用来查找相应实现的唯一键。可以是字符串、符号或类。
  • 装饰器 — @injectable() 和 @inject() — 向 TypeScript 指示该类可以被注入,以及它需要哪些依赖。


安装与配置



首先,安装 InversifyJS 及其类型依赖:



npm install inversify reflect-metadata --savenpm install --save-dev @types/node


然后,在 tsconfig.json 中添加两个必需选项:



{  "compilerOptions": {    "emitDecoratorMetadata": true,    "experimentalDecorators": true,    "types": ["reflect-metadata"]  }}


之后,在应用的主文件(通常是 index.ts 或 main.ts)中导入 reflect-metadata:



import "reflect-metadata";


第一个示例:简单服务



创建一个接口及其实现。请注意 @injectable() 装饰器:



// interfaces/IWarrior.tsexport interface IWarrior {    fight(): string;}

// entities/Warrior.tsimport { injectable } from "inversify";

@injectable()export class Warrior implements IWarrior { fight(): string { return "Warrior attacks with sword!"; }}


现在,在容器中注册此绑定并获取实例:



import { Container } from "inversify";import { IWarrior } from "./interfaces/IWarrior";import { Warrior } from "./entities/Warrior";

const container = new Container();

// 注册抽象及其实现container.bind<IWarrior>("IWarrior").to(Warrior);

// 获取实例const warrior = container.get<IWarrior>("IWarrior");console.log(warrior.fight()); // "Warrior attacks with sword!"


通过构造函数注入依赖



当一个类依赖于另一个类时,DI 的真正威力得以展现。使用 @inject() 装饰器:



// interfaces/IWeapon.tsexport interface IWeapon {    use(): string;}

// entities/Sword.tsimport { injectable } from "inversify";

@injectable()export class Sword implements IWeapon { use(): string { return "Swing sword!"; }}

// entities/Knight.tsimport { injectable, inject } from "inversify";import { IWarrior } from "../interfaces/IWarrior";import { IWeapon } from "../interfaces/IWeapon";

@injectable()export class Knight implements IWarrior { private _weapon: IWeapon;

constructor(@inject("IWeapon") weapon: IWeapon) { this._weapon = weapon; }

fight(): string { return this._weapon.use() + " The knight fights!"; }}


注册

推荐