Angular 8+,让惰性模块中的组件工厂在全局服务中可用

Angular 8+, make component factories in lazy module available in global service

我已经编写了一个 ModalService 来包装 MatDialog 和 MatSnackBar,以避免在我的每个组件中注入这两者,并且该服务提供了包装 material 的方法。所以你可以写

modalService.dialog(MyDialogComponent, { data: {} });

而不是

matDialog.open(MyDialogComponent, { data: {} });

ModalService 在 ModalModule 中声明,并在其 forRoot 方法中提供,因此在我的 AppModule 中导入它:

ModalModule.ts:

@NgModule({ imports: [MatDialogModule, ...], ... })
public class ModalModule {
    static forRoot() {
        return { ngModule: ModalModule, providers: [{ provide: ModalService, useClass: ModalService }] };
    }
}

AppModule.ts:

@NgModule({ imports: [ModalModule.forRoot(), ...], ... })
public class AppModule {}

我还有其他模块,其中一些是延迟加载的,它们导入 ModalModule 并声明一些入口组件以在对话框中打开: LazyModule.ts

@NgModule({
    imports: [MatDialogModule, ModalModule, ...], // <--- ModalModule without forRoot()
    declarations: [MyDialogComponent, MyLazyComponent],
    entryComponents: [MyDialogComponent],
})
public class LazyModule {}

现在,如果我在 MyLazyComponent 中尝试使用 ModalService 打开 MyDialogComponent,我会收到一条错误消息,指出没有找到 MyDialogComponent 的工厂,而在使用 dialog.open 时,它会按预期工作。

MyLazyComponent:

modalService.dialog(MyDialogComponent); // <--- error
matDialog.open(MyDialogComponent); // <--- fine

在使用开发工具进行调试时,我注意到在 MatDialog 代码的某处,matDialog 引用了 LazyModule 的注入器,它有一个正确包含 MyDialogComponent 工厂的 ComponentFactoryResolver,而 ModalService 引用了AppModule 的注入器,不包含那些工厂。 我明白其中的原因:我在 AppModule 而不是在 LazyModule 中提供了服务。我没有得到的是如何解决这个问题,或者为什么 MatDialog 引用了 LazyModule 的注入器。

正如我的问题的评论中所述,MatDialogModule 的装饰器中提供了 MatDialog,因此对于每个惰性模块,都会创建一个新的 MatDialog 实例,并对该模块的组件具有可见性。毕竟,对话服务不需要是单例的,这种方法很好,所以我最终也在模块的元数据中提供了我的模态服务,而不仅仅是在 forRoot 方法中。