Angular 4 DI 通过接口

Angular 4 DI through interfaces

我遵循了如何使用 InjectionToken 通过接口进行注入的文档。我刚刚创建了一个小项目 -

export interface MyInterface {
   sayHello();
}

@Injectable()
export class MyService implements MyInterface {
  sayHello()
  {
    throw new Error("Method not implemented.");
  }
}

我的app.module

export let MY_SERVICE = new InjectionToken<MyInterface>('MY_SERVICE');
  providers: [
    {
      provide: MY_SERVICE,
      useClass : MyService
    }
],`

这里是app.component.ts

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(@Inject(MY_SERVICE) private myService : MyInterface) {
  }
}

这是我在 Chrome 工具

中遇到的错误

compiler.es5.js:1690 Uncaught Error: Can't resolve all parameters for AppComponent: (?). at syntaxError (compiler.es5.js:1690) at CompileMetadataResolver.webpackJsonp.../../../compiler/@angular/compiler.es5.js.CompileMetadataResolver._getDependenciesMetadata (compiler.es5.js:15765) at CompileMetadataResolver.webpackJsonp.../../../compiler/@angular/compiler.es5.js.CompileMetadataResolver._getTypeMetadata (

这是 plunkr - https://embed.plnkr.co/qQP5BhNzgu2F4FYclG1e/

original code中的问题是MY_SERVICE注入令牌实际上是在用于注入之后定义的。

为避免这种情况,应在此之前定义:

export let MY_SERVICE = new InjectionToken<MyInterface>('MY_SERVICE');
...
constructor(@Inject(MY_SERVICE) private myService: MyInterface) {
...

或者,可以使用 forwardRef 帮助程序,它旨在避免像这样的竞争条件:

...
constructor(@Inject(forwardRef(() => MY_SERVICE)) private myService: MyInterface) {
...
export let MY_SERVICE = new InjectionToken<MyInterface>('MY_SERVICE');

对于提供程序和使用它们的位置位于不同模块文件中的真实应用程序,这通常不会成为问题。