Skip to content

Commit

Permalink
Implements #505 (#512)
Browse files Browse the repository at this point in the history
* Implemments #505

* Added docs for #505
  • Loading branch information
remojansen authored Mar 22, 2017
1 parent 1410309 commit be1c2fc
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "inversify",
"version": "3.2.0",
"version": "3.3.0",
"description": "A powerful and lightweight inversion of control container for JavaScript and Node.js apps powered by TypeScript.",
"main": "lib/inversify.js",
"jsnext:main": "es/inversify.js",
Expand Down
7 changes: 7 additions & 0 deletions src/container/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,13 @@ class Container implements interfaces.Container {
return this.getAllTagged<T>(serviceIdentifier, METADATA_KEY.NAMED_TAG, named);
}

public resolve<T>(constructorFunction: interfaces.Newable<T>) {
const tempContainer = new Container();
tempContainer.bind<T>(constructorFunction).toSelf();
tempContainer.parent = this;
return tempContainer.get<T>(constructorFunction);
}

// Prepares arguments required for resolution and
// delegates resolution to _middleware if available
// otherwise it delegates resoltion to _planAndResolve
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ namespace interfaces {
getNamed<T>(serviceIdentifier: ServiceIdentifier<T>, named: string|number|symbol): T;
getTagged<T>(serviceIdentifier: ServiceIdentifier<T>, key: string|number|symbol, value: any): T;
getAll<T>(serviceIdentifier: ServiceIdentifier<T>): T[];
resolve<T>(constructorFunction: interfaces.Newable<T>): T;
load(...modules: ContainerModule[]): void;
unload(...modules: ContainerModule[]): void;
applyCustomMetadataReader(metadataReader: MetadataReader): void;
Expand Down
35 changes: 35 additions & 0 deletions test/features/resolve_unbinded.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect } from "chai";
import { Container, injectable } from "../../src/inversify";

describe("Container.prototype.resolve", () => {

it("Should be able to resolve a class that has not binded", () => {

@injectable()
class Katana {
public hit() {
return "cut!";
}
}

@injectable()
class Ninja implements Ninja {
public katana: Katana;
public constructor(katana: Katana) {
this.katana = katana;
}
public fight() { return this.katana.hit(); }
}

const container = new Container();
container.bind(Katana).toSelf();

const tryGet = () => container.get(Ninja);
expect(tryGet).to.throw("No matching bindings found for serviceIdentifier: Ninja");

const ninja = container.resolve(Ninja);
expect(ninja.fight()).to.eql("cut!");

});

});
34 changes: 33 additions & 1 deletion wiki/container_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,4 +278,36 @@ container.rebind<number>(TYPES.someType).toConstantValue(3);
let values2 = container.getAll(TYPES.someType);
expect(values2[0]).to.eq(3);
expect(values2[1]).to.eq(undefined);
```
```

## container.resolve<T>(constructor: Newable<T>)
Resolve is like `container.get<T>(serviceIdentifier: ServiceIdentifier<T>)` but it allows users to create an instance wven if no bindings have been declared:

```ts
@injectable()
class Katana {
public hit() {
return "cut!";
}
}

@injectable()
class Ninja implements Ninja {
public katana: Katana;
public constructor(katana: Katana) {
this.katana = katana;
}
public fight() { return this.katana.hit(); }
}

const container = new Container();
container.bind(Katana).toSelf();

const tryGet = () => container.get(Ninja);
expect(tryGet).to.throw("No matching bindings found for serviceIdentifier: Ninja");

const ninja = container.resolve(Ninja);
expect(ninja.fight()).to.eql("cut!");
```

Please note that it only allows to skip declaring a binding for the root element in the dependency graph (composition root). All the sub-dependencies (e.g. `Katana` in the preceding example) will require a binding to be declared.

0 comments on commit be1c2fc

Please sign in to comment.