我试图用两种方式明确地创建依赖.两者几乎相同,但我有点混淆使用反射注射器优于普通注射器的优势是什么?推荐哪种方式?
使用注射器
import { Injector } from '@angular/core'; constructor( private injector: Injector) { this.myService = this.injector.get(MyService); }
使用反射注射器
import { ReflectiveInjector } from '@angular/core'; constructor() { var injector= ReflectiveInjector.resolveAndCreate([MyService]); let myservice=injector.get(MyService); }
注入器是具有提供者/服务的容器.它实现了一个方法get并返回一个服务实例.让我们在JS伪代码中实现最基本的注入器版本:
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 }); } }
现在,我们需要在使用它之前创建注入器的实例.当我们创建它时,我们定义提供者:
const existingInjector = ReflectiveInjector.resolveAndCreate([{provide: A,useClass: A }]); const AInstance = existingInjector.get(A);
所以你看,为了使用注射器,必须首先创建它.它没有任何允许添加提供程序的特定方法,因此在创建之后我们无法向其添加任何新提供程序.
注入组件构造函数的注入器已由Angular创建.您无法向其添加任何内容,只能查询已在其上定义的提供程序.如果您需要提供B类,则不能使用现有的注射器.你需要一个新的.这就是ReflectiveInjector类的用武之地.它允许您通过创建注入器的新实例并注册新的提供程序来添加新的提供程序.而且好处是它还可以设置喷射器链.
让我们稍微修改resolveAndCreate并获取允许链接注入器的方法:
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; }
所以现在唯一剩下的就是使用它:
// passing existingInjector as a parent const childInjector = ReflectiveInjector.resolveAndCreate([{provide: B,useClass: B }],i); const AInstance = childInjector.get(A); const BInstance = childInjector.get(B);
现在,假设有人可能想要访问我们现有的注入者.我们需要一个令牌来使用这个现有的注入器.让我们像这样定义这个标记:
abstract class Injector {}
让我们编写一个能够获得现有注入器的函数:
function resolveDependency(token) { if (token === Injector) { return existingInjector; } }
现在假设Angular在执行组件的构造函数时,使用您指定的标记来获取依赖项并将它们传递给resolveDependency函数.所以你这样写:
// the Injector here is a reference to our abstract Injector class and simply used as a token MyComp { constructor(private injector: Injector) { ... } }
这里的令牌是Injector,正如我所说,它被传递到resolveDependency函数并返回现有的注入器.