Pattern to enable customization through DI

。_饼干妹妹 提交于 2019-12-12 03:31:00

问题


I'm looking at the implementation of in-memory-web-api and there is the following code:

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

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

As I understand the pattern is the following:

  1. Defined class property and instantiate a dependency without using DI
  2. Optionally inject dependency

If a user provides modified dependency through DI, it will be injected and the default one instantiated without DI will be overridden. I suspect something similar maybe with RequestOptions in HTTP module.

Is this a common pattern?

EDIT:

It turns out that in-memory-web-api is not exactly the pattern I'm asking about. Suppose, I have a class A that uses instance of class B injectable with the token B. So they are both registered with the root injector:

providers: [A, B]

Now, if a user wants to customize B, he can register the customized version under the same token, thus effectively overrriding the original B:

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

This is how RequestOptions can be extended in http module.


回答1:


The default value isn't just overridden. The most important part here is

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

Nothing would happen without it.

This pattern isn't specific to DI, it is a common recipe for default property values, similar to _.defaults.

I would say that InMemoryBackendConfig default implementation is useless abstraction here. Since this.config is always merged with config, the former could be just a plain object

  protected config: InMemoryBackendConfigArgs = { ... };

InMemoryBackendConfig and RequestOptions use complicated variations of this pattern. Yes, in most basic form this is how this can be done:

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

This pattern is widely used by constant services in AngularJS for configuration objects, but having B as a class instead of plain object allows to extend the original values instead of replacing them.



来源:https://stackoverflow.com/questions/42347721/pattern-to-enable-customization-through-di

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!