Search code examples
angularstrategy-patternservice-locator

Angular: lookup all providers implementing a specific interface


In my Angular (4+) application, I want to create a basic plugin mechanism:

  • The extension point is defined as an interface
  • Extensions implement that interface
  • To find all extensions, I need to discover the implementations of that interface at runtime.

Example: interface SearchStrategy with implementations PersonSearchStrategy and DocumentSearchStrategy (both services, registered as providers).

Is there a way to dynamically get instances of these services by querying for implementations of the SearchStrategy interface? How?

(might be some Injector related functionality?)


Solution

  • It's kinda possible, provided if you register the services with InjectionToken and use provide multi.

    You can create an injection token with interface.

    export const SearchStrategyToken = new InjectionToken<SearchStrategy[]>('SearchStrategy');
    

    In your module register:

    providers: [
      {provide: SearchStrategyToken, useClass: PersonSearchStrategy, multi: true}, 
      {provide: SearchStrategyToken, useClass: DocumentSearchStrategy, multi: true},
    ]
    

    In your component or service:

    constructor(private injector: Injector) {
    
      const services = this.injector
      .get(SearchStrategyToken); // return 2 items [ PersonSearchStrategy, DocumentSearchStrategy ]
    
      const personSearch = services.find(x => x.constructor.name === 'PersonSearchStrategy');
    
      const docSearch = services.find(x => x.constructor.name === 'DocumentSearchStrategy');
    
    }
    

    Code example provided here: https://stackblitz.com/edit/angular-clxr6k.

    However, it would be good if you provide more details on your use case. Probably there are better solution than going for the above route.