angularfactoryangular-providersangular-factory

Angular creating named instances of providers


In Angular I have a service to access a cache. The service roughly works like this (but with a lot more asynchronous behavior).

@Injectable()
export class Cache {

  cache : CacheTable;

  constructor(
    protected name : string
  ) {
    this.cache = this.getTable(name);
  }

  put(id:string, data:any):void { this.cache.put(id, data); }
  get(id:string):any { return this.cache.get(id); }

  getTable(name : string) : CacheTable;

}

Now I have a number of services like UserService that would like to have a Cache corresponding to new Cache('user');. Another service named ImageService should work with an instance of Cache corresponding to new Cache('image');

For this I would like to create a Factory to provide these:

// file: custom-caches.ts

import { Provider } from '@angular/core';
import { Cache } from '../cache/cache';

export let userCache : Provider = {
  provide: Cache,
  useFactory: () => new Cache('user')
};

export let imageCache : Provider = {
  provide: Cache,
  useFactory: () => new Cache('image')
};

How would I go about registering and using each of these services? As far as I can tell they're all registered as 'Cache'.

// file: my.module.ts

@NgModule({
  providers: [userCache, imageCache]
})
export class MyModule {}

(This relates to my other question)


Solution

  • As suggested by @ghetolay I used InjectionToken and was able to successfully create multiple named providers as factoried instances:

    // file: custom-caches.ts
    
    import { Provider } from '@angular/core';
    import { Cache } from '../cache/cache';
    
    export const UserCache = new InjectionToken('userCache');
    
    export let userCacheProvider : Provider = {
      provide: UserCache,
      useFactory: () => new Cache('user')
    };
    
    export const ImageCache = new InjectionToken('imageCache');
    
    export let imageCacheProvider : Provider = {
      provide: ImageCache,
      useFactory: () => new Cache('image')
    };
    

    _

    // file: my.module.ts
    
    @NgModule({
      providers: [userCacheProvider, imageCacheProvider]
    })
    export class MyModule {}
    

    _

    // file : UserService
    
    @Injectable()
    export class UserService {
      constructor(
        @Inject(UserCache) private cache : Cache
      ) {}
    }
    

    UserCache and ImageCache are now tokens for these provider instances.