【问题标题】:Obtaining a disjoint dependency injector in Angular 2在 Angular 2 中获取不相交的依赖注入器
【发布时间】:2017-07-24 07:29:37
【问题描述】:

我目前正在使用 Angular 4 的异步编译器来动态加载外部模块并使用 NgComponentOutlet 将其组件之一添加到 DOM 中。外部模块意味着在功能上与主应用程序脱节,因此它应该有自己的、唯一的依赖注入器(或者更确切地说,一个无法访问父模块提供者的注入器)。但是,如果我使用 ReflectiveInjector.resolveAndCreate 创建一个新的依赖注入器,NgComponentOutlet 会失败并显示错误 No provider for NgModuleRef!

通过 NgComponentOutlet 进行一些跟踪后,这似乎是因为 NgModuleFactory 依赖于渲染器等来创建组件。但是,我一直无法找到一个 API 来公开一个最小的依赖注入器,类似于提供给根模块的那个。有没有办法获得这个注入器,或者创建一个最小的依赖注入器,它仍然包含渲染动态编译组件所需的资源?

【问题讨论】:

  • 显示您的相关代码,_ 加载一个外部模块并使用 NgComponentOutlet 将其添加到 DOM 中。_ - 您的意思是从中添加组件吗?你不能将模块添加到ngComponentOutlet
  • 相反,外部模块是使用编译器的注入实例编译的。编译后的模块被提供给 ngComponentOutlet,它从中构造其组件之一。 <ng-container *ngComponentOutlet="component; ngModuleFactory: moduleFactory; injector: injector"></ng-container>
  • 有趣,我不使用*ngComponentOutlet,所以不知道他们引入了该功能。根注入器包含许多应用程序范围的提供程序,例如ApplicationRefErrorHandlerrendererFactory 等,因此您无法完全避免它 - 否则您的任何组件都无法访问它们。为什么你希望你的组件不能访问父注入器提供者?
  • 这对程序的运行并不重要,但我想尽可能保持隔离。由于子模块对父应用程序知之甚少,我想为它提供一个关于依赖注入的完全干净的状态。由于期望父母和孩子都使用注入令牌,因此肯定有可能发生冲突。我希望有某种方法可以获取一个包含所有全局提供程序的注入器,而不是应用程序模块引入的任何提供程序,类似于根模块本身。
  • 知道了,请参阅my answer。如果有不清楚的地方请告诉我。

标签: angular dependency-injection


【解决方案1】:

不可能限制对应用程序注入器的访问,因为它包含应用程序范围的全局提供程序,如 ApplicationRefErrorHandlerrendererFactory 等。此外,不可能只使用这些提供程序获取注入器,因为所有模块提供程序被合并。阅读更多in this answer

但是,可以限制对父组件定义的提供程序的访问。 Angular 为组件使用不同类型的注入器 - 见this answer。为此,您需要将应用程序注入器而不是您通过依赖注入器获得的注入器传递到模块工厂到组件构造函数中。我现在知道获取此应用程序注入器的唯一方法是这样的:

platform.bootstrapModule(AppModule).then((module) => {
  window['rootInjector'] = module.injector;
});

还有一个平台注入器,您可以轻松获得,但它对我们的目的毫无用处。阅读更多in this answer。所以假设您已经获得了应用程序注入器,您可以将其传递给模块工厂:

System.import('app/b.module').then((module) => {
  const appInjector = window['rootInjector'];
  const moduleFactory_ = c.compileModuleSync(module.BModule);
  const moduleRef = moduleFactory_.create(appInjector);

或者你使用ngComponentOutlet的方式。

另一种可能的方法是获取应用程序范围的依赖项并在自定义注入器中重新映射它们:

const applicationRef = i.get(ApplicationRef);
const errorHandler = i.get(ErrorHandler);
...

const customInjector = ReflectiveInjector.resolveAndCreate([
   {provide: ApplicationRef, useValue: applicationRef},
   {provide: ErrorHandler, useValue: errorHandler}
   ...
]);

但它很有可能在未来某个时候失败。

【讨论】:

    猜你喜欢
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2016-07-19
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    相关资源
    最近更新 更多