From 82f016a519d507b09d2c22178524c27005bee3e2 Mon Sep 17 00:00:00 2001 From: "thomasnlowe@gmail.com" Date: Sat, 18 Nov 2017 23:39:23 -0600 Subject: [PATCH 1/3] feat(container): add self registration of container in constructor, test, and document it --- examples/javascript/resolving-container.js | 12 ++++++++++ examples/typescript/resolving-container.ts | 12 ++++++++++ src/lib/container.interface.ts | 6 ++++- src/lib/container.ts | 3 ++- src/lib/index.ts | 2 +- src/tests/container.spec.ts | 27 ++++++++++++++++++++-- 6 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 examples/javascript/resolving-container.js create mode 100644 examples/typescript/resolving-container.ts diff --git a/examples/javascript/resolving-container.js b/examples/javascript/resolving-container.js new file mode 100644 index 0000000..465c483 --- /dev/null +++ b/examples/javascript/resolving-container.js @@ -0,0 +1,12 @@ +import { Container, TContainer, Injectable } from 'container-ioc'; + +const container = new Container(); + +@Injectable([TContainer]) +class Builder { + constructor(container) {} +} + +container.register({ token: Builder, useClass: Builder }); + +const builder = container.resolve(Builder); \ No newline at end of file diff --git a/examples/typescript/resolving-container.ts b/examples/typescript/resolving-container.ts new file mode 100644 index 0000000..9dcd778 --- /dev/null +++ b/examples/typescript/resolving-container.ts @@ -0,0 +1,12 @@ +import { IContainer, Container, TContainer, Injectable, Inject } from 'container-ioc'; + +const container = new Container(); + +@Injectable() +class Builder { + constructor(@Inject(TContainer) private container: IContainer) {} +} + +container.register({ token: Builder, useClass: Builder }); + +const builder = container.resolve(Builder); \ No newline at end of file diff --git a/src/lib/container.interface.ts b/src/lib/container.interface.ts index 918f9f1..1deb87c 100644 --- a/src/lib/container.interface.ts +++ b/src/lib/container.interface.ts @@ -6,6 +6,8 @@ export interface IContainerOptions { } export interface IContainer { + [key: string]: any; + register(provider: RegistrationProvider|RegistrationProvider[]): void; resolve(token: ProviderToken): IInjectionInstance; @@ -18,4 +20,6 @@ export interface IContainer { createChild(): IContainer; setParent(parent: IContainer): void; -} \ No newline at end of file +} + +export const TContainer = Symbol('IContainer'); \ No newline at end of file diff --git a/src/lib/container.ts b/src/lib/container.ts index c0a0953..ce0cc52 100644 --- a/src/lib/container.ts +++ b/src/lib/container.ts @@ -1,6 +1,6 @@ import { IConstructor, IInjectionInstance, IInjectionMd, IProvider, LifeTime, ProviderToken, RegistrationProvider } from './interfaces'; import { FactoryFunction, IFactory, IRegistryData, RegistryData } from './registry-data'; -import { IContainer, IContainerOptions } from './container.interface'; +import { IContainer, IContainerOptions, TContainer } from './container.interface'; import { ClassNotInjectableError, InvalidProviderProvidedError, NoProviderError } from './exceptions'; import { INJECTABLE_MD_KEY, INJECTIONS_MD_KEY } from './metadata/keys'; import { IMetadataAnnotator } from './metadata/metadata-annotator.interface'; @@ -21,6 +21,7 @@ export class Container implements IContainer { this.parent = options.parent; this.defaultLifeTime = options.defaultLifeTime || this.defaultLifeTime; } + this.register({ token: TContainer, useValue: this }); } public register(provider: RegistrationProvider|RegistrationProvider[]): void { diff --git a/src/lib/index.ts b/src/lib/index.ts index d5e2729..fb54755 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,5 +1,5 @@ export { Container } from './container'; -export { IContainer } from './container.interface'; +export { IContainer, TContainer } from './container.interface'; export { Inject, Injectable } from './decorators'; export { InjectionToken } from './injection-token'; export { IMetadataAnnotator } from './metadata/metadata-annotator.interface'; diff --git a/src/tests/container.spec.ts b/src/tests/container.spec.ts index 8b8b27b..2bcaf17 100644 --- a/src/tests/container.spec.ts +++ b/src/tests/container.spec.ts @@ -1,4 +1,4 @@ -import { IContainer } from '../lib/container.interface'; +import { IContainer, TContainer } from '../lib/container.interface'; import { Container } from '../lib/index'; import 'mocha'; @@ -356,6 +356,21 @@ describe('Container', () => { expect(throwableFunc).to.throw('No provider for IB. Trace: IA --> IB'); }); + + it('should resolve container instance when injected into class Literal', () => { + // arrange + @Injectable() + class TestClass { + constructor(@Inject(TContainer) public a: IContainer) {} + } + container.register({ token: TestClass, useClass: TestClass }); + // act + const actual = container.resolve(TestClass); + // assert + expect(actual).to.be.ok; + expect(actual.a).to.be.ok; + expect(actual.a).to.equal(container); + }); }); describe('Hierarchial', () => { @@ -449,6 +464,14 @@ describe('Container', () => { expect(instance1).not.to.be.equal(instance2); }); + + it('should register itself for injection', () => { + // arrange, act + const actual = container.resolve(TContainer); + // assert + expect(actual).to.be.ok; + expect(actual).to.equal(container); + }); }); describe('createChild()', () => { @@ -471,5 +494,5 @@ describe('Container', () => { expect(value).to.be.equal('string'); }); - }); + }); }); \ No newline at end of file From bfaf4693672e2873107304f2bac4ab52b2a6028a Mon Sep 17 00:00:00 2001 From: "thomasnlowe@gmail.com" Date: Fri, 1 Dec 2017 21:52:55 -0600 Subject: [PATCH 2/3] fix(code-review): remove test comments and interface prop as per pr comments --- src/lib/container.interface.ts | 4 +--- src/lib/index.ts | 1 - src/tests/container.spec.ts | 8 +++----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/lib/container.interface.ts b/src/lib/container.interface.ts index 1deb87c..1bb099a 100644 --- a/src/lib/container.interface.ts +++ b/src/lib/container.interface.ts @@ -5,9 +5,7 @@ export interface IContainerOptions { defaultLifeTime?: LifeTime; } -export interface IContainer { - [key: string]: any; - +export interface IContainer { register(provider: RegistrationProvider|RegistrationProvider[]): void; resolve(token: ProviderToken): IInjectionInstance; diff --git a/src/lib/index.ts b/src/lib/index.ts index 243824e..2392651 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,6 +1,5 @@ export { Container } from './container'; export { IContainer, TContainer } from './container.interface'; -export { Inject, Injectable } from './decorators'; export { Inject, Injectable, Component } from './decorators'; export { InjectionToken } from './injection-token'; export { IMetadataAnnotator } from './metadata/metadata-annotator.interface'; diff --git a/src/tests/container.spec.ts b/src/tests/container.spec.ts index 2bcaf17..ab15ed9 100644 --- a/src/tests/container.spec.ts +++ b/src/tests/container.spec.ts @@ -358,15 +358,14 @@ describe('Container', () => { }); it('should resolve container instance when injected into class Literal', () => { - // arrange @Injectable() class TestClass { constructor(@Inject(TContainer) public a: IContainer) {} } + container.register({ token: TestClass, useClass: TestClass }); - // act const actual = container.resolve(TestClass); - // assert + expect(actual).to.be.ok; expect(actual.a).to.be.ok; expect(actual.a).to.equal(container); @@ -466,9 +465,8 @@ describe('Container', () => { }); it('should register itself for injection', () => { - // arrange, act const actual = container.resolve(TContainer); - // assert + expect(actual).to.be.ok; expect(actual).to.equal(container); }); From 869bada180ce0bf10662a88ec390a563f586daf9 Mon Sep 17 00:00:00 2001 From: "thomasnlowe@gmail.com" Date: Fri, 1 Dec 2017 22:02:55 -0600 Subject: [PATCH 3/3] feat(container): remove tcontainer symbol and resolve as class type as per pr comments --- examples/javascript/resolving-container.js | 4 ++-- examples/typescript/resolving-container.ts | 4 ++-- src/lib/container.interface.ts | 4 +--- src/lib/container.ts | 4 ++-- src/lib/index.ts | 2 +- src/tests/container.spec.ts | 6 +++--- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/examples/javascript/resolving-container.js b/examples/javascript/resolving-container.js index 465c483..b66392c 100644 --- a/examples/javascript/resolving-container.js +++ b/examples/javascript/resolving-container.js @@ -1,8 +1,8 @@ -import { Container, TContainer, Injectable } from 'container-ioc'; +import { Container, Injectable } from 'container-ioc'; const container = new Container(); -@Injectable([TContainer]) +@Injectable([Container]) class Builder { constructor(container) {} } diff --git a/examples/typescript/resolving-container.ts b/examples/typescript/resolving-container.ts index 9dcd778..3a97cf1 100644 --- a/examples/typescript/resolving-container.ts +++ b/examples/typescript/resolving-container.ts @@ -1,10 +1,10 @@ -import { IContainer, Container, TContainer, Injectable, Inject } from 'container-ioc'; +import { IContainer, Container, Injectable, Inject } from 'container-ioc'; const container = new Container(); @Injectable() class Builder { - constructor(@Inject(TContainer) private container: IContainer) {} + constructor(@Inject(Container) private container: IContainer) {} } container.register({ token: Builder, useClass: Builder }); diff --git a/src/lib/container.interface.ts b/src/lib/container.interface.ts index 1bb099a..cf3b5f0 100644 --- a/src/lib/container.interface.ts +++ b/src/lib/container.interface.ts @@ -18,6 +18,4 @@ export interface IContainer { createChild(): IContainer; setParent(parent: IContainer): void; -} - -export const TContainer = Symbol('IContainer'); \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/container.ts b/src/lib/container.ts index ce0cc52..5faed28 100644 --- a/src/lib/container.ts +++ b/src/lib/container.ts @@ -1,6 +1,6 @@ import { IConstructor, IInjectionInstance, IInjectionMd, IProvider, LifeTime, ProviderToken, RegistrationProvider } from './interfaces'; import { FactoryFunction, IFactory, IRegistryData, RegistryData } from './registry-data'; -import { IContainer, IContainerOptions, TContainer } from './container.interface'; +import { IContainer, IContainerOptions } from './container.interface'; import { ClassNotInjectableError, InvalidProviderProvidedError, NoProviderError } from './exceptions'; import { INJECTABLE_MD_KEY, INJECTIONS_MD_KEY } from './metadata/keys'; import { IMetadataAnnotator } from './metadata/metadata-annotator.interface'; @@ -21,7 +21,7 @@ export class Container implements IContainer { this.parent = options.parent; this.defaultLifeTime = options.defaultLifeTime || this.defaultLifeTime; } - this.register({ token: TContainer, useValue: this }); + this.register({ token: Container, useValue: this }); } public register(provider: RegistrationProvider|RegistrationProvider[]): void { diff --git a/src/lib/index.ts b/src/lib/index.ts index 2392651..0a736e5 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,5 +1,5 @@ export { Container } from './container'; -export { IContainer, TContainer } from './container.interface'; +export { IContainer } from './container.interface'; export { Inject, Injectable, Component } from './decorators'; export { InjectionToken } from './injection-token'; export { IMetadataAnnotator } from './metadata/metadata-annotator.interface'; diff --git a/src/tests/container.spec.ts b/src/tests/container.spec.ts index ab15ed9..0024d94 100644 --- a/src/tests/container.spec.ts +++ b/src/tests/container.spec.ts @@ -1,4 +1,4 @@ -import { IContainer, TContainer } from '../lib/container.interface'; +import { IContainer } from '../lib/container.interface'; import { Container } from '../lib/index'; import 'mocha'; @@ -360,7 +360,7 @@ describe('Container', () => { it('should resolve container instance when injected into class Literal', () => { @Injectable() class TestClass { - constructor(@Inject(TContainer) public a: IContainer) {} + constructor(@Inject(Container) public a: IContainer) {} } container.register({ token: TestClass, useClass: TestClass }); @@ -465,7 +465,7 @@ describe('Container', () => { }); it('should register itself for injection', () => { - const actual = container.resolve(TContainer); + const actual = container.resolve(Container); expect(actual).to.be.ok; expect(actual).to.equal(container);