Skip to content

Commit

Permalink
Enhanced IFactory<T> flexibility (#185)
Browse files Browse the repository at this point in the history
* Added toDynamicValue

* Added DynamicValue

* Added toDynamicValue

* Added DynamicValue binding support

* Removed white spaces

* Added toDynamicValue test

* Removed white spaces

* Added DynamicValue

* Added

* Added

* Update inversify-test.ts

* Added DynamicValue

* Added DynamicValue

* Update resolver.test.ts

* Update resolver.test.ts

* Update README.md

* Update inversify-test.ts

* Update inversify-global-tests.ts

* fixing build

* working on #180

* working on #180

* updated docs

* updated docs
  • Loading branch information
remojansen committed Apr 28, 2016
1 parent 9128ee4 commit 48d96b7
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 8 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ class Ninja implements INinja {
private _shuriken: IShuriken;

public constructor(
@inject("IFactory<IKatana>") katanaFactory: IFactory<IKatana>,
@inject("IFactory<IKatana>") katanaFactory: () => IKatana,
@inject("IShuriken") shuriken: IShuriken
) {
this._katana = katanaFactory();
Expand All @@ -411,7 +411,9 @@ kernel.bind<IFactory<IKatana>>("IFactory<IKatana>").toFactory<IKatana>((context)
};
});
```

You can also define a Factory with args:

```ts
kernel.bind<IFactory<IWeapon>>("IFactory<IWeapon>").toFactory<IWeapon>((context) => {
return (throwable: boolean) => {
Expand All @@ -424,6 +426,33 @@ kernel.bind<IFactory<IWeapon>>("IFactory<IWeapon>").toFactory<IWeapon>((context)
});
```

Sometimes you might need to pass arguments to a factory in different moments during the execution:
```ts
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;
};
});

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

#### Auto factory
Binds an abstraction to a auto-generated Factory.
```ts
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"gulp-sourcemaps": "^1.6.0",
"gulp-tslint": "^5.0.0",
"gulp-typedoc": "^1.2.1",
"gulp-typescript": "^2.12.1",
"gulp-typescript": "^2.13.0",
"gulp-uglify": "^1.5.1",
"harmonize": "^1.4.4",
"harmony-proxy": "^1.0.0",
Expand All @@ -57,7 +57,7 @@
"sinon": "^1.17.3",
"tsify": "^0.15.2",
"tslint": "^3.2.2",
"typescript": "^1.7.5",
"typescript": "^1.8.10",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0",
"wallabify": "0.0.14"
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/bindings/factory.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// <reference path="../interfaces.d.ts" />

interface IFactory<T> extends Function {
(...args: any[]): T;
(...args: any[]): (((...args: any[]) => T)|T);
}
87 changes: 84 additions & 3 deletions test/inversify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ describe("InversifyJS", () => {
private _shuriken: IShuriken;

public constructor(
@inject("IFactory<IKatana>") katanaFactory: IFactory<IKatana>,
@inject("IFactory<IKatana>") katanaFactory: () => IKatana,
@inject("IShuriken") shuriken: IShuriken
) {
this._katana = katanaFactory();
Expand Down Expand Up @@ -627,7 +627,7 @@ describe("InversifyJS", () => {
private _shuriken: IWeapon;

public constructor(
@inject("IFactory<IWeapon>") weaponFactory: IFactory<IWeapon>
@inject("IFactory<IWeapon>") weaponFactory: (throwable: boolean) => IWeapon
) {
this._katana = weaponFactory(false);
this._shuriken = weaponFactory(true);
Expand Down Expand Up @@ -659,6 +659,87 @@ describe("InversifyJS", () => {

});

it("Should support the injection of user defined factories with partial application", () => {

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: (displacement: number) => 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);

});

it("Should support the injection of auto factories", () => {

interface INinja {
Expand Down Expand Up @@ -695,7 +776,7 @@ describe("InversifyJS", () => {
private _shuriken: IShuriken;

public constructor(
@inject("IFactory<IKatana>") katanaAutoFactory: IFactory<IKatana>,
@inject("IFactory<IKatana>") katanaAutoFactory: () => IKatana,
@inject("IShuriken") shuriken: IShuriken
) {
this._katana = katanaAutoFactory();
Expand Down
2 changes: 1 addition & 1 deletion type_definitions/inversify/inversify.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ declare namespace inversify {
interface IBindingWhenOnSyntax<T> extends IBindingWhenSyntax<T>, IBindingOnSyntax<T> {}

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

interface IFactoryCreator<T> extends Function {
Expand Down

0 comments on commit 48d96b7

Please sign in to comment.