2015-11-28 16 views
15

Ich habe die folgende Klasse ModuleWithHttp:Wie erweitert man eine Komponente mit Abhängigkeitsinjektion in Angular 2?

@Injectable() 
export default class { 
    constructor(private fetchApi: FetchApi) {} 
} 

und ich möchte es wie folgt verwenden:

@Component({ 
    selector: 'main', 
    providers: [FetchApi] 
}) 
export default class extends ModuleWithHttp { 
    onInit() { 
    this.fetchApi.call(); 
    } 
} 

so durch eine Super-Klasse erweitern, die bereits eine Abhängigkeit ich einen Zugang haben wollen spritzt es in seinen Kindern.

habe ich versucht, viele verschiedene Möglichkeiten, auch Super-Klasse als Komponente:

@Component({ 
    providers: [FetchApi] 
}) 
export default class { 
    constructor(private fetchApi: FetchApi) {} 
} 

Aber noch, this.fetchApinull ist, auch in der Super-Klasse.

+0

Sie benötigen FetchApi in die erbenden Klasse zu injizieren, aber wenn es hilft, können Sie es von der Basisklasse, etwas zu tun zugreifen wie '( this) .fetchapi.call (...)' (Sie müssen es nicht ausdrücklich über 'super()' übergeben.) – rinogo

Antwort

23

Sie haben fetchAPI in der Superklasse zu injizieren und es auf das Kind Klasse übergeben

export default class extends ModuleWithHttp { 

    constructor(fetchApi: FetchApi) { 
    super(fetchApi); 
    } 

    onInit() { 
    this.fetchApi.call(); 
    } 
} 

Dies ist ein Merkmal, wie DI im Allgemeinen funktioniert. Die Superklasse instanziiert das Kind durch Vererbung, aber Sie müssen dem Kind die erforderlichen Parameter bereitstellen.

+0

Das ist was ich auch lese.Ich wollte DI abstrahieren, um dieses ganze Beispiel zu vermeiden, aber ich sehe, dass ich Unterklassen fast genauso importieren, injizieren und erweitern muss. – squixy

+1

Ich verstehe das nicht. Mit "Basisklasse" meinst du "abgeleitete Klasse" (normalerweise "Basisklasse" wäre das gleiche wie "Superklasse")? Wo in Ihrem Beispiel ist "fetchAPI" "übergeben"? Willst du sagen, dass, wenn ich eine neue abgeleitete Klasse konstruiere, die in der Oberklasse geforderten Injektionen gemacht werden? –

+3

_ "Dies ist ein Merkmal, wie DI im Allgemeinen funktioniert" _ im Allgemeinen in eckigen, aber nicht im Allgemeinen überall. Viele Frameworks unterstützen DI durch die Bindung von Eigenschaften. – Qwertiy

53

Wenn Sie möchten, um diesen „Kesselblech“ Code vermeiden Dienstleistungen der Klassen Kind Injektion Konstruktor nur für die Injektion in übergeordneten Klassen und dann unter Verwendung von effektiv, dass Dienste in untergeordneten Klassen durch Vererbung, können Sie dies tun:

edit: von Angular 5.0.0 ReflectiveInjector hat sich für StaticInjector veraltet, ist unten Code aktualisiert, um diese Änderung mit deps

Haben Sie einen Dienste Karte zu reflektieren,

export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = { 
    'FetchApi': { 
    provide: FetchApi, 
    deps: [] 
    } 
} 

Haben Sie einen Düsenhalter,

import {Injector} from "@angular/core"; 

export class ServiceLocator { 
    static injector: Injector; 
} 

set it up in AppModule,

@NgModule(...) 
export class AppModule { 
    constructor() { 
    ServiceLocator.injector = Injector.create(
     Object.keys(services).map(key => ({ 
     provide: services[key].provide, 
     useClass: services[key].provide, 
     deps: services[key].deps 
     })) 
    ); 
    } 
} 

den Injektor in Elternklasse verwenden,

export class ParentClass { 

    protected fetchApi: FetchApi; 

    constructor() { 
    this.fetchApi = ServiceLocator.injector.get(FetchApi); 
    .... 
    } 
} 

und Elternklasse erweitern, so dass Sie nicht tun muss den FetchApi Service injizieren.

export class ChildClass extends ParentClass { 
    constructor() { 
    super(); 
    ... 
    } 

    onInit() { 
    this.fetchApi.call(); 
    } 
} 
+0

Wie kann ich einen Dienst von Kind injizieren und es von Eltern verwenden? –

+0

Ich denke, dass Sie nicht können und es ergibt keinen Sinn für mich. Was ist dein Anwendungsfall? –

+3

Ich bin bei Petr - soweit ich weiß, sind Elternklassen überhaupt nichts in ihren Unterklassen bekannt. Das wäre wie der Charakter von Roy Scheider aus Jaws, der weiß, was mit Michael Caine in Jaws: The Revenge passiert. Und ich bestehe darauf, dass dies eine perfekte Analogie ist. – SilithCrowe

3

Vielleicht späte Antwort, aber ich hatte nur den Injektor auf der BaseComponent und in allen Unterklassen aufgelöst injizieren, so brauche ich nicht einen Service Locator zu halten.

Meine Basisklasse:

constructor(private injectorObj: Injector) { 

    this.store = <Store<AppState>>this.injectorObj.get(Store); 
    this.apiService = this.injectorObj.get(JsonApiService); 
    this.dialogService = this.injectorObj.get(DialogService); 
    this.viewContainerRef = this.injectorObj.get(ViewContainerRef); 
    this.router = this.injectorObj.get(Router); 
    this.translate = this.injectorObj.get(TranslateService); 
    this.globalConstantsService = this.injectorObj.get(GlobalConstantsService); 
    this.dialog = this.injectorObj.get(MatDialog); 
    this.activatedRoute = this.injectorObj.get(ActivatedRoute); 
} 

My Child Klassen:

constructor(private injector: Injector) { 

    super(injector); 

} 
Verwandte Themen