1

我有一个抽象类和它的实现

export abstract class IPrint {
    abstract Print(textInput: string): void;
}

export class FilePrint implements IPrint {
    Print(textInput: string): void {
        console.log("File Print");
    }
}

然后介绍Angular DI:

  providers:
    [
      { provide: IPrint, useClass: FilePrint }
    ],

我可以像下面这样使用它:

  constructor(private _print: IPrint) { }

  ngOnInit(): void {
    console.log(this._print.Print("HI"))
  }

现在我想要 IPrint 的多重实现

export class ScreenPrint implements IPrint {
    Print(textInput: string): void {
        console.log("Screen Print")
    }
}

然后介绍Angular DI:

  providers:
    [
      { provide: IPrint, useClass: FilePrint },
      { provide: IPrint, useClass: ScreenPrint }
    ],

当我想使用 IPrint 时,angular 不知道必须使用哪个实现:

constructor(private _print: IPrint) { }
4

2 回答 2

0

我有类似的问题,并通过一个接口和一个 InjectionToken 列表来解决它。这有点矫枉过正,但这提供了很大的灵活性,并且可以应用于其他问题。

在一个项目中,我们在一个共享模块和每个组件提供的多个自定义实现中设置了一个全局打印服务。并且无需在全局服务中显式注入(因此引用)所有可能的实现。

接口和第一个实现

export interface IPrint {
    Print(textInput: string): void;
}

export class FilePrint implements IPrint {
    Print(textInput: string): void {
        console.log("File Print");
    }
}

使用 InjectionToken 创建服务实现列表

 // Keep list of token, provider will give a implementation for each of them
 export const PrintServiceTokens: Map<string, InjectionToken<IPrint>> = new Map();
 // Add File service implementation token
 PrintServiceTokens.set('file', new InjectionToken<IPrint>('file'));

提供者文件服务实现

   providers: [
      ...
      // First implementation service
      {
         provide: PrintServiceTokens.get('file'),
         useClass: FilePrint
      }
   ]

其他实现(可能在另一个模块上)

export class ScreenPrint implements IPrint {
    Print(textInput: string): void {
        console.log("ScreenPrint");
    }
}

为其他实现添加令牌

PrintServiceTokens.set('screen', new InjectionToken<IPrint>('screen'));

添加提供商

   providers: [
      ...
      // Other implementation service
      {
         provide: PrintServiceTokens.get('screen'),
         useClass: ScreenPrint
      }
   ]

最后,在组件或服务中

    myPrintService: IPrint;

    constructor(private injector: Injector) {
       // Up to you to choose service to use, a simple string could be provided by a @Input
       this.myPrintService = this.injector.get(PrintServiceTokens.get('file'));
       this.myPrintService = this.injector.get(PrintServiceTokens.get('screen'));
    }
于 2021-05-13T14:29:25.290 回答
0

角度不知道必须使用哪个实现:

角知道。Angular 将使用ScreenPrint. 您只需覆盖 IPrint 的注入令牌。对于一个注入令牌,您一次不能有不同的实现。

于 2020-08-04T17:37:36.687 回答