我有抽象类(没有构造函数),我想向其中注入另一个类。
抽象类:
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
我该如何解决这个问题?
从 Angular 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.module.ts:
// 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);
}
}
您可以将所需的服务声明为目标抽象类的私有或受保护成员,然后在其构造函数中使用 inject 函数:
import { inject } from '@angular/core';
export abstract class BaseApiComponent<T> {
protected errorHandler: ErrorHandler;
constructor() {
this.errorHandler = inject(ErrorHandler);
}
testService() {
this.errorHandler.test();
}
}
您可以在这个抽象类的实现中使用它:
@Component({...})
export class MyComponentImplementation extends BaseApiComponent<T> {
override testService() {
super.testService();
this.errorHandler.test();
}
}
此解决方案是一种将依赖项注入抽象类而不触及其实现的方法。