我有以下构造函数:
constructor(env: Env, private logger: Logger,
@Inject(MockEndpoints.TOKEN) @Optional()
private endpoints: MockEndpoints[]) {
// ...
}
它与jit编译器一起工作。
但如果启用了aot编译器,则会产生生成错误:
ERROR in : Can't resolve all parameters for MockBackendInterceptor in /path/mock-backend.interceptor.ts: ([object Object], [object Object], ?).
令牌对象定义如下:
export interface MockEndpoints {
handle(req: HttpRequest<any>): HttpResponse<any>;
}
export namespace MockEndpoints {
export const TOKEN: InjectionToken<MockEndpoints[]> =
new InjectionToken<MockEndpoints[]>('MockEndpoints');
}
我确信这完全是由医生推荐的。
有什么暗示吗?;)
编辑(作为对Gunter评论的回应):
端点在同一模块中注册:
@NgModule({
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MockBackendInterceptor, multi: true },
{ provide: MockEndpoints.TOKEN, useClass: MockBackupService, multi: true },
{ provide: MockEndpoints.TOKEN, useClass: MockConfigurationService, multi: true }
]
})
export class MockBackendModule { }
最佳答案
最后我找到了原因。
非常感谢用户yurzui
和Günter Zöchbauer
的评论,这些评论有助于发现问题。
解决方案
如果(并且仅当)令牌常量在命名空间内声明,InjectionToken
的参数化类型(例如,MockEndpoints
在这种情况下)不能是一个接口。所以把它改成一个抽象类就足够了。
export abstract class MockEndpoints {
handle(req: HttpRequest<any>): HttpResponse<any>;
}
export namespace MockEndpoints {
export const TOKEN: InjectionToken<MockEndpoints[]> =
new InjectionToken<MockEndpoints[]>('MockEndpoints');
}
从名称空间中提取令牌常量甚至更简单。
export interface MockEndpoint {
handle(req: HttpRequest<any>): HttpResponse<any>;
}
export const MOCK_ENDPOINT = new InjectionToken<MockEndpoint[]>('MockEndpoints');
请注意,名称空间名称与接口名称相同(在本例中,两个名称都
MockEndpoints
)这一事实没有任何意义。当在名称空间中声明了令牌常量时,不同的名称不适用于接口作为参数化类型。当然,它也使用纯字符串标记,而不是使用
InjectionToken
接口。此行为仅在使用AOT编译时发生。使用jit,两种情况下都没有问题。
关于angular - 具有用户定义的InjectionToken的DI在启用AOT时不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48341592/