通过 DI 启用自定义的模式

Pattern to enable customization through DI

我在看in-memory-web-api的实现,有如下代码:

@Injectable()
export class InMemoryBackendService {
  protected config: InMemoryBackendConfigArgs = new InMemoryBackendConfig();
            ^^^^^^
  ...

      constructor(
        @Inject(InMemoryBackendConfig) @Optional() config: InMemoryBackendConfigArgs 
                                                   ^^^^^^
        ) {
        ...

据我了解,模式如下:

  1. 已定义 class 属性 并在不使用 DI 的情况下实例化依赖项
  2. 可选地注入依赖项

如果用户通过 DI 提供修改的依赖项,它将被注入并覆盖默认的没有 DI 实例化的依赖项。我怀疑 HTTP 模块中的 RequestOptions 可能有类似的东西。

这是常见的模式吗?

编辑:

原来 in-memory-web-api 并不是我要问的模式。假设,我有一个 class A,它使用 class B 的实例,可通过令牌 B 注入。所以他们都注册了根注入器:

供应商:[A, B]

现在,如果用户想要自定义B,他可以在同一个token下注册自定义版本,从而有效地覆盖原来的B:

providers: [{provide:B, useClass: extendedB}]`

这就是 RequestOptionshttp 模块中的扩展方式。

不只是覆盖默认值。这里的most important part

Object.assign(this.config, config || {})

没有它什么都不会发生。

此模式并非特定于 DI,它是默认 属性 值的常见配方,类似于 _.defaults

我会说 InMemoryBackendConfig default implementation 在这里是无用的抽象。由于 this.config 总是与 config 合并,前者可能只是一个普通对象

  protected config: InMemoryBackendConfigArgs = { ... };

InMemoryBackendConfigRequestOptions 使用此模式的复杂变体。是的,在最基本的形式中,这是可以做到的:

providers: [{provide:B, useClass: extendedB}]`

此模式被 AngularJS 中的 constant 服务广泛用于配置对象,但将 B 作为 class 而不是普通对象允许扩展原始对象值而不是替换它们。