动态查找服务实现

Look up service implementations dynamically

我们的 Angular 应用程序有一个可以有不同实现的服务,又名。 “策略”。为简单起见,我们假设它是一个“事件报告”服务。事件上报服务具有上报信息的功能。根据运行时偏好,报告可以关闭,转到 console,或发送到 REST API,或转到其他地方。

使用纯 TS,这看起来像:

interface IReporter {
  report (message: string): void;
}

class NoReporter implements IReporter {
  report (message: string): void {
    // no op.
  }
}

class ConsoleReporter implements IReporter {
  report (message: string): void {
    console.log(message);
  }
}

// etc.

在消费者中,我会放置一些工厂来提供所需的记者,例如基于用户偏好设置:

getReporter (key: string): IReporter {
  switch (key) {
    // … tedious cases, which need to be mainted. Yikes!
  }
}

然而,这感觉不太像“Angular”。第一步可能是为个别记者提供适当的 Angular 服务,但仅此一点感觉收获不大。所以:是否有一些现有机制可以让我获得上述工厂功能来动态查找实现?有任何可遵循的模式、示例或最佳实践吗?

如评论中所述FactoryProviders完美解决此问题

您必须将 IReporter 接口定义为 class interface,因为接口在运行时不存在,因此它们不是有效的 DI 令牌:

export abstract class IReporter {
  report: (message: string) => void;
}

@Injectable()
export class NoReporter implements IReporter{
  report(message:string):void{

  }
}

@Injectable()
export class ConsoleReporter implements IReporter {
  report(message: string): void {
    console.log(message);
  }
}

现在您可以创建 reporterFactoryreporterProvider,如下所示:

const reporterFactory = (key: string) => {
  switch (key) {
    case 'no-report':
      return () => new NoReporter();
    case 'console-report':
      return () => new ConsoleReporter();
    default:
      return () => new ConsoleReporter();
  }
};

export const reporterProvider = (key: string) => {
  return {
    provide: IReporter,
    useFactory: reporterFactory(key)
  }
};

并在你的组件中注入一个记者:

@Component({
  selector: 'test',
  template: `TESTCOMPONENT`,
  providers: [
    reporterProvider('console-report')
  ]
})
export class TestComponent {
  constructor(private reporter: IReporter) {
    reporter.report('it works!!!');
  }

}