inversify-binding-decorators fails with separated files
Expected Behavior
I expect to see success emitted to console in code below
Current Behavior
Instead, I see the error Error: No matching bindings found for serviceIdentifier: Weapon
Steps to Reproduce (for bugs)
Just run the snippet below
Context
I'm trying to use inversify-binding-decorators to get rid of boilerplate.
Your Environment
- Version used:
"inversify": "^5.0.1","inversify-binding-decorators": "^4.0.0","reflect-metadata": "^0.1.13" - Environment name and version: node.js: v14.8.0
- Operating System and version: Windows 10
- Link to your project: N/A - see code below
- Running in debug mode using PyCharm, if it helps..
Detailed description:
The following code was working very well, until I separated it to different files:
import {Container, inject} from "inversify";
import {buildProviderModule, provide} from "inversify-binding-decorators";
import "reflect-metadata";
export interface Weapon {
hit(): string
}
@provide("Weapon")
export class Katana implements Weapon {
public hit() {
return "cut!";
}
}
@provide(Ninja)
export class Ninja {
private weapon: Weapon;
constructor(@inject("Weapon") weapon: Weapon) {
this.weapon = weapon;
}
Fight() {
return this.weapon.hit()
}
}
try {
const container = new Container();
container.load(buildProviderModule());
const ninja = container.get(Ninja);
console.log(ninja.Fight())
console.log("success")
} catch (e) {
console.error(e)
}
console.log("done")
After refactoring, this is the new file structure:
ioc/
node_modules/
src/
warrior.ts
weapon.ts
main.ts
package.json
package-lock.json
tsconfig.json
They hold the same logic, just separated:
warrior.ts:
import "reflect-metadata";
import {provide} from "inversify-binding-decorators";
import {inject} from "inversify";
import {Weapon} from "./weapon";
@provide(Ninja)
export class Ninja {
private weapon: Weapon;
constructor(@inject("Weapon") weapon: Weapon) {
this.weapon = weapon;
}
Fight() {
return this.weapon.hit()
}
}
weapon.ts:
import {provide} from "inversify-binding-decorators";
export interface Weapon {
hit(): string
}
@provide("Weapon")
export class Katana implements Weapon {
public hit() {
return "cut!";
}
}
main.ts:
import {Container} from "inversify";
import {buildProviderModule} from "inversify-binding-decorators";
import "reflect-metadata";
import {Ninja} from "./src/warrior";
try {
const container = new Container();
container.load(buildProviderModule());
const ninja = container.get(Ninja);
console.log(ninja.Fight())
console.log("success")
} catch (e) {
console.error(e)
}
console.log("done")
But now it fails on const ninja = container.get(Ninja); with error Error: No matching bindings found for serviceIdentifier: Weapon.
请问你解决了么?
In case anyone stumbles upon this: This is seems not to be an issue with the library itself, but with the way code is compiled and then evaluated during run time.
tariano's main.ts does not include any import of the Katana class or refererence to the weapon.ts file in general, which makes sense since it's supposed to be injected. However, this means the run time will execute the code in main.ts without ever touching Katana (as only the Weapon interface is referenced by the Ninja class) and thus it's provide decorator is never evaluated.
Unfortunately, there seems no real fix to this. Only the workaround of explicitly importing the module like so:
import './src/weapon';
... at the beginning of main.ts, in order to ensure the class is bound to the container before accessing it.
Still, I hope this helps!