Website-Suche

angular - Abhängigkeitsinjektion in abstrakte Klasse Typescript (Angular2)


Ich habe eine abstrakte Klasse (ohne Konstruktor) und ich möchte eine andere Klasse in sie injizieren.

Abstrakte Klasse:

import { ErrorHandler } from '../../shared/services/errorHandler.service';
import { Inject } from '@angular/core';


export abstract class BaseApiComponent<T> {
    @Inject(ErrorHandler) errorHandler: ErrorHandler;

    this.errorHandler.test();
}

Injizierte Klasse:

import { Injectable } from '@angular/core';

@Injectable()
export class ErrorHandler  {
  constructor() { }


  public test() {
    console.log('Test');
  }

}

Und ich habe den nächsten Fehler

ORIGINAL EXCEPTION: TypeError: Cannot read property 'test' of undefined

Wie kann ich das reparieren?

Antwort #1

Ab Angular 2 RC5 wird die DI einfacher. Sie müssen die Dinge nicht mit @Injectable() dekorieren. Stattdessen deklarieren Sie sie einfach an einer Stelle für DI - NgModule.

export class ErrorHandler {
    test() {
        console.log('ErrorHandler.test()');
    }
}

export abstract class BaseApiComponent<T> {
    // use protected property parameter in abstract class
    // for accessibility from descendants.
    constructor(protected errorHandler: ErrorHandler) {}

    someMethod() {
        this.errorHandler.test();
    }
}

export class ApiComponentImpl<T> extends BaseApiComponent<T> {
    // use @Inject decorator
    constructor(@Inject(ErrorHandler) errorHandler: ErrorHandler) {
        super(errorHandler);
    }
}

app.module.ts:

// class declarations
@NgModule({
    providers: [
        ErrorHandler,
        ApiComponentImpl
    ]
})
export class AppModule{
}

// bootstrap the app
platformBrowserDynamic().bootstrapModule(AppModule);

Sie können OpaqueToken verwenden, um die Modularität zu verbessern und die Typabhängigkeit zu entfernen:

export const errorHandlerToken = new OpaqueToken('ErrorHandler');

im Modul:

    providers: [
        // using OpaqueTokens you can change the provided value
        // to anything without changing consumer code 
        {provide: errorHandlerToken, useClass: ErrorHandler},

Konstruktor:

    constructor(@Inject(errorHandlerToken) errorHandler: ErrorHandler) {

Antwort #2

Angular DI unterstützt nur Konstruktorinjektion, was bedeutet, dass Sie einen Konstruktor benötigen.

Man kann auch nicht direkt in eine abstrakte Klasse injizieren, weil eine abstrakte Klasse nicht instanziierbar sein soll.

Daher muss es so sein:

export abstract class BaseApiComponent<T> {
    constructor(errorHandler: ErrorHandler) {}

    someMethod() {
     this.errorHandler.test();
    }
}

export class ApiComponentImpl<T> {
    constructor(errorHandler: ErrorHandler) {
      super(errorHandler);
    }

}

Verwandte Artikel