2017-10-12 148 views
4

我注意到我的項目有很多resolver儘管與不同的實體和存儲庫一起工作的服務託管了相同的代碼。所以我接受了挑戰,以減少他們使用泛型單解析服務:如何提供在Angular4中使用泛型的服務?

@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>指定泛型類型的編譯器要我創建一個實例:typeof運算DetailResolver是不可呼叫類型的

價值。你是否想要 包括新的?

我對angular4 DI內部並不是很熟悉。任何人都可以描述什麼是錯的,有沒有解決這個問題的方法?我正在使用角度4.3。

回答

4

當您使用注入器註冊提供者時,DI系統會使用該令牌或其他方式看作密鑰 - 用於維護每次需要依賴項時引用的令牌提供者映射。

令牌通常是唯一且具有象徵意義的對象,因此泛型的概念在此區域中直接衝突的原因正是因爲該令牌將用作密鑰。泛型是設計時的工件,這是另一種說法,它們將從生成的JavaScript中消失,因此不會在運行時留下它們的類型信息以供Angular查找。出於同樣的原因,TypeScript接口也不是有效令牌。

抽象類

我的第一選擇是使用abstract classes。抽象類在這裏解決兩個問題: 1)雖然它們不能直接實例化,但與接口不同,它們可以包含實現細節,因此可以編譯爲Javascript。 2)通過基於擴展的體系結構獲得DI令牌,這可能對您的體系結構非常有用。

你的情況,你可以做類似如下:

@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 }] 

InjectionToken

另一種選擇是使用InjectionToken(在Angula之前稱爲OpaqueToken) 4.0)。 InjectionToken s是專門用作DI令牌的對象;然而不像它們的前身OpaqueToken,它們需要鍵入他們將注入的值的類型。

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

你會發現,你可以爲你所創建的InjectionToken實例有編譯器支持你前進的道路上提供的類型。當您在NgModule中添加提供程序時,這會強制執行。

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

值得注意的是useClass在技術上並不是必需的;在提供相應的任何其他備選方案時,如useValueuseFactory在此處均有效。

希望這是有幫助的,並就此事提供一些澄清!

相關問題