MOBILE-3320 core: Refactor singletons definition
This commit is contained in:
		
							parent
							
								
									17dbc340e0
								
							
						
					
					
						commit
						e181a019e5
					
				| @ -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<Service> = Type<Service> | Type<unknown> | string; | ||||
| 
 | ||||
| /** | ||||
|  * Singleton class created using the factory. | ||||
|  */ | ||||
| export type CoreSingletonClass<Service> = 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<Service>(injectionToken: CoreInjectionToken<Service>): CoreSingletonClass<Service> { | ||||
|         // 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; | ||||
|             } | ||||
| 
 | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -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<Service> = 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<Service>(injectionToken: CoreInjectionToken<Service>): CoreSingletonClass<Service> { | ||||
|     return factory.makeSingleton(injectionToken); | ||||
| export function makeSingleton<Service>(injectionToken: Type<Service> | Type<unknown> | string): CoreSingletonClass<Service> { | ||||
|     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.
 | ||||
|  | ||||
| @ -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<U> { | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user