【问题标题】:Angular implementing a genetic resolverAngular实现遗传解析器
【发布时间】:2019-10-25 17:07:20
【问题描述】:

一段时间以来,我一直在尝试在我的应用中实现基因解析器。根据我的直觉,我的第一个实现给了我这个 SO 问题的确切结果:How to provide a service that uses generics in Angular4?,这当然也给了我确切的错误。

我尝试使用例外答案(使用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> {

  ...
}

当前代码抛出错误:

错误:无法解析 GenericResolverService 的所有参数:(?, [对象对象])。

我做错了什么?

【问题讨论】:

    标签: angular generics angular-resolver


    【解决方案1】:

    Angular 要求 DI 令牌在运行时可用,但您使用的泛型类型会从生成的 JavaScript 中消失。

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

    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);
       }
    }
    

    在您的示例中,您仍在尝试为类提供泛型构造函数参数,但 Angular 不知道要实例化哪个类。

    因此,您可以像上面的示例一样创建派生类,也可以利用 DI(useFactory) 的替代方案:

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

    此外,您可以将泛型类用作标记:

    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 }
    

    【讨论】:

      猜你喜欢
      • 2010-10-31
      • 2020-08-04
      • 2014-10-02
      • 1970-01-01
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多