Typescript IOC in case of node

…衆ロ難τιáo~ 提交于 2019-12-08 03:35:03

问题


I am wondering how would you use typescript IOC specifically node app.

In case of external module-based architecture there is no any classes in the app. Just pure modules because my app heavily depends on node_modules.

How would I integrate IOC solution in such case? Any thoughts?

Here is my specific case I want to use IOC for:

I have mongoose model:

interface IStuffModel extends IStuff, mongoose.Document { }   

var Stuff= mongoose.model<IStuffModel>('Stuff', Schemas.stuffSchema);

export = Stuff;

And related fake class:

export class Stuff implements IStuff { 
 //do stuff
}

回答1:


How would I integrate IOC solution in such case

Here is a very popular library that I recommend : https://github.com/inversify/InversifyJS

External modules

Using external modules doesn't change the code at all. Instead of

kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", FooBar));

Production

You just have

import {ProdFooBar} from "./prodFooBar";
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", ProdFooBar));

Test

import {MockFooBar} from "./mockFooBar";
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", MockFooBar));



回答2:


As Basarat indicated in his answer, I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings.

You need to follow 3 basic steps to use it:

1. Add annotations

The annotation API is based on 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(); };

}

2. Declare bindings

The binding API is based on 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;

3. Resolve dependencies

The resolution API is based on Ninject:

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

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

expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true

The latest release (2.0.0) supports many use cases:

  • Kernel modules
  • Kernel middleware
  • Use classes, string literals or Symbols as dependency identifiers
  • Injection of constant values
  • Injection of class constructors
  • Injection of factories
  • Auto factory
  • Injection of providers (async factory)
  • Activation handlers (used to inject proxies)
  • Multi injections
  • Tagged bindings
  • Custom tag decorators
  • Named bindings
  • Contextual bindings
  • Friendly exceptions (e.g. Circular dependencies)

You can learn more about it at https://github.com/inversify/InversifyJS

In the particular context of Node.js there is a hapi.js example that uses InversifyJS.



来源:https://stackoverflow.com/questions/35545695/typescript-ioc-in-case-of-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!