带有自动装配的打字稿依赖注入

Ber*_*gan 0 api dependency-injection typescript

是否有任何打字稿框架允许用户使用众所周知的 java-spring 自动装配?例子

class A {
   public print() : void;
}

class B {
   constructor(a : A)
}
var obj = CONTAINER.get("B");
Run Code Online (Sandbox Code Playgroud)

容器是 API 的一部分

Rem*_*sen 5

我开发了一个名为 InversifyJS 的 IoC 容器,具有高级依赖注入功能,如上下文绑定。

您需要遵循3 个基本步骤来使用它:

1. 添加注释

注解 API 基于 Angular 2.0:

import { injectable, inject } from "inversify";

@injectable()
class Katana implements IKatana {
    public hit() {
        return "cut!";
    }
}

@injectable()
class Shuriken implements IShuriken {
    public throw() {
        return "hit!";
    }
}

@injectable()
class Ninja implements INinja {

    private _katana: IKatana;
    private _shuriken: IShuriken;

    public constructor(
        @inject("IKatana") katana: IKatana,
        @inject("IShuriken") shuriken: IShuriken
    ) {
        this._katana = katana;
        this._shuriken = shuriken;
    }

    public fight() { return this._katana.hit(); };
    public sneak() { return this._shuriken.throw(); };

}
Run Code Online (Sandbox Code Playgroud)

2. 声明绑定

绑定 API 基于 Ninject:

import { Kernel } from "inversify";

import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";

var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);

export default kernel;
Run Code Online (Sandbox Code Playgroud)

3. 解决依赖

解析 API 基于 Ninject:

import kernel = from "./inversify.config";

var ninja = kernel.get<INinja>("INinja");

expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
Run Code Online (Sandbox Code Playgroud)

最新版本 (2.0.0) 支持许多用例:

  • 内核模块
  • 内核中间件
  • 使用类、字符串文字或符号作为依赖标识符
  • 注入常​​数值
  • 注入类构造函数
  • 工厂注塑
  • 汽车厂
  • 提供程序的注入(异步工厂)
  • 激活处理程序(用于注入代理)
  • 多次注射
  • 标记绑定
  • 自定义标签装饰器
  • 命名绑定
  • 上下文绑定
  • 友好异常(例如循环依赖)

您可以在https://github.com/inversify/InversifyJS 上了解更多信息

2016 年 5 月更新

像 C# 这样的编译型编程语言中的自动装配如下所示:

kernel.Scan(scanner =>
{
    // look for types in this assembly
    scanner.FromCallingAssembly();

    // make ISomeType bind to SomeType by default (remove the 'I'!)
    scanner.BindWith<DefaultBindingGenerator>();
});
Run Code Online (Sandbox Code Playgroud)

或者

kernel.Bind(
    x => x.FromThisAssembly()
          .SelectAllClasses()
          .BindAllInterfaces());
Run Code Online (Sandbox Code Playgroud)

在 TypeScript 和 JavaScript 中没有程序集。我们可以创建一个任务,用@injectable()装饰器在你的模块中搜索类,但这会非常低效。

我们正在为 InversifyJS开发一个扩展,它允许我们认为类似于一种伪自动装配的东西。

代替:

@injectable()
class Katana implements IKatana {
    public hit() {
        return "cut!";
    }
}

kernel.bind<IKatana>("IKatana").to(Katana);
Run Code Online (Sandbox Code Playgroud)

你可以写:

@provide(Katana)
class Katana implements IKatana {
    public hit() {
        return "cut!";
    }
}
Run Code Online (Sandbox Code Playgroud)

@provide()装饰器在幕后生成绑定:

kernel.bind<Katana>(Katana).to(Katana);
Run Code Online (Sandbox Code Playgroud)

该扩展还包括一个名为的助手autoProvide,它@provide为您将装饰器应用于所有实体。

import * as entites from "../entities";

let kernel = new Kernel();
autoProvide(kernel, entites);
let warrior = kernel.get<Warrior>(entites.Warrior);
Run Code Online (Sandbox Code Playgroud)

实体模块必须提供对所有实体的直接访问:

export { default as Warrior } from "./warrior";
export { default as Katana } from "./katana";
Run Code Online (Sandbox Code Playgroud)

并且实体不需要@injectableor@provide装饰器:

class Katana {
    public use() {
        return "Using Katana...";
    }
}

export default Katana;
Run Code Online (Sandbox Code Playgroud)

但是,@inject需要装饰器:

import Katana from "./katana";
import { inject } from "inversify";

class Warrior {
    private _weapon: Katana;
    public constructor(
        // we need to declare binding because auto-provide uses
        // @injectbale decorator at runtime not compilation time
        // in the future maybe this limitation will desapear
        // thanks to design-time decorators or some other TS feature
        @inject(Katana) weapon: Katana
    ) {
        this._weapon = weapon;
    }
    public fight() {
        return this._weapon.use();
    }
}

export default Warrior;
Run Code Online (Sandbox Code Playgroud)

正如我所说,这不是自动装配,因为没有装配是不可能的,但它已经足够接近了。

您可以在此处了解有关 inversify-binding-decorators 的更多信息。