gpt4 book ai didi

angular - 如何在 Angular4 中提供使用泛型的服务?

转载 作者:太空狗 更新时间:2023-10-29 17:25:02 25 4
gpt4 key购买 nike

我注意到我的项目有很多 resolver 尽管与不同的实体和存储库一起工作但托管相同代码的服务。所以我接受了使用泛型将它们减少为单个解析器服务的挑战:

@Injectable()
export class DetailResolver<T, R extends Repository<T>> implements Resolve<T> {

constructor(private repositoryService: R, private router: Router) {}

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> {
// use repositoryService to resolve this route
}
}

可以指定实体类型 T 和存储库类型 R。但是我在使用这项服务时遇到了问题:

const appRoutes: Routes = [
// other routes
{
path: ':id',
component: MessageEditComponent,
resolve: {
message: DetailResolver<Message, MessageService>
}
}
];

@NgModule({
imports: [
RouterModule.forChild(appRoutes)
],
exports: [
RouterModule
],
providers: [
DetailResolver<Message, MessageService>
]
})

只要我在 DetailResolver<Message, MessageService> 中指定泛型类型编译器要我创建一个实例:

Value of type typeof DetailResolver is not callable. Did you mean to include new?

我不太熟悉 angular4 DI 的内部结构。谁能描述出什么问题了,这个问题有什么解决办法吗?我正在使用 Angular 4.3。

最佳答案

当您使用注入(inject)器注册提供者时,DI 系统使用该 token ——或者可以被视为的东西——来维护一个 token 提供者映射,每次注入(inject)时都会引用该映射要求依赖。

token 通常是唯一的和符号化的对象,因此泛型的概念在这方面直接冲突,正是因为 token 将充当 key 。泛型是一种设计时产物,换句话说,它们将从生成的 JavaScript 中消失,因此不会留下它们的类型信息供 Angular 在运行时查找。出于同样的原因,TypeScript 接口(interface)也不是有效的标记。

抽象类

我的第一个选择是使用 abstract classes .抽象类在这里解决了两个问题:1) 虽然它们不能直接实例化,但与接口(interface)不同,它们可以包含实现细节,因此可以编译成 Javascript。2) 您通过基于扩展的架构获得 DI token ,这可能非常适合您的架构。

在您的情况下,您可以执行以下操作:

@Injectable()
export abstract class DetailResolver<T, R extends Repository<T>> implements Resolve<T> {...}

@Injectable()
export class MessageResolver extends DetailResolver<Message, MessageService> {...}

然后在 NgModule 中,您将按以下方式提供它:

providers: [{ provide: DetailResolver, useClass: MessageResolver }]

注入(inject) token

另一种选择是使用 InjectionToken (在 Angular 4.0 之前称为 OpaqueToken)。 InjectionToken 是专门用作 DI token 的对象;然而,与它们的前身 OpaqueToken 不同的是,它们需要输入它们将注入(inject)的值的类型。

const MESSAGE_RESOLVER = new InjectionToken<DetailResolver<Message, MessageService>>('MESSAGE_RESOLVER');

您会注意到,您可以在创建 InjectionToken 实例时提供类型,以使编译器一路支持您。当你在你的 NgModule 中添加提供者时,这是强制执行的。

providers: [{ provide: MESSAGE_RESOLVER, useClass: MessageResolver }]

值得注意的是,useClass 在技术上不是必需的;提供相应的任何其他替代方案,如 useValueuseFactory 在这里都是有效的。

希望这对您有所帮助,并能就此事提供一些澄清!

关于angular - 如何在 Angular4 中提供使用泛型的服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46705532/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com