简体   繁体   中英

Why is my property injection attempt not injecting anything but undefined?

I have an existing typescript project using inversify. I have defined a logger in my TYPES at TYPES.ILoggger and when I access the logger directly from my container it works:

import {ILogger} from "./interfaces/ILogger";
import {TYPES} from "./interfaces/TYPES";
import container from "./kernel/inversify.config";

const loggerFromTheContainer: ILogger = container.get<ILogger>(TYPES.ILogger);
loggerFromTheContainer.info("I WILL LOG"); // this works

So my setup should be fine.

I don't want to access the container directly but I want to use property injection. [InversifyJS' README provides an example:

If you prefer it you can use property injection instead of constructor injection so you don't have to declare the class constructor:

 @injectable() class Ninja implements Warrior { @inject(TYPES.Weapon) private _katana: Weapon; @inject(TYPES.ThrowableWeapon) private _shuriken: ThrowableWeapon; public fight() { return this._katana.hit(); } public sneak() { return this._shuriken.throw(); } }

and I try to follow that one.

Yet when I try to inject the logger through property injection, I suddenly get undefined as a logger and I don't know why:

@injectable()
class ShouldHaveLogger {
    @inject(TYPES.ILogger) private logger: ILogger;

    constructor() {
        this.logger.info("Hello World"); // this.logger will remain undefined
    }
}

new ShouldHaveLogger();

It will throw a generic

TypeError: Cannot read property 'info' of undefined

as this.logger is not being injected. Yet why and how to fix it?

The normal behavior of property injection is to let inversify create the instances for you. You are now describing a use-case, in which you create the instance of ShouldHaveLogger yourself (or another library is creating it for you).

This is also pointed out by the docs

In order to do that, you will need inversify-inject-decorators , as then you can inject the logger eg via @lazyInject .

You have to setup lazyInject using your container and your code should look like:

import {injectable} from "inversify";
import getDecorators from "inversify-inject-decorators";
import {ILogger} from "./interfaces/ILogger";
import {TYPES} from "./interfaces/TYPES";
import container from "./kernel/inversify.config";   

const {lazyInject} = getDecorators(container);

@injectable()
class ShouldHaveLogger {
    @lazyInject(TYPES.ILogger) private logger: ILogger;

    constructor() {
        this.logger.info("I am working now");
    }
}

new ShouldHaveLogger();

Will print depending on you logger implementation:

2019-01-30T09:47:54.890Z - info: "I am working now"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM