11import { IConstructor , IInjectionInstance , IInjectionMd , IProvider , LifeTime , ProviderToken , RegistrationProvider } from './interfaces' ;
2- import { IRegistryData , RegistryData } from './registry-data' ;
2+ import { FactoryFunction , IFactory , IRegistryData , RegistryData } from './registry-data' ;
33import { IContainer } from './container.interface' ;
4- import { ClassNotInjectableError , InvalidProviderProvidedError , NoProviderError } from './exceptions' ;
4+ import { InvalidProviderProvidedError , NoProviderError } from './exceptions' ;
55import { INJECTABLE_MD_KEY , INJECTIONS_MD_KEY } from './metadata/keys' ;
66import { IMetadataAnnotator } from './metadata/metadata-annotator.interface' ;
77import { AnnotatorProvider } from './metadata/index' ;
@@ -32,14 +32,14 @@ export class Container implements IContainer {
3232 return new Container ( this ) ;
3333 }
3434
35- public setParent ( parent : IContainer ) : void {
36- this . parent = parent ;
37- }
38-
3935 public createChild ( ) : IContainer {
4036 return new Container ( this ) ;
4137 }
4238
39+ public setParent ( parent : IContainer ) : void {
40+ this . parent = parent ;
41+ }
42+
4343 private resolveInternal ( token : ProviderToken , traceMessage ?: string ) : IInjectionInstance {
4444 traceMessage = this . buildTraceMessage ( token , traceMessage ) ;
4545
@@ -56,24 +56,7 @@ export class Container implements IContainer {
5656 return registryData . instance ;
5757 }
5858
59- if ( registryData . factory ) {
60- let injections : ProviderToken [ ] = [ ] ;
61-
62- if ( registryData . injections ) {
63- injections = registryData . injections . map ( i => this . resolveInternal ( i , traceMessage ) ) ;
64- }
65-
66- return registryData . factory ( ...injections ) ;
67- }
68-
69- const constructor : IConstructor = registryData . cls ;
70-
71- const isInjectable : boolean = this . isInjectable ( constructor ) ;
72- if ( ! isInjectable ) {
73- throw new ClassNotInjectableError ( constructor . name ) ;
74- }
75-
76- const instance : IInjectionInstance = this . createInstance ( constructor , traceMessage ) ;
59+ const instance : IInjectionInstance = this . instantiateWithFactory ( registryData . factory , traceMessage ) ;
7760
7861 if ( registryData . lifeTime === LifeTime . Persistent ) {
7962 registryData . instance = instance ;
@@ -92,28 +75,57 @@ export class Container implements IContainer {
9275
9376 if ( provider . useValue ) {
9477 registryData . instance = provider . useValue ;
95- } else if ( provider . useClass ) {
96- registryData . cls = provider . useClass ;
97- } else if ( provider . useFactory ) {
98- registryData . factory = provider . useFactory ;
99- registryData . injections = < ProviderToken [ ] > provider . inject ;
100- }
78+ } else {
79+ const factoryValue = provider . useFactory || provider . useClass ;
80+ const isClass : boolean = this . isInjectable ( factoryValue ) ;
81+
82+ registryData . factory = {
83+ value : factoryValue ,
84+ isClass
85+ } ;
86+
87+ if ( isClass ) {
88+ registryData . factory . inject = this . retrieveInjectionsFromClass ( < IConstructor > registryData . factory . value ) ;
89+ } else {
90+ registryData . factory . inject = this . convertTokensToInjectionMd ( < ProviderToken > provider . inject ) ;
91+ }
10192
102- registryData . lifeTime = provider . lifeTime || LifeTime . Persistent ;
93+ registryData . lifeTime = provider . lifeTime || LifeTime . Persistent ; // TODO issue #88
94+ }
10395
10496 this . registry . set ( provider . token , registryData ) ;
10597 }
10698
107- private createInstance ( cls : IConstructor , message : string ) : IInjectionInstance {
108- const injectionsMd : IInjectionMd [ ] = this . getInjections ( cls ) ;
109- const resolvedInjections : any [ ] = injectionsMd . map ( injectionMd => this . resolveInternal ( injectionMd . token , message ) ) ;
99+ private convertTokensToInjectionMd ( tokens : ProviderToken [ ] ) : IInjectionMd [ ] {
100+ let injections : IInjectionMd [ ] = [ ] ;
101+
102+ if ( tokens ) {
103+ injections = tokens . map ( ( token : ProviderToken , index : number ) => {
104+ return {
105+ token,
106+ parameterIndex : index
107+ } ;
108+ } ) ;
109+ }
110+
111+ return injections ;
112+ }
113+
114+ private instantiateWithFactory ( factory : IFactory , traceMessage : string ) : IInjectionInstance {
115+ const injections = < IInjectionMd [ ] > factory . inject ;
116+
117+ const resolvedInjections : any [ ] = injections . map ( injection => this . resolveInternal ( injection . token , traceMessage ) ) ;
110118
111119 const args : any [ ] = [ ] ;
112- injectionsMd . forEach ( ( injection : IInjectionMd , index ) => {
120+ injections . forEach ( ( injection : IInjectionMd , index : number ) => {
113121 args [ injection . parameterIndex ] = resolvedInjections [ index ] ;
114122 } ) ;
115123
116- return new cls ( ...args ) ;
124+ if ( factory . isClass ) {
125+ return new ( < IConstructor > factory . value ) ( ...args ) ;
126+ } else {
127+ return ( < FactoryFunction > factory . value ) ( ...args ) ;
128+ }
117129 }
118130
119131 private nornalizeProvider ( provider : RegistrationProvider | RegistrationProvider [ ] ) : IProvider {
@@ -167,7 +179,8 @@ export class Container implements IContainer {
167179 return ! ! ( MetadataAnnotator . getMetadata ( INJECTABLE_MD_KEY , cls ) ) ;
168180 }
169181
170- private getInjections ( cls : any ) : IInjectionMd [ ] {
171- return MetadataAnnotator . getMetadata ( INJECTIONS_MD_KEY , cls ) || [ ] ;
182+ private retrieveInjectionsFromClass ( cls : IConstructor ) : IInjectionMd [ ] {
183+ const injections : IInjectionMd [ ] = MetadataAnnotator . getMetadata ( INJECTIONS_MD_KEY , cls ) || [ ] ;
184+ return this . convertTokensToInjectionMd ( injections ) ;
172185 }
173186}
0 commit comments