InversifyJS
InversifyJS copied to clipboard
LazyServiceIdentifer does not work for property injection
Unable to lazily inject circular service dependency via property injection.
Side-note: Identifer -> Identifier
Expected Behavior
Inject without error
Current Behavior
throws error
Steps to Reproduce (for bugs)
import "reflect-metadata";
import { Container, injectable, inject, LazyServiceIdentifer } from "inversify";
const container = new Container();
interface IModuleA {}
interface IModuleB {}
const moduleA = Symbol.for("IModuleA");
const moduleB = Symbol.for("IModuleB");
@injectable()
class ModuleA implements IModuleA {
@inject(new LazyServiceIdentifer(()=>moduleB))
b: IModuleB;
}
@injectable()
class ModuleB implements IModuleB{
@inject(new LazyServiceIdentifer(()=>moduleA))
a: IModuleA
}
container.bind(moduleA).to(ModuleA).inSingletonScope();
container.bind(moduleB).to(ModuleB).inSingletonScope();
let bar = container.get(moduleA);
console.log(bar);
Context
I'm aware that injecting via the constructor works; however in NInject I was able to do this kind of lazy property injection within a base "Module" class. Subsequent derivations of that "Module" class then didn't have to deal with adding those dependencies manually.
Environment
inversify: "^4.13.0" node-js: 10.1.0
Stack trace
Error: No matching bindings found for serviceIdentifier: [object Object]
at _validateActiveBindingCount (D:\Code\logger\node_modules\inversify\lib\planning\planner.js:62:23)
at _getActiveBindings (D:\Code\logger\node_modules\inversify\lib\planning\planner.js:48:5)
at _createSubRequests (D:\Code\logger\node_modules\inversify\lib\planning\planner.js:91:26)
at D:\Code\logger\node_modules\inversify\lib\planning\planner.js:115:17
at Array.forEach (<anonymous>)
at D:\Code\logger\node_modules\inversify\lib\planning\planner.js:114:26
at Array.forEach (<anonymous>)
at _createSubRequests (D:\Code\logger\node_modules\inversify\lib\planning\planner.js:94:20)
at Object.plan (D:\Code\logger\node_modules\inversify\lib\planning\planner.js:136:9)
at D:\Code\logger\node_modules\inversify\lib\container\container.js:318:37
I have tried to reproduce the same case (A injected in B. B injected in A.) with @lazyInject but also getting an error. And also I tried an example with the service identifier. https://github.com/inversify/InversifyJS/issues/865
Any progress on this issue?
Any updates ? facing same issue with lazyServiceIdentifier
I resolved this problem by defining a third class, class C, which has an A and B injected property. This will contain methods which should call each property's methods.
This really really hurts.
Just had an issue with that. My workaround:
a) Inject Container
to container somewhere
import { Container } from 'inversify'
const container = new container({...})
container.bind(Container).toConstantValue(container)
b) Implement custom lazy inject getter decorator based on container.get()
import { interfaces, decorate, Container, METADATA_KEY } from 'inversify'
export function lazyInject(
serviceIdentifierCallback: () => interfaces.ServiceIdentifier<any>,
): PropertyDecorator {
return function (target: any, propertyKey) {
// inject container as this.container if it's not present
if (!Reflect.getMetadata(METADATA_KEY.TAGGED_PROP, target.constructor)?.container) {
decorate(inject(Container), target, 'container')
}
// define getter
Object.defineProperty(target, propertyKey, {
get: function () {
return this.container.get(serviceIdentifierCallback())
},
})
}
}
c) Usage
@injectable()
export class MyClass {
@lazyInject(() => SOME_TOKEN) service!: SomeService
}
The caveats are:
- we're injecting container as container property in each class (need to make sure not to use it for smth else)
- we're lazy resolving it at runtime (so we loose some debug value from inversify messages, idk about perf)
Any progress on this issue?
I don't think anyone is working on Inversify