Object Factories
Sometimes you want your object to receive a factory, that when called will resolve
and return the dependency in question.
class Item {
constructor() {
console.log("creating an item");
}
}
class Manager{
constructor(itemFactory) {
this._itemFactory = itemFactory;
}
createItem(name) {
return this._itemFactory(name);
}
}
let container = new Container();
container.register('item', Item).transient();
container.register('manager', Manager).inject({ resolver: 'factory', key: 'item'});
let manager = container.resolve('manager');
let item1 = manager.createItem();
let item2 = manager.createItem();
Output:
creating an item
creating an item
Note
Injected factories are different from factories you use to create objects (via
container.registerFactory
). A factory registered viaregisterFactory
is simply used to create your instance. An injected factory lets the container create the instance but it wraps this creation in a factory and injects the factory. It’s typically used for lazy resolution of objects or when an object needs to create many other objects but doesn’t want to take a dependency on the container itself.
Additional Dependencies in Factories
You can pass arguments to the factory and they forwarded as discussed under the resolve(..)
section.
Lets modify the sample from above to demonstrate this:
class Item {
constructor(otherDependencyA, name) {
console.log('Hello ' + name + '. Other dependency: ' + otherDependencyA);
}
}
class Manager{
constructor(itemFactory) {
this._itemFactory = itemFactory;
}
createItem(name) {
return this._itemFactory(name);
}
}
let container = new Container();
container.registerInstance('otherDependencyA', 'look! a string dependency');
container.register('item', Item).inject('otherDependencyA').transient();
container.register('manager', Manager).inject({ resolver: 'factory', key: 'item'});
let manager = container.resolve('manager');
let fooItem = manager.createItem('Foo');
let barItem = manager.createItem('Bar');
Output:
Hello Bob
Hello Mick