You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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]
      }
    ]
  });
}

更优实现方案

如果需要频繁根据参数切换抽象服务的实现,可以用工厂服务封装逻辑,避免每次创建组件都手动构建注入器:

  1. 创建工厂服务,负责根据参数返回对应的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);
    }
  }
}
  1. 动态创建组件时,直接通过工厂获取实例,再用注入器提供:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:30:28