Skip to content

Dependency injection

Oliver Leve edited this page Nov 7, 2018 · 1 revision

Dependency injection is a design pattern that will resolve your class dependencies via it's constructor function. With this pattern, there is no need to care about how to get the dependency. You only have to declare it.

There are three ways of getting your dependency via injection:

  • Constructor declaration
  • Property declaration with decorator
  • Manual injecting

Constructor declaration

When you have a singleton like class, you can use constructor injection to get your dependencies.

import { QhunAddon } from "@wartoshika/wow-qhun-core-ts/src/core";
import { SlashCommandRegistar } from "@wartoshika/wow-qhun-core-ts/src/slash";

@QhunAddon()
class MyAddon {

    constructor(
        // declaring a dependency as a local variable. The type hint tells the transpiler wich dependency should be used.
        // In this case SlashCommandRegistar will be available via slashRegister local variable
        slashRegister: SlashCommandRegistar
    ) {
        // register /myaddon as slash command and print the typed parameters
        slashRegister.registerCommand(["myaddon"], message => { print(`You typed ${message}`); });
    }
}

You can declare all required dependencies via parameter declaration of the constructor. The important part for the Injector is the type of the variable. In the adobe example, the Injector will look for an @Injectable() class in the given import path @wartoshika/wow-qhun-core-ts/src/slash and if there is any, it will instantiate and provide this class.

Important: In order to resolve the constructor dependencies you have to instantiate this class using the dependency injection as well. Declare this class as dependency in an other or use other dependency injection methods.

Property declaration with decorator

On some cases, you dont want to use a singleton class. This might be the case for a eg. a Unit class. It must be instantiated for every unit that should be reflected via this class. In this case you should use the property injection.

import { Inject, Logger } from "@wartoshika/wow-qhun-core-ts/src/core";

export class Unit {

    @Inject(Logger)
    private logger: Logger

    constructor(
        unitId: WowUnitId
    ) {
        this.logger.info(`Unit's current health is ${UnitHealth(unitId)}`);
    }
}

In the above example, the @Inject(...) decorator is used to inject the debug Logger into the class when it is instantiated. You can now use new Unit("player"); to instantiate your class and the dependency will be available in the class context.

Manual injecting

In rare cases you can not use the two injecting methods above. Manual injecting provide the backup possability to get your dependency.

import { Injector, EventEmitter } from "@wartoshika/wow-qhun-core-ts/src/core";

export function emitMyEvent(): void {

    // getting the EventEmitter instance via manual injecting
    const eventEmitter = Injector.getInstance().instantiateClass(EventEmitter);

    // emit the test event
    eventEmitter.emit("TestEvent");
}

The Injector class is a singleton and must be aquired using .getInstance() method. After having the Injector instance, you can instantiate the required class.