【问题标题】:Angular 4 DI through interfacesAngular 4 DI 通过接口
【发布时间】:2018-01-25 03:17:09
【问题描述】:

我遵循文档如何使用 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 未捕获的错误:无法解析 AppComponent 的所有参数:(?)。 在 syntaxError (compiler.es5.js:1690) 在 CompileMetadataResolver.webpackJsonp.../../../compiler/@angular/compiler.es5.js.CompileMetadataResolver._getDependenciesMetadata (compiler.es5.js:15765) 在 CompileMetadataResolver.webpackJsonp.../../../compiler/@angular/compiler.es5.js.CompileMetadataResolver._getTypeMetadata (

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

【问题讨论】:

  • 我希望它能够工作。如果 MY_SERVICE 未在模块提供程序中注册,则会发生错误。上面的代码被截断了,不确定它是否被截断。无论如何,抽象类同时用作接口和令牌时效果更好。
  • @estus 我不认为它是重复的,因为我想使用精确的接口,而不是抽象类。 > MY_SERVICE 未在模块提供程序中注册是什么意思?我想我已经做到了
  • 我认为它是重复的,因为您尝试做的事情自然是通过抽象类实现的,实际上不需要 MY_SERVICE 注入令牌。在上面的代码中MyInterface 应该没有什么不同,你可以用同样的结果做@Inject(MY_SERVICE) private myService : any。所以未注册的 MY_SERVICE 是主要嫌疑人。考虑提供可以复制问题的stackoverflow.com/help/mcve
  • @estus 谢谢。但是我提供了足够的信息。请查看我的问题并找出 - “我的 app.module” 部分。我提供了 MY_SERVICE 的注册部分。作为更新,如果我这样做,我会获得类型支持 - @Inject(MY_SERVICE) private myService : any 吗?我不这么认为

标签: angular dependency-injection code-injection


【解决方案1】:

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');

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

【讨论】:

    猜你喜欢
    • 2011-02-20
    • 2018-12-27
    • 1970-01-01
    • 2017-12-20
    • 2017-12-08
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    • 1970-01-01
    相关资源
    最近更新 更多