Binding classes with property injection to kernel in inversify

拥有回忆 提交于 2021-01-04 05:33:49

问题


I am trying to achieve dependency injection on my node project via inversify.

I have a kernel config like this: inversify.config.ts

import "reflect-metadata";
import {Kernel, interfaces} from "inversify";

import {Config} from "./config";
import {Collection} from "./collection";

let kernel = new Kernel();

kernel.bind<Config>("Config").to(Config).inSingletonScope();
// kernel.bind<interfaces.Newable<Collection>>("Collection").toConstructor<Collection>(Collection);
// it works without the line above

A class: config.ts

import {injectable} from "inversify";
@injectable()
export class Config {
  constructor() {}
}

A class with property DI collection.ts

import {injectable} from "inversify";
import getDecorators from "inversify-inject-decorators";
import kernel from "../inversify.config";
let {lazyInject} = getDecorators(kernel);

@injectable()
export class Collection {
  @lazyInject(Config)
  private Config: Config;

  constructor(a: string, b: string) {}
}

Everything works as expected if I don't bind a class with property injection. When I try to bind a class with @lazyInject as shown in the example

kernel.bind<interfaces.Newable<Collection>>("Collection").toConstructor<Collection>(Collection);

import line in inversify.config.ts starts processing Collection.ts and the line

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

in it. However as we arrived Collection.ts while we already processing inversify.config.ts file line

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

somehow returns undefined making kernel undefined for Collection class. Therefore @lazyInject DI fails.

Eventually when I try to read Config in Collection it fails with:

TypeError: Cannot read property 'get' of undefined
    at resolve (node_modules/inversify-inject-decorators/lib/decorators.js:24:30)
    at Category.getter (node_modules/inversify-inject-decorators/lib/decorators.js:6:47)

I wonder if there is a way to accomplish binding a class with property DI via @lazyInject without moving kernel definition into the same file with one of the classes. I am looking for a way to import kernel as it is now, but make it work properly.


回答1:


Your problem is that you have a circular dependency:

I'm going to change your code and add a couple of additional files. Nothe that the he file types.ts is not needed but it is recommended to keep all your type identifiers in one single location.

After changing your code the dependency diagram will change to the following:

As you can se we have eliminated the circular dependency.

inversify.config.ts

import "reflect-metadata";
import {Kernel, interfaces} from "inversify";
import getDecorators from "inversify-inject-decorators";
import { makeProvideDecorator } from "inversify-binding-decorators";

let kernel = new Kernel();
let {lazyInject} = getDecorators(kernel);
let provide = makeProvideDecorator(kernel);

export { lazyInject, provide };

types.ts

let TYPES = {
  Config: "Config",
  Collection: "Collection",
};

export default TYPES;

config.ts

import { provide } from "../inversify.config";
import TYPES from "./types";

@provide(TYPES.Config)
export class Config {
  constructor() {}
}

export default Config;

collection.ts

import { lazyInject, provide } from "../inversify.config";

@provide(TYPES.Collection)
export class Collection {
  @lazyInject(TYPES.Config)
  private Config: Config;
  constructor(a: string, b: string) {}
}

export default Collection;

main.ts

You need to import all your dependencies when they are imported @provide is executed and then bindings are generated.

import Config from "./lib/config";
import Collection from "./models/collection";

//...

We have been able to eliminate the circular dependency using the @provide decorator from inversify-binding-decorators.



来源:https://stackoverflow.com/questions/38927236/binding-classes-with-property-injection-to-kernel-in-inversify

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