首页 > 解决方案 > 导入模块的顺序将注入的抽象覆盖到模块中

问题描述

我有一个TableComponent需要抽象服务来执行一些异步调用。该模块如下所示:

@NgModule({
    imports: [
        CommonModule,
    ],
    declarations: [
        TableComponent
    ],
    exports: [
        TableComponent
    ]
})
export class TableModule {

    static forRoot(tableService: Type<TableService>): ModuleWithProviders {
        return {
            ngModule: TableModule,
            providers: [
                { provide: TableService, useClass: tableService }
            ]
        };
    }
}

我必须进一步模块:EmployeeModule 和 LocalizationModule。它看起来:

@NgModule({
    imports: [
        CommonModule,
        TableModule.forRoot(EmployeeTableService), <---- Injected EmployeeTableService
    ],
    declarations: [
        EmployeeComponent,
        ModalEmployeeComponent
    ],
    providers: [
        EmployeeResource,
        EmployeeRepository,
        EmployeeTableService
    ]
})
export class EmployeeModule {
}

@NgModule({
    imports: [
        CommonModule,
        TableModule.forRoot(LocalizationTableService),
    ],
    declarations: [
        LocalizationComponent
    ],
    providers: [
        LocalizationResource,
        LocalizationRepository,
        LocalizationTableService
    ],
})
export class LocalizationModule {
}

现在我按顺序将这两个模块导入 AppModule . 所以它看起来像:

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        HttpClientModule,
        AppRoutes,
        LocalizationModule,
        EmployeeModule
    ],
    providers: [
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

这里的问题是订单。取决于哪个模块(员工或本地化)是服务注入的最后一个TableComponent,它将抽象作为构造函数的参数。IE。如果订单像上面那样只EmployeeTableService被注入。否则LocalizationTableService被注入 - 为什么以及如何更改它,以便TableComponent始终采用正确的抽象?

TableComponent看起来像:

@Component({
    selector: 'sp-table[configuration]',
    templateUrl: './TableComponent.html',
    styleUrls: ['./TableComponent.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class TableComponent implements OnInit {

    constructor(
        public readonly dialog: MatDialog,
        private readonly tableService: TableService,
        private readonly changeDetectorRef: ChangeDetectorRef
    ) {
        super();
    }

员工表服务示例:

@Injectable()
export class EmployeeTableService extends TableService {
    constructor(
        private readonly employeeResource: EmployeeResource
    ) {
        super();
    }

}

标签: angulardependency-injectionabstract-classabstract

解决方案


如果我理解正确,这里是stackblitz


在这种情况下,一个提供者覆盖另一个提供者的原因是您定义它们的方式。当您通过providers模块数组定义提供者时,它将在根注入器中注册。所以我知道的唯一一个解决方案是TableService每次你要使用它时都在组件级别上覆盖它。您也可以为根注入器定义默认提供程序,以供您直接使用。TableServiceTableService


推荐阅读