TypeScript中的依赖注入

Sop*_*len 28 tdd amd requirejs typescript

我正在研究用TypeScript做TDD的可能性.如果我在TypeScript中编写我的测试,是否可以使import语句为我测试的类返回模拟?或者是用纯JavaScript编写测试并处理自己注入AMD的唯一​​可行方法?

Phi*_*ley 20

我在TypeScript中使用infuse.js进行依赖注入.

参考d.ts

/// <reference path="definition/infusejs/infusejs.d.ts"/>
Run Code Online (Sandbox Code Playgroud)

启动时初始化进样器

this.injector = new infuse.Injector();  
Run Code Online (Sandbox Code Playgroud)

映射依赖项

this.injector.mapClass( 'TodoController', TodoController );
this.injector.mapClass( 'TodoView', TodoView );
this.injector.mapClass( 'TodoModel', TodoModel, true );  // 'true' Map as singleton
Run Code Online (Sandbox Code Playgroud)

注入依赖关系

export class TodoController
{
    static inject = ['TodoView', 'TodoModel'];

    constructor( todoView:TodoView, todoModel:TodoModel )
    {

    }
 }
Run Code Online (Sandbox Code Playgroud)

它是基于字符串的,而不是基于类型的(因为在TypeScript中还不能实现反射).尽管如此,它在我的应用程序中运行良好.


Rem*_*sen 18

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


Ole*_*uka 6

试试这个依赖注入器(Typejector)

GitHub Typejector

使用新的TypeScript 1.5,可以使用注释方式

例如

    @injection
    class SingletonClass {
        public cat: string = "Kitty";
        public dog: string = "Hot";

        public say() {
            alert(`${this.cat}-Cat and ${this.dog}-Dog`);
        }
    }
    @injection
    class SimpleClass {
        public say(something: string) {
            alert(`You said ${something}?`);
        }
    }

    @resolve
    class NeedInjectionsClass {
        @inject(SingletonClass)
        public helper: SingletonClass;
        @inject(SimpleClass)
        public simpleHelper: SimpleClass;

        constructor() {
            this.helper.say();
            this.simpleHelper.say("wow");
        }
    }
    class ChildClass extends NeedInjectionsClass {

    }

    var needInjection = new ChildClass();
Run Code Online (Sandbox Code Playgroud)

对于问题案例:某些属性应该像下一个示例中那样实现伪接口(或抽象类).

    class InterfaceClass {
        public cat: string;
        public dog: string;

        public say() {

        }
    }

    @injection(true, InterfaceClass)
    class SingletonClass extends InterfaceClass {
        public cat: string = "Kitty";
        public dog: string = "Hot";

        public say() {
            alert(`${this.cat}-Cat and ${this.dog}-Dog`);
        }
    }

    @injection(true, InterfaceClass)
    class MockInterfaceClass extends InterfaceClass {
        public cat: string = "Kitty";
        public dog: string = "Hot";

        public say() {
            alert(`Mock-${this.cat}-Cat and Mock-${this.dog}-Dog`);
        }
    }

    @injection
    class SimpleClass {
        public say(something: string) {
            alert(`You said ${something}?`);
        }
    }

    @resolve
    class NeedInjectionsClass {
        @inject(InterfaceClass)
        public helper: InterfaceClass;
        @inject(SimpleClass)
        public simpleHelper: SimpleClass;

        constructor() {
            this.helper.say();
            this.simpleHelper.say("wow");
        }
    }

    class ChildClass extends NeedInjectionsClass {

    }

    var needInjection = new ChildClass();
Run Code Online (Sandbox Code Playgroud)

注意: 模拟注入应该在源代码之后定义,因为它重新定义了接口的类创建者

  • 虽然此链接可能会回答这个问题,但最好在此处包含答案的基本部分并提供参考链接.如果链接的页面发生更改,则仅链接的答案可能会无效 (2认同)

Ale*_*sko 0

TypeScript 与 AMD 加载器(如 requirejs)配合得很好。如果配置正确,TypeScript 将输出完全符合 AMD 的 JavaScript。

在测试情况下,您可以配置 requirejs 来注入可测试的模块。