Angular 14动态添加组件:自定义注入器获取ServiceC报空注入器错误求助
问题原因与解决方案
错误原因
你创建的自定义Injector没有指定父注入器,导致它无法从Angular的全局注入器树中获取ServiceC的实例,因此抛出NullInjectorError。Angular注入器是分层结构,自定义注入器默认是孤立的,不会自动继承上层注入器的依赖。
另外代码里还有一处小错误:new AbstractServiceImpA(ServiceC)传入的是类本身,不是注入的实例,应该改成new AbstractServiceImpA(serviceC)。
修正后的代码
方法1:传入父注入器(推荐)
修改makeCustomInjector方法,接收当前组件的注入器作为父注入器,让自定义注入器能继承上层的依赖:
makeCustomInjector(param: string, parentInjector: Injector) { return Injector.create({ providers: [ { provide: AbstractService, useFactory: (serviceC: ServiceC): AbstractService => { if (param === 'some_value') { return new AbstractServiceImpA(serviceC); // 传入实例而非类 } else { return new AbstractServiceImpB(serviceC); } }, deps: [ServiceC] } ], parent: parentInjector // 指定父注入器 }); }
调用时传入当前组件的注入器(通过构造函数注入Injector):
constructor(private injector: Injector) {} // 动态创建组件时 const customInjector = this.makeCustomInjector('param_value', this.injector); const componentRef = this.container.createComponent(DynamicallyAddedComponent, { injector: customInjector, environmentInjector });
方法2:直接在自定义注入器中提供ServiceC
如果ServiceC是可直接实例化的类,也可以在自定义注入器的providers里添加它的提供者,但这种方式会创建新的实例,不如继承父注入器的实例高效:
makeCustomInjector(param: string) { return Injector.create({ providers: [ ServiceC, // 添加ServiceC的提供者 { provide: AbstractService, useFactory: (serviceC: ServiceC): AbstractService => { if (param === 'some_value') { return new AbstractServiceImpA(serviceC); } else { return new AbstractServiceImpB(serviceC); } }, deps: [ServiceC] } ] }); }
更优实现方案
如果需要频繁根据参数切换抽象服务的实现,可以用工厂服务封装逻辑,避免每次创建组件都手动构建注入器:
- 创建工厂服务,负责根据参数返回对应的AbstractService实现:
@Injectable({ providedIn: 'root' }) export class AbstractServiceFactory { constructor(private serviceC: ServiceC) {} createService(param: string): AbstractService { if (param === 'some_value') { return new AbstractServiceImpA(this.serviceC); } else { return new AbstractServiceImpB(this.serviceC); } } }
- 动态创建组件时,直接通过工厂获取实例,再用注入器提供:
constructor(private factory: AbstractServiceFactory, private injector: Injector) {} // 动态创建组件 const serviceInstance = this.factory.createService('param_value'); const customInjector = Injector.create({ providers: [{ provide: AbstractService, useValue: serviceInstance }], parent: this.injector }); const componentRef = this.container.createComponent(DynamicallyAddedComponent, { injector: customInjector, environmentInjector });
这种方式逻辑更清晰,也便于后续扩展更多服务实现。
内容的提问来源于stack exchange,提问作者user814425
相关产品推荐
相关产品推荐

