Skip to content

Enhanced IFactory<T> flexibility #180

Description

@remojansen

Expected Behavior

export interface IFactory<T> extends Function {
    (...args: any[]): (IFactory<T>|T);
} 

Current Behavior

export interface IFactory<T> extends Function {
    (...args: any[]): T;
}

Context

This use cases comes form the #177.

interface IInjectorPump {}

@injectable()
class InjectorPump implements IInjectorPump {}

interface ISparkPlugs {}

@injectable()
class SparkPlugs implements ISparkPlugs {}

class IEngine {
    public displacement: number;
}

@injectable()
class DieselEngine implements IEngine {
    public displacement: number;
    private _injectorPump: IInjectorPump;
    constructor(
        @inject("IInjectorPump") injectorPump: IInjectorPump
    ) {
        this._injectorPump = injectorPump;
        this.displacement = null;
    }
}

@injectable()
class PetrolEngine implements IEngine {
    public displacement: number;
    private _sparkPlugs: ISparkPlugs;
    constructor(
        @inject("ISparkPlugs") sparkPlugs: ISparkPlugs
    ) {
        this._sparkPlugs = sparkPlugs;
        this.displacement = null;
    }
}

interface ICarFactory {
    createEngine(displacement: number): IEngine;
}

@injectable()
class DieselCarFactory implements ICarFactory {
    private _dieselFactory: (...args: any[]) => IEngine ;
    constructor(
        @inject("IFactory<IEngine>") factory: (category: string) => (displacement: number) => IEngine
    ) {
        this._dieselFactory = factory("diesel");
    }
    public createEngine(displacement: number): IEngine {
        return this._dieselFactory(displacement);
    }
}

let kernel = new Kernel();
kernel.bind<ISparkPlugs>("ISparkPlugs").to(SparkPlugs);
kernel.bind<IInjectorPump>("IInjectorPump").to(InjectorPump);
kernel.bind<IEngine>("IEngine").to(PetrolEngine).whenTargetNamed("petrol");
kernel.bind<IEngine>("IEngine").to(DieselEngine).whenTargetNamed("diesel");

kernel.bind<IFactory<IEngine>>("IFactory<IEngine>").toFactory<IEngine>((context) => {
    return (named: string) => (displacement: number) => {
        let engine = context.kernel.getNamed<IEngine>("IEngine", named);
        engine.displacement = displacement;
        return engine;
    };
});

kernel.bind<ICarFactory>("IDieselCarFactory").to(DieselCarFactory);

let dieselCarFactory = kernel.get<ICarFactory>("IDieselCarFactory");
let engine = dieselCarFactory.createEngine(300);

expect(engine.displacement).eql(300);
expect(engine instanceof DieselEngine).eql(true);

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions