Dependency Injection container uses Resolvers
internally to provide all instances. When explicitly configuring
the container, you are actually specifying what Resolver
should be associated with a particular lookup key. However, there's a second way that resolvers
are useful. Instead of supplying a key as part of the inject
decorator, you can provide a Resolver
instead.
This resolver
then communicates
with the container to provide special resolution behavior, specific to the injection
. Here's a list of the resolvers
you can use in this capacity:
Lazy : Injects a function for lazily evaluating the dependency.
Ex. Lazy.of(HttpClient)
All
: Injects an array of all services registered with the provided key.
Ex. All.of(Plugin)
Optional
: Injects an instance of a class only if it already exists in the container; null otherwise.
Ex. Optional.of(LoggedInUser)
Parent
: Skips starting dependency resolution from the current container and instead begins the lookup process on the parent container.
Ex. Parent.of(MyCustomElement)
Factory
: Used to allow injecting dependencies, but also passing data to the constructor.
Ex. Factory.of(CustomClass)
NewInstance
: Used to inject a new instance of a dependency, without regard for existing instances in the container.
Ex. NewInstance.of(CustomClass).as(Another)
If using TypeScript
, keep in mind that @autoinject
won't allow you to use Resolvers. You also can use inject as argument decorator for your own custom resolvers, eg constructor(@inject(NewInstance.of(HttpClient)) public client: HttpClient){...}
. Available build-in function parameter decorators are :
* lazy(key)
* all(key)
* optional(checkParent?)
* parent
* factory(key)
* newInstance(asKey?, dynamicDependencies: [any])
Here's an example of how we might express a dependency
on HttpClient
that we may or may not actually need to use, depending on runtime scenarios :
Using Resolvers : TypeScript
import {lazy} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';
export class CustomerDetail {
constructor(@lazy(HttpClient) private getHTTP: () => HttpClient){ }
}
In this case, the Lazy
resolver doesn't actually provide an instance of HttpClient
directly. Instead, it provides a function that can be invoked at some point in the future to obtain an instance of HttpClient
if needed.