IOC for TypeScript

Den*_*rev 9 javascript dependency-injection inversion-of-control typescript

现在使用TypeScript,我们在JavaScript中有静态分析和许多OOP功能.所以现在也是时候在客户端逻辑中进行更好的单元测试了,同时我们需要IOC容器进行依赖注入,以使代码更易于测试......

那么,有人已经体验过这个主题,或者可能知道可以移植到TypeScript的打字稿或JavaScript框架的库吗?

Rem*_*sen 17

我开发了一个名为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了解更多相关信息


小智 5

我为typescript创建了DI库 - huject

https://github.com/asvetliakov/huject

例:

import {Container, FactoryMethod, ConstructorInject, Inject} from 'huject';
class FirstService {
   public constructor(param: number) {}
}
class SecondService {
}

@ConstructorInject
class MyController {
    @Inject
    public service: FirstService;

    public second: SecondService;
    public constructor(service: SecondService) {
        this.second = service;
    }
    ...
}
container.setAllowUnregisteredResolving(true);
container.register(FirstService, [10]); // Register constructor arguments

// FirstService and SecondService will be resolved for container instance
let controller = container.resolve(MyController);
Run Code Online (Sandbox Code Playgroud)

虽然TypeScript接口存在问题,但我有2个解决方法(使用抽象或简单类作为接口)


小智 5

或者,您可以不使用框架,而是使用类作为容器,并使用对象工厂作为属性。然后,您可以在测试中继承此类并更改工厂。这种方法是类型安全的,不需要任何装饰器,只需要注册类。

class B {
    echo() {
        alert('test');
    }   
}

class A {
    constructor(private b: B) {
        b.echo();
    }
}

class Container {
    A = () => new A(this.B());
    B = singleton(() => new B()); 
}

var c = new Container();
var a = c.A();

// singleton helper:

function memoize<T>(factory: () => T): () => T  {
    var memo: T = null;
    return function () {
        if(!memo) {
            memo = factory();
        }
        return memo;
    };
}

var singleton = memoize;
Run Code Online (Sandbox Code Playgroud)


Fen*_*ton 2

目前,您可以在 JavaScript 中使用依赖注入,而无需 IOC 部分。是否编写“手动”解析器、工厂或您喜欢的任何 DI 模式都取决于您。

当 ECMAScript 6 标准被采用时,可能会让 JavaScript 中 IOC 的概念成为可能。