2017-08-16 73 views
0

我遵循文档如何使用InjectionToken通过接口注入。我刚刚创建了一个小项目 -角度4 DI通过接口

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/

+0

我会期待它的工作。如果MY_SERVICE未在模块提供程序中注册,则会发生该错误。上面的代码被截断,并不确定它是什么。无论如何,当抽象类同时用作接口和令牌时,它会更好。 – estus

+0

可能重复的[导出类作为Angular2中的接口](https://stackoverflow.com/questions/43572149/export-class-as-interface-in-angular2) – estus

+0

@estus我不认为它是重复的,因为我想使用确切的接口,而不是抽象类。你的意思是什么> MY_SERVICE没有在模块提供商注册?我认为我已经做到了 –

回答

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

这通常荣获”对于真实应用程序而言,它们的提供者和地点位于不同的模块文件中。