Инъекция зависимостей в абстрактный класс 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);
}
}