Injections
Dependencies can be injected in two ways: Constructor Injection with.use()
and Property Injection with.set()
.
Constructor Injection
$.bind(a contract).to(a concrete).use(some dependencies);
This allows you to inject dependencies via component's constructor. Remember that the order of dependencies must be same as of constructor's parameters. Following binding statement is an example of incorrect order that leads to an application error:
$.bind('my car').to(Car).use('a fuel tank', 'an engine'); // incorrect! Engine must be first.
No needs to always fully provide all dependencies as all parameters for the constructor. E.g if you want to just inject the Engine to the Car but the FuelTank, you can skip 'a fuel tank' as in following statement:
$.bind('my car').to(Car).use('an engine'); // skip the fuel tank to inject it later on.
It is NOT possible to skip the Engine but keep the FuelTank, because of constructor invocation is actually intrinsic function invocation in JS.
Property Injection
$.bind(a contract).to(a concrete).set(property mappings);
When your component has many dependencies and you want to inject them all, Constructor Injection maybe painful as you will have to deal with having so many parameters in your component's constructor. Considering having too many parameters in a function is likely a proof of code smell. Moreover, not all dependencies are collaborators of your component. Some of them can be Value Objects (e.g the Manufacturer of your Car). Therefore it is much better to declare them as properties of your component and inject them via Property Injection.
Let's go back to your Car. Now imagine you want to move Manufacturer off Car's constructor and make it a property of your car, similar to property 'model':
function Manufacturer(name) {
this.name = name;
};
function Car(engine, fuelTank) {
this.manufacturer = undefined;
this.model = undefined;
this.toString = function() {
return `Manufacturer: ${manufacturer.name} | Model: ${model}`;
}
};
Both manufacturer and model are initially set to undefined and will be injected at runtime. Now let's bind these properties to your car and build:
$.bind('my car').to(Car).set({ manufacturer: 'BMW', model: $.value('320i') });
console.log($('my car').toString()); // "Manufacturer: BMW | Model: 320i"
You can also combine both Constructor Injection and Property Injection in one statement:
$.bind('my car')
.to(Car)
.use('an engine', 'a fuel tank')
.set({ manufacturer: 'BMW', model: $.value('320i') });
// build the car and start it
var myCar = $('my car');
console.log(`My Car Information: [${myCar.toString()}]`);
myCar.start();
The console output will look like:
My Car Information: [Manufacturer: BMW | Model: 320i]
Car starting...
Engine started
Car started. Ready to go.
Last updated