0

由于孩子的知识,我试图将提供者延迟加载到父母中。想象一下:

@Injectable()
export class ServiceA {
    constructor(
        @Inject(MY_TOKEN)
        private serviceB: ServiceBImpl
    ) { }

    run() {
        this.serviceB.b();
    }
}

ServiceBImpl只是一个接口

export let MY_TOKEN = new InjectionToken<ServiceBImpl>('MY_TOKEN');

export interface ServiceBImpl {
    b();
}

ServiceA加载到根目录AppModule

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    ServiceA
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

MY_TOKEN加载在子注射器中。但是,我不要求MY_TOKEN在这个组件中,我要求ServiceA.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [
    { provide: MY_TOKEN, useClass: ServiceB }
  ]
})
export class AppComponent {
  title = 'app';

  constructor(
    public serviceA: ServiceA
  ) {
    // Does not work
    this.serviceA.run();
  }
}

这不起作用。

让我明确一点,我不想ServiceA在组件级别的提供程序中拥有它,而是从AppModule.

这是一个测试: https ://stackblitz.com/edit/angular-u8tbwx

4

1 回答 1

0

您尝试完成的挑战是ServiceA根注入器提供的,它出于所有意图和目的创建了一个单例。因此,在ServiceA构建时,它只需要与该注入器中可用的任何东西一起工作——如果没有MY_TOKEN提供,那么它就会中断。

我建议建立ServiceA更多的工厂,为您提供所需的灵活性。从您的 Stackblitz 示例中获取 whereServiceA取决于ServiceAAwhich 取决于ServiceB

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  providers: [
    { provide: MY_TOKEN, useClass: ServiceB }
  ]
})
export class AppComponent  {
  serviceAA: ServiceAA;

  constructor(
    private serviceA: ServiceA,
    @Inject(MY_TOKEN) private serviceB: ServiceBImpl
  ) {
    this.serviceAA = serviceA.createServiceAAWithB(serviceB);
  } 
}

createServiceAAWithB从字面上看new ServiceAA(serviceb)。这种模式可能类似于@angular/cdkOverlay 服务在他们的方法中生成覆盖实例的create方法,基本上是工厂:https://github.com/angular/material2/blob/7.0.0/src/cdk/overlay/overlay。 ts#L66

于 2018-10-21T19:21:46.547 回答