From e181a019e5be96dc412f8c36ac02b175337a1e0e Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 7 Dec 2020 14:31:40 +0100 Subject: [PATCH] MOBILE-3320 core: Refactor singletons definition --- src/core/classes/singletons-factory.ts | 88 -------------------------- src/core/singletons/index.ts | 49 ++++++++++++-- src/testing/utils.ts | 2 +- 3 files changed, 43 insertions(+), 96 deletions(-) delete mode 100644 src/core/classes/singletons-factory.ts diff --git a/src/core/classes/singletons-factory.ts b/src/core/classes/singletons-factory.ts deleted file mode 100644 index d574f6591..000000000 --- a/src/core/classes/singletons-factory.ts +++ /dev/null @@ -1,88 +0,0 @@ -// (C) Copyright 2015 Moodle Pty Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import { Injector, Type } from '@angular/core'; - -/** - * Stub class used to type anonymous classes created in CoreSingletonsFactory#makeSingleton method. - */ -class CoreSingleton {} - -/** - * Token that can be used to resolve instances from the injector. - */ -export type CoreInjectionToken = Type | Type | string; - -/** - * Singleton class created using the factory. - */ -export type CoreSingletonClass = typeof CoreSingleton & { - instance: Service; - setInstance(instance: Service): void; -}; - -/** - * Factory used to create CoreSingleton classes that get instances from an injector. - */ -export class CoreSingletonsFactory { - - /** - * Angular injector used to resolve singleton instances. - */ - private injector?: Injector; - - /** - * Set the injector that will be used to resolve instances in the singletons created with this factory. - * - * @param injector Injector. - */ - setInjector(injector: Injector): void { - this.injector = injector; - } - - /** - * Make a singleton that will hold an instance resolved from the factory injector. - * - * @param injectionToken Injection token used to resolve the singleton instance. This is usually the service class if the - * provider was defined using a class or the string used in the `provide` key if it was defined using an object. - */ - makeSingleton(injectionToken: CoreInjectionToken): CoreSingletonClass { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const factory = this; - - return class { - - private static serviceInstance: Service; - - static get instance(): Service { - // Initialize instances lazily. - if (!this.serviceInstance) { - if (!factory.injector) { - throw new Error('Can\'t resolve a singleton instance without an injector'); - } - - this.serviceInstance = factory.injector.get(injectionToken); - } - - return this.serviceInstance; - } - - static setInstance(instance: Service): void { - this.serviceInstance = instance; - } - - }; - } - -} diff --git a/src/core/singletons/index.ts b/src/core/singletons/index.ts index 161f310ae..bab681879 100644 --- a/src/core/singletons/index.ts +++ b/src/core/singletons/index.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ApplicationRef, ApplicationInitStatus, Injector, NgZone as NgZoneService } from '@angular/core'; +import { ApplicationRef, ApplicationInitStatus, Injector, NgZone as NgZoneService, Type } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { @@ -52,9 +52,23 @@ import { Zip as ZipService } from '@ionic-native/zip/ngx'; import { TranslateService } from '@ngx-translate/core'; -import { CoreSingletonsFactory, CoreInjectionToken, CoreSingletonClass } from '@classes/singletons-factory'; +/** + * Injector instance used to resolve singletons. + */ +let singletonsInjector: Injector | null = null; -const factory = new CoreSingletonsFactory(); +/** + * Stub class used to type anonymous classes created in the makeSingleton method. + */ +class CoreSingleton {} + +/** + * Singleton class created using the factory. + */ +export type CoreSingletonClass = typeof CoreSingleton & { + instance: Service; + setInstance(instance: Service): void; +}; /** * Set the injector that will be used to resolve instances in the singletons of this module. @@ -62,17 +76,38 @@ const factory = new CoreSingletonsFactory(); * @param injector Module injector. */ export function setSingletonsInjector(injector: Injector): void { - factory.setInjector(injector); + singletonsInjector = injector; } /** - * Make a singleton for this module. + * Make a singleton for the given injection token. * * @param injectionToken Injection token used to resolve the singleton instance. This is usually the service class if the * provider was defined using a class or the string used in the `provide` key if it was defined using an object. */ -export function makeSingleton(injectionToken: CoreInjectionToken): CoreSingletonClass { - return factory.makeSingleton(injectionToken); +export function makeSingleton(injectionToken: Type | Type | string): CoreSingletonClass { + return class { + + private static serviceInstance: Service; + + static get instance(): Service { + // Initialize instances lazily. + if (!this.serviceInstance) { + if (!singletonsInjector) { + throw new Error('Can\'t resolve a singleton instance without an injector'); + } + + this.serviceInstance = singletonsInjector.get(injectionToken); + } + + return this.serviceInstance; + } + + static setInstance(instance: Service): void { + this.serviceInstance = instance; + } + + }; } // Convert ionic-native services to singleton. diff --git a/src/testing/utils.ts b/src/testing/utils.ts index 97d6bba4b..8bbfddc4e 100644 --- a/src/testing/utils.ts +++ b/src/testing/utils.ts @@ -15,7 +15,7 @@ import { Component, CUSTOM_ELEMENTS_SCHEMA, Type, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreSingletonClass } from '@classes/singletons-factory'; +import { CoreSingletonClass } from '@singletons'; abstract class WrapperComponent {