123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- import 'reflect-metadata';
- import { ERR_NO_INITIALIZE_WITH_PRIORITY, ERR_NO_INJECTION_TOKEN } from './Strings';
- import { Constructor, Type, SingletonDefinition, InjectionError, InjectionResolutionError } from './Internals';
-
- class _Injector {
-
- private injectionQueue: any[] = []
- private singletonDefinitions: SingletonDefinition[] = []
-
- private singletonObjects: { [classname in string]: any } = {}
- private tokenLookupTable: { [token in string]: Constructor<any> } = {}
-
- private initialized = false
-
- /**
- * Resolves instances by injecting required services
- * @param {Type<any>} request
- * @returns {T}
- */
- public resolve<T>(request: Constructor<T>): T {
- if (!this.initialized) {
- this.initialize()
- this.initialized = true
- }
-
- return this.singletonObjects[request.name] as any
- }
-
- public async resolveAsync<T>(target: Type<T>): Promise<T> {
- if (!this.initialized) {
- this.initialize()
- this.initialized = true
- }
-
- return this.singletonObjects[target.name] as any
- }
-
- private initialize = () => {
- this.createSingletons()
- this.injectDependencies()
- this.initializeSingletons()
- this.cleanup()
- }
-
- private createSingletons = () => {
- this.singletonDefinitions.forEach(def => {
- const obj = new def.ctor()
-
- if (def.initializationPriority != undefined && !obj.initialize) {
- throw new InjectionError(ERR_NO_INITIALIZE_WITH_PRIORITY(def.ctor))
- }
-
- this.singletonObjects[def.ctor.name] = obj
- })
- }
-
- private injectDependencies = () => {
- this.injectionQueue.forEach(inj => {
-
- if (inj.token.name in this.tokenLookupTable) { //injection alias was used
- inj.token = this.tokenLookupTable[inj.token.name]
- }
-
- if (this.singletonObjects[inj.token.name]) {
- this.singletonObjects[inj.receiver.constructor.name][inj.key] = this.singletonObjects[inj.token.name]
- } else {
- throw new InjectionResolutionError(ERR_NO_INJECTION_TOKEN(inj.injectionType))
- }
- })
- }
-
- private initializeSingletons = () => {
- this.singletonDefinitions
- .sort((a, b) => (b.initializationPriority ?? 0) - (a.initializationPriority ?? 0))
- .map(def => this.singletonObjects[def.ctor.name])
- .forEach(obj => obj.initialize ? obj.initialize() : undefined)
- }
-
- private cleanup = () => {
- while (this.singletonDefinitions.length > 0)
- this.singletonDefinitions.pop()
- while (this.injectionQueue.length > 0)
- this.injectionQueue.pop()
- }
- }
-
- /**
- * The Injector stores services and resolves requested instances.
- */
- export const Injector = new _Injector()
|