Injection via the constructor parameters vs. the Injector service

Viewed 2117

I am using Angular2/4 for few months now and I still cannot figure out what is the difference between these two methods and which one I should use about Dependency Injection

Can you help me please.

First method : via the constructor

...
  constructor(
    private myService: MyService
  ) { 
    // this.myService.myMethod() ...
  }
...

and

Second Method : via the Injector

...
  private myService: MyService;

  constructor(
    injector: Injector
  ) {
    this.myService = injector.get(MyService);
    // this.myService.myMethod() ...
  }
...

I understand what is done in each method, bubt I cannot figure out the best practice.

I know it is probably a subjective opinion, but I think there pros and cons for both of them.

Thanks for any explanation.

2 Answers

You should always prefer the first option:

...
  constructor(
    private myService: MyService
  ) { 
    // this.myService.myMethod() ...
  }
...

The second approach works because when you inject MyService it is injected using the Injector.

Angular makes Injector available for injection because you may need to use it when dynamically instantiating modules or components:

Component:

export class ModuleLoaderComponent {
  constructor(private _injector: Injector,private loader: NgModuleFactoryLoader) { ... }

  ngAfterViewInit() {
    this.loader.load('app/t.module#TModule').then((factory) => {
      const module = factory.create(this._injector);  <-----------------

Module:

export class RouterConfigLoader {

  load(parentInjector, route) {
    ...
    const modFactory = this.loadModuleFactory(route.loadChildren);
    const module = modFactory.create(parentInjector);
  }

You can read more about dynamic instantiation in the following articles:

As @estus noted, injector is also used in cases where injecting a dependency in a constructor results in circular dependency or you want to get dependency depending on some conditions.

I've been told that it is often better to use the constructor method for dependency injection. It tells you exactly what this class needs.

On the other hand, there are cases where you are better off using the injector. Along with dynamic instantiation, you also have to consider class inheritance Suppose that you want to build a component off of a base component that brings in services S2 that is also based on other services S1. that is C2(S2) from C1(S1).

Normally, C2 instantiates C1 using the super, which looks something like this

constructor(
    private service2: S2
  ) { 
    super(S1)
  }

I see a problem with having to call the parent service S1 and S2 in order to build C2. It gets less tangled if S1 uses the injector method so that writing C2 is as simple as

constructor(
    private injector: Injector
  ) { 
    super()
    this.service2 = this.injector.get(S2)
  }

private service2: S2

You can go further and create your own injector singleton if want to forgo setting instance in the constructor. See this article

Related