动态查找服务实现 [英] Look up service implementations dynamically

查看:64
本文介绍了动态查找服务实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Our Angular application has a service which can have different implementations, aka. "strategies". For simplicity, let’s assume it’s an "event reporting" service. The event reporting service has a function for reporting information. Depending on a runtime preference, the reporting can either turned off, go to the console, or be sent to a REST API, or go somewhere else.

使用纯TS,如下所示:

Using pure TS, this would look like:

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.

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

In a consumer, I’d put some factory which delivers the desired reporter, e.g. based on a user-preference setting:

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

但是,这感觉不太像"Angular".第一步可能是为单个记者提供适当的Angular服务,但是仅此一点就感觉很少.因此:是否有一些现有机制可以赋予我以上工厂功能以动态查找实现?有什么模式,示例或最佳做法可以遵循吗?

However, this feels not very "Angular"-like. First step would probably be to make proper Angular services of the individual reporters, but this alone feels like little gained. So: Is there some existing mechanism which would give me above factory functionality to dynamically look up an implementation? Any patterns, example or best practices to follow?

推荐答案

就像评论

Like mentioned in the comment FactoryProviders perfectly solve this problem.

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

You have to define your IReporter interface as an class interface because interfaces don't exist at runtime and therefore they are no valid DI tokens:

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:

Now you could create your reporterFactory and reporterProvider like shown below:

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

然后在组件中注入一个报告器:

And inject a reporter in your component:

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

}

这篇关于动态查找服务实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆