Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
510 views
in Technique[技术] by (71.8m points)

dependency injection - Difference between Reflective Injector and Injector in Angular

I tried to create dependency explictly using two ways. Both are almost same but I am little bit confusing what's the advantage of using Reflective Injector over the normal Injector and which one is recommended way?

Using Injector

import { Injector } from '@angular/core';
constructor( private injector: Injector) {
    this.myService = this.injector.get(MyService);
  }

Using Reflective Injector

import { ReflectiveInjector } from '@angular/core';
 constructor() {

       var injector= ReflectiveInjector.resolveAndCreate([MyService]);
       let myservice=injector.get(MyService);
     }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

An injector is a container with providers/services. It implements one method get and returns an instance of the service. Let's implement the most basic version of the injector in JS pseudocode:

class ReflectiveInjector {
   providers = [];

   static resolveAndCreate(providers) {
     providers.forEach((provider)=>{
         providers.push({token: provider.provide, instance: new provider.useClass})
     });  
  )}

  get(dep) {
     return providers.find((provider)=>{ return provider.token === token });
  }
}

Now, we need to create the instance of the injector before we can use it. And when we create it we define providers:

const existingInjector = ReflectiveInjector.resolveAndCreate([{provide: A, useClass: A }]);
const AInstance = existingInjector.get(A);

So you see in order to use an injector it has to be created first. It doesn't have any specific methods that allow adding providers so after it's created we can't add any new providers to it.

The injector you inject into the component constructor is already created by Angular. You can't add anything to it and can query only the providers already defined on it. If you need to provide B class, you can't do that with existing injector. You need a new one. And this is where ReflectiveInjector class comes in. It allows you to add new providers by creating a new instance of the injector and registering new providers. And the good part is that it can also setup an injector chain.

Let's a bit modify resolveAndCreate and get methods to allow chaining injectors:

class ReflectiveInjector {
   providers = [];
   parent;

   static resolveAndCreate(providers, parent) {
       this.parent = parent;
   ...
   }

   get(dep) {
       let found = providers.find((provider)=>{ return provider.token === token });
       if (!found && parent) {
            found = parent.get(dep);
       }

       return found;
   }

So now the only that left is to use it:

// passing existingInjector as a parent
const childInjector = ReflectiveInjector.resolveAndCreate([{provide: B, useClass: B }], i);
const AInstance = childInjector.get(A);
const BInstance = childInjector.get(B);

Now, suppose someone might want to get access to our existingInjector. We need a token to use to get this existing injector. Let's define this token like this:

abstract class Injector {}

and let's write a function that will get the existing injector:

function resolveDependency(token) {
   if (token === Injector) {
       return existingInjector;
   }
}

And now suppose that Angular when executes the constructor of the component, uses the tokens you specified to get dependencies and passes them to the resolveDependency function. So you write like this:

// the Injector here is a reference to our abstract Injector class and simply used as a token
MyComp {
   constructor(private injector: Injector) { ...  }
}

And the token here is Injector which as I said is passed into the resolveDependency function and the existing injector is returned.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...