2017-08-16 4 views
0

Ich folgte Dokumentation, wie InjectionToken für die Injektion über Schnittstellen zu verwenden. Ich habe nur ein kleines Projekt -Angular 4 DI durch Schnittstellen

export interface MyInterface { 
    sayHello(); 
} 

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

Mein app.module

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

Hier ist 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) { 
    } 
} 

Und das ist ein Fehler, den ich in Chrome Werkzeuge bekam

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 (

Hier ist Plunkr - https://embed.plnkr.co/qQP5BhNzgu2F4FYclG1e/

+0

Ich würde erwarten, dass es funktioniert. Der Fehler tritt auf, wenn MY_SERVICE nicht in Modulanbietern registriert wurde. Der Code oben ist abgeschnitten und es ist nicht sicher, dass es war. In jedem Fall funktioniert es besser, wenn die abstrakte Klasse sowohl als Schnittstelle als auch als Token verwendet wird. – estus

+0

Mögliches Duplikat von [Export Klasse als Schnittstelle in Angular2] (https://stackoverflow.com/questions/43572149/export-class-as-interface-in-angular2) – estus

+0

@estus Ich glaube nicht, dass es doppelt ist, weil Ich möchte eine exakte Schnittstelle verwenden, keine abstrakte Klasse. Was meinst du mit> MY_SERVICE war bei Modulanbietern nicht registriert? Ich denke, ich habe es schon getan –

Antwort

1

Das Problem in original code ist, dass MY_SERVICE Injektionstoken tatsächlich definiert ist, nachdem es für die Injektion verwendet wird.

Um dies zu vermeiden, sollte es vor, dass definiert werden:

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

Alternativ könnten forwardRef Helfer verwendet werden, speziell Rennbedingungen wie das vermeiden:

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

Diese in der Regel gewonnen‘ t ein Problem für eine reale Anwendung sein, in der sich Anbieter und Orte, an denen sie verwendet werden, in verschiedenen Moduldateien befinden.