How can I register my own injection providers globally to work around circular module dependencies?

133 Views Asked by At

We can use Angular's @Injectable decorator to make a service available for dependency injection throughout the application. In this case, the service class itself will be used as the injection token; whoever injects it must know the class.

We can also define injection providers based on arbitrary injection tokens, but as far as I could find out, we can pass these only to newly created nested injectors.


I am working on a large Angular-based application that consists of many modules for different subject areas. Plenty of the modules will have to inject services from other modules, which invariably leads to circular references (on the TypeScript level) between the modules.

circular references between modules

The code of the injectable services must remain inside the modules (for otherwise, splitting everything up in modules would be pointless and I would end up with a single huge shared module).

However, I can extract interfaces for each service and place them into one or more modules that are compiled before any of the actual code modules. This results in the following structure (depicted in a simplified manner - actually, what is injected is an injection token typed to the interface):

circular references resolved

But now, where and how do I define static providers for these tokens?

  • Where: Presumably, somewhere as close to the root as possible ... is the idea that I concatenate all the providers into the providers array in the component that happens to represent the root of my UI?
  • How: This one seems harder. I cannot define the providers in the shared modules, as those must not have access to the modules with the service classes. I think they cannot be in the modules together with the services, either, because I do not know when those are loaded (upon request). How do I add this last missing link?

The only solution I can think of right now is to essentially write my own dependency injection system, separately from Angular's, in such a way that it includes lazy loading of modules, then register each pair of token + lazily loaded service class from one overarching module that is compiled last, but loaded first.


Context: The application I am working on consists of roughly 250 modules. Each module contains functionality related to a specific domain topic. These modules are typically lazy-loaded when the respective functionality in the application is accessed.

The ~150 developers working on the application are split up into teams of (on average) 5 to 10 people each. Each team is responsible for the features, internal technical design, and implementation of a couple of modules, about whose domain topic they are knowledgeable about.

Most of the domain-specific modules use a couple of services from several other domain-specific modules to link or combine functionality. Again, each module team is responsible for design and development of the publicly reachable interface of their modules (e.g. services usable by other modules).

0

There are 0 best solutions below