You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Injector.ts 1.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import 'reflect-metadata';
  2. import { Constructor, Type } from './Types';
  3. class _Injector {
  4. private injectionQueue: any[] = []
  5. private modules: { implements?: Constructor<any>, ctor: Type<any> }[] = []
  6. private moduleObjs: { [key in string]: any } = {}
  7. private initialized = false
  8. /**
  9. * Resolves instances by injecting required services
  10. * @param {Type<any>} target
  11. * @returns {T}
  12. */
  13. public resolve<T>(target: Type<T>): T {
  14. if (!this.initialized) {
  15. this.initialize()
  16. this.initialized = true
  17. }
  18. return this.moduleObjs[target.name] as any
  19. }
  20. public async resolveAsync<T>(target: Type<T>): Promise<T> {
  21. if (!this.initialized) {
  22. await this.initialize()
  23. this.initialized = true
  24. }
  25. return this.moduleObjs[target.name] as any
  26. }
  27. private initialize = async (async?: boolean) => {
  28. this.createSingletons()
  29. this.injectDependencies()
  30. if (async)
  31. await this.initializeSingletons()
  32. else
  33. this.initializeSingletons()
  34. }
  35. private createSingletons = () => {
  36. //instantiate all non-root modules
  37. this.modules.forEach(m => {
  38. const module = new m.ctor()
  39. if (m.implements)
  40. this.moduleObjs[m.implements.name] = module
  41. this.moduleObjs[m.ctor.name] = module
  42. })
  43. }
  44. private injectDependencies = () => {
  45. while (this.injectionQueue.length > 0) {
  46. const inj = this.injectionQueue.shift()
  47. if (this.moduleObjs[inj.injectionType.name]) {
  48. inj.prototype[inj.injectIntoKey] = this.moduleObjs[inj.injectionType.name]
  49. } else {
  50. throw new Error("Cannot resolve injection token " + inj.injectionType.name)
  51. }
  52. }
  53. }
  54. private initializeSingletons = () => {
  55. Object.values(this.moduleObjs).forEach(element => element.initialize ? element.initialize() : undefined);
  56. }
  57. }
  58. /**
  59. * The Injector stores services and resolves requested instances.
  60. */
  61. export const Injector = new _Injector()