Инъекция зависимостей в абстрактный класс typescript (Angular2)

у меня есть абстрактный класс (без конструктора), и я хочу ввести в него другой класс.

абстрактный класс:

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


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

    this.errorHandler.test();
}

класса вводят:

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

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


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

}

и у меня следующая ошибка

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

как я могу это исправить?

3 ответов


с углового 2 RC5 DI становится проще. Вам не нужно украшать вещи с @Injectable(). Вместо этого вы просто объявляете его для 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.модуль.ТС:

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

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

вы можете использовать OpaqueToken для улучшения модульности и удаления зависимости типа:

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

в модуле:

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

конструктора:

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

Angular DI поддерживает только инъекцию конструктора, что означает, что вам нужен конструктор.

вы также не можете вводить в абстрактный класс напрямую, потому что абстрактный класс не должен быть инстанцируемым.

надо так:
export abstract class BaseApiComponent<T> {
    constructor(errorHandler: ErrorHandler) {}

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

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

}

Я не угловой разработчик, но глядя на примеры @Inject декоратор всегда используется как декоратор параметр, а не собственность декоратора.

поскольку два типа декораторов разные, это может вызвать проблему, но я не уверен.
Попробуйте:

export abstract class BaseApiComponent<T> {
    private errorHandler: ErrorHandler;

    protected constructor(@Inject(ErrorHandler) handler) {
        this.errorHandler = handler;
    }

    public error() {
        this.errorHandler.test();
    }
}

также я не уверен, когда вы на самом деле используете this.errorHandler.test(); поскольку он не может просто сидеть там в классе, я переместил его в error метод.


редактировать

право. Вам нужно будет ввести в расширяющийся класс, а затем передать экземпляр родительскому:

export abstract class BaseApiComponent<T> {
    protected errorHandler: ErrorHandler;

    protected constructor(handler: ErrorHandler) {
        this.errorHandler = handler;
    }
}

export class Restaurants extends BaseApiComponent<any> {
    constructor(@Inject(ErrorHandler) handler) {
        super(handler);
    }
}