angular - Tillhandahåll samma tjänsteinstans under olika tokens
Jag har 2 gränssnitt:
export interface IUserService {
...
}
export interface IUserStorageService {
...
}
Och en enda tjänst som implementerar båda:
@Injectable()
export class UserService implements IUserService, IUserStorageService {
...
}
(Denna del verkar irrelevant för frågan, så det är bara för fullständighetens skull. Jag kan enkelt omvandla gränssnitt till abstrakta klasser för att använda dem direkt som tokens utan ytterligare injektionstokens.)
Nu, eftersom Angular inte stöder gränssnitt som tokens för providers, måste jag skapa injektionstokens:
export let USER_SERVICE: InjectionToken<IUserService> = new InjectionToken<IUserService>("user.service");
export let USER_STORAGE_SERVICE: InjectionToken<IUserStorageService> = new InjectionToken<IUserStorageService>("user-storage.service");
Och nu kan jag mappa dessa injektionstoken till den enda tjänsteklassen globalt i min app.module.ts:
@NgModule({
...
providers: [
{ provide: USER_SERVICE, useClass: UserService },
{ provide: USER_STORAGE_SERVICE, useClass: UserService }
],
...
})
export class AppModule {
...
}
Och slutligen kan jag nu injicera tjänsten under olika gränssnitt till mina komponenter:
// Some component - sees service's API as IUserService
constructor(@Inject(USER_SERVICE) private readonly userService: IUserService) {
}
// Another component- sees service's API as IUserStorageService
constructor(@Inject(USER_STORAGE_SERVICE) private readonly userStorageService: IUserStorageService) {
}
Problemet här är att Angular faktiskt skapar 2 instanser av UserService, en för varje token, medan jag behöver att UserService ska vara en enda instans per app.
Hur kan jag uppnå det?
Svar #1
Jag hade ett mycket liknande krav: Jag tillhandahöll en tjänst till flera komponenter - tjänsten har en dispatchEvent-funktion och en subscribeToEvents-funktion. Jag vill att det ska vara tydligt att endast den hanterande komponenten kan använda dispatchEvent(), så tjänsten implementerar två abstrakta klasser (dessa kan sedan användas som token - vilket är tydligare än formatet för injektionstoken) - den ena har dispatchEvents, den andra har subscribeToEvents
providers: [
{provide: AbstractSettingsManager, useClass: SettingsEventService},
{provide: AbstractSettingsConsumer, useExisting: AbstractSettingsManager}
],
Du kan använda useExisting-nyckeln, och kom ihåg att det betyder "använd den befintliga token"
Komponenterna kommer alla att ha samma ServiceEventService-instans, men eftersom jag tillhandahåller AbstractSettingsManager/AbstractSettingsConsumer kommer komponenterna bara att ha tillgång (via TypeScript-kontroller) till antingen den ena eller den andra av tjänstens funktioner
