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:
- Defined class property and instantiate a dependency without using DI
- 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.
The default value isn't just overridden. The most important part here is
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. Sincethis.config
is always merged withconfig
, the former could be just a plain objectInMemoryBackendConfig
andRequestOptions
use complicated variations of this pattern. Yes, in most basic form this is how this can be done:This pattern is widely used by
constant
services in AngularJS for configuration objects, but havingB
as a class instead of plain object allows to extend the original values instead of replacing them.