12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- import 'reflect-metadata';
- import { Constructor, Type } from './Types';
-
- class _Injector {
-
- private injectionQueue: any[] = []
- private modules: { implements?: Constructor<any>, ctor: Type<any> }[] = []
- private moduleObjs: { [key in string]: any } = {}
- private initialized = false
-
- /**
- * Resolves instances by injecting required services
- * @param {Type<any>} target
- * @returns {T}
- */
- public resolve<T>(target: Constructor<T>): T {
- if (!this.initialized) {
- this.initialize()
- this.initialized = true
- }
-
- return this.moduleObjs[target.name] as any
- }
-
- public async resolveAsync<T>(target: Type<T>): Promise<T> {
- if (!this.initialized) {
- await this.initialize()
- this.initialized = true
- }
-
- return this.moduleObjs[target.name] as any
- }
-
- private initialize = async (async?: boolean) => {
- this.createSingletons()
- this.injectDependencies()
- if (async)
- await this.initializeSingletons()
- else
- this.initializeSingletons()
- }
-
- private createSingletons = () => {
- //instantiate all non-root modules
- this.modules.forEach(m => {
- const module = new m.ctor()
- if (m.implements)
- this.moduleObjs[m.implements.name] = module
- this.moduleObjs[m.ctor.name] = module
- })
- }
-
- private injectDependencies = () => {
- while (this.injectionQueue.length > 0) {
- const inj = this.injectionQueue.shift()
-
- if (this.moduleObjs[inj.injectionType.name]) {
- this.moduleObjs[inj.instance.constructor.name][inj.injectIntoKey] = this.moduleObjs[inj.injectionType.name]
- } else {
- throw new Error("Cannot resolve injection token " + inj.injectionType.name)
- }
- }
- }
-
- private initializeSingletons = () => {
- Object.values(this.moduleObjs).forEach(element => element.initialize ? element.initialize() : undefined);
- }
- }
-
- /**
- * The Injector stores services and resolves requested instances.
- */
- export const Injector = new _Injector()
|