我还是Angular的新手。当前,我在一个组件中有一个基于一个抽象类的REST服务的两种实现。就像scenario一样,唯一的区别是我在组件级别注入了服务:
@Component({
selector: 'this-is-tag',
template: htmlStr,
providers: [{ provide: RESTToken, useClass: FirstRESTService }],
...
问题是,我可以基于特定配置在运行时切换实现吗?或者,对于这个问题,我应该使用其他方法吗?
编辑:
似乎我需要使用接口,而不是抽象类。 link
答案 0 :(得分:0)
解决方案是用useFactory代替UseClass,如下例所示更改代码: 首先,创建一个具有DI逻辑决定的工厂类:
export function myFactory() {
if(myRule){
return new FirstRESTService();
}
return new SecondRESTService();
}
然后将您的组件代码更改为:
@Component({
selector: 'this-is-tag',
template: htmlStr,
providers: [{ provide: RESTToken, useFactory: myFactory}],
有时会出现这种情况,您想向工厂添加一些依赖项,因为您需要它来决定是返回serviceA还是serviceB。 为了满足这个要求,我们可以使用如下的deps属性:
export function myFactory(obj:MyDependencyClass) {
if(obj.HasMyRule){
return new FirstRESTService();
}
return new SecondRESTService();
}
另外,在您的组件中:
@Component({
selector: 'this-is-tag',
template: htmlStr,
providers: [{ provide: RESTToken, useFactory: myFactory}],
deps: [MyDependencyClass]
但不要忘记在app.module.ts中包含MyDependencyClass。
答案 1 :(得分:0)
因此,我最终使用接口而不是该解决方案的抽象类。而且,当我尝试对两个服务(例如this question)使用基类时,继承方法也会失败。
这是我在JIT和AOT编译中的可行解决方案:
@Component({
selector: 'invoice-list',
templateUrl: './invoice-list.component.html',
providers: [{ provide: RESTToken, useClass: InvoiceRESTService }],
...
组件中实际使用的服务:
@Injectable()
export class InvoiceRESTService {
public invoiceType: InvoiceType;
constructor(
private _visma: VismaRESTService,
private _fortnox: FortnoxRESTService
) {}
public get instance(): RESTServiceInterface {
if (this.invoiceType === InvoiceType.Visma) {
return this._visma;
} else if (this.invoiceType === InvoiceType.Fortnox) {
return this._fortnox;
} else {
console.log('Please set the invoice type.');
}
}
}
界面本身:
export interface RESTServiceInterface {
getExportDataFunctionURL(): string;
// So far, only for Visma
getAuthUrl?(): string;
getButtonTitlle(): string;
synchData(instanceUid: string, code?: string): Observable<Object>;
updateInvoice(payload: any): Observable<Object>;
// Loading messages
getWaitingMessage(): string;
getSuccessMessage(): string;
getErrorMessage(code: VismaErrorCode | FortnoxErrorCode | BKErrorCode): string;
}
实现接口的服务:
@Injectable({
providedIn: 'root'
})
export class FortnoxRESTService implements RESTServiceInterface {
...
...
...
}
@Injectable({
providedIn: 'root'
})
export class VismaRESTService implements RESTServiceInterface {
...
...
...
}