Angular 实施遗传解析器

Angular implementing a genetic resolver

一段时间以来,我一直在尝试在我的应用程序中实施遗传解析器。我的第一个基于直觉的实现给了我这个 SO 问题的确切结果:,这当然也给了我确切的错误。

我尝试使用例外答案(使用InjectionToken)解决它但无法使其工作,也许我对InjectionToken的使用不够熟练,我当前的代码:

GenericResolverService

`export interface GetItem<T> {
  getItem(id: number): Observable<T>;
 }

@Injectable()
export class GenericResolverService<T, U extends GetItem<T>> 
  implements Resolve<T> {

constructor(private dataService: U,
            private router: Router) {

}

resolve(route: ActivatedRouteSnapshot, 
      stata: RouterStateSnapshot):
  Observable<T> | Observable<never> {
  const itemId = +route.paramMap.get('id');

  return this.dataService.getItem(itemId).pipe(
    take(1),
    mergeMap(item => {
        if (item) {
            return of(item);
        } else {
            this.router.navigate(['/error/not-found']);
            return EMPTY;
        }
    })
  );
}
}`

路由器模块

const ITEM_RESOLVER = 
    new InjectionToken<GenericResolverService<ItemMasterData,   ItemMasterDataService>>
    ('itemResolver');

const routes: Routes = [
{ 
    path: ':id', component: ItemMasterDataEditComponent,
    resolve: {
        item: ITEM_RESOLVER
    } 
}
];

 @NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: [{ provide: ITEM_RESOLVER, useClass: GenericResolverService}]
})
export class ItemMasterDataRoutingModule { }   

ItemMasterDataService

@Injectable()
export class ItemMasterDataService implements GetItem<ItemMasterData> {

  public getItem(id: number): Observable<ItemMasterData> {

  ...
}

当前代码抛出错误:

Error: Can't resolve all parameters for GenericResolverService: (?, [object Object]).

我做错了什么?

Angular 要求 DI 令牌在运行时可用,但您使用的通用类型将从生成的 JavaScript.

中消失

如果您仔细阅读所链接问题的答案,您会注意到基本泛型 class 根本没有提供,而是派生的 class:

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

在其构造函数中包含特定标记:

export abstract class DetailResolver<T, R extends Repository<T>> implements Resolve<T> {
   constructor(protected repositoryService: R, protected router: Router) {}
}

@Injectable()
export class MessageResolver extends DetailResolver<Message, MessageService> {
   constructor(repositoryService: MessageService, router: Router) {
                                  ^^^^^^^^^^^^^^
                                  available at runtim
     super(repositoryService, router);
   }
}

在您的示例中,您仍在尝试向 class 提供通用构造函数参数,但 Angular 不知道要实例化哪个 class。

因此您可以像上面的示例一样创建派生 class 或利用 DI(useFactory) 的替代配方:

{
  provide: ITEM_RESOLVER,
  useFactory: (service, router) => new GenericResolverService(service, router),
  deps: [ItemMasterDataService, Router]
}

此外,您可以使用您的通用 class 作为标记:

const routes: Routes = [
  { 
    path: ':id', component: ItemMasterDataEditComponent,
    resolve: {
        item: GenericResolverService
    } 
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
  providers: [
     ItemMasterDataService,
     {
       provide: GenericResolverService,
       useFactory: (service, router) => new GenericResolverService(service, router),
       deps: [ItemMasterDataService, Router]
     }
  ]
})
export class ItemMasterDataRoutingModule { }  

另一种选择是为您的 dataService

使用真实代币
constructor(protected dataService: SomeBaseDateServiceClass) {}

并在应用程序的不同级别提供不同的实现:

{ provide: SomeBaseDateServiceClass, useClass: ItemMasterDataService }