簡體   English   中英

從角度8的模塊中獲取進樣器

[英]Get injector from module in angular 8

問題:

我正在為angular的非路由模塊設置延遲加載。 在版本7中,我使用了NgModuleFactoryLoader並將其功能load到延遲加載模塊並獲取該模塊的第一個入口點(服務在外情況下)

this.loader.load('path-to-module')
  .then(factory => {
    const module = factory.create(this._injector);
    return module.injector.get(EntryService);
  });

但是在Angular 8中, NgModuleFactoryLoader被棄用了,所以我不得不以這種方式加載模塊:

import('path-to-module')
  .then(m => m.MyModule)
  .then(myModule => {
    ...
});

這里的問題是我無法在新的延遲加載中檢索工廠並在此處獲取提供者(IVY的想法之一-沒有工廠)。

我已經嘗試過的:

第一個解決方案(僅適用於不適合我們的JIT編譯器,因為我將AOT編譯器用於產品)

import('path-to-module')
  .then(m => m.MyModule)
  .then(myModule => {
    return this._compiler.compileModuleAsync(myModule)
      .then(factory => {
        const module = factory.create(this._injector);
        return module.injector.get(EntryService);
      });
});

第二種解決方案(臟且未完全檢查。它使用的是ngInjectorDef ,這是IVY的新功能,尚無任何描述的API):

import('path-to-module')
  .then(m => m.MyModule)
  .then(myModule => {
    const providers = myModule['ngInjectorDef'].providers; // Array<Providers>
    ... find EntryService in providers
});

ngInjectorDef是一個靜態模塊類屬性,該屬性是由angular添加的,並且具有工廠,提供者和進口的屬性。

資料來源:

我不會說訪問ngInjectorDef屬性是“骯臟的黑客”。 是的,它沒有在任何地方進行文檔記錄,因為正如Igor Minar所說,Ivy是Angular 8的選擇性加入預覽。但是Viktor Savkin的某些文章中已經提到了很多私有函數,例如directiveInject

您不應在providers屬性中搜索服務。 想象一下,有20多個提供者, EntryService名稱在生產中將EntryService tk

如果使用Ivy-有一個名為createInjector的私有函數,該函數接受模塊構造函數作為參數。

@Injectable()
export class EntryService {
  public logFromEntryService(): void {
    console.log('Logging from EntryService...');
  }
}

@NgModule({
  providers: [EntryService]
})
export class EntryModule {
  public static getEntryService: () => EntryService = null;

  constructor(injector: Injector) {
    EntryModule.getEntryService = () => injector.get(EntryService);
  }
}

假設您有這樣的代碼,讓我們使用動態導入來加載此EntryModule

import { ɵcreateInjector as createInjector } from '@angular/core';

export class AppComponent {
  constructor(private injector: Injector) {
    this.loadEntryModule();
  }

  private async loadEntryModule(): Promise<void> {
    const { EntryModule } = await import('./entry.module');
    createInjector(EntryModule, this.injector);
    EntryModule.getEntryService().logFromEntryService();
  }
}

createInjector用於實例化EntryModule ,instanting之后-該getEntryService靜態方法並不等於null

我們還可以公開injector屬性,例如:

public static injector: Injector = null;

constructor(injector: Injector) {
  EntryModule.injector = injector;
}

可以將其視為服務定位器,這是一種反模式。 但是取決於你!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM