lib/injector.js
/**
* @class Injector
*/
export class Injector{
/**
* This is an Injector
* @constructor
* @param {ResolvedBinding} resolvedBindings - The resolved binding of the injector
* @param {Injector} parent - The parent injector
*/
constructor(resolvedBindings, parent){
this.resolvedBindings = resolvedBindings;
this.parent = parent;
}
/**
* This is an injector Factory
* @param {Binding} bindings - List of the bindings to resolve
* @Optionnal {Injector} injector - Optionnal parent injector
* @returns {Injector} The new injector created
*/
static resolveAndCreate(bindings, injector){
return new Injector(Injector.resolve(bindings), injector);
}
/**
* Start the binding resolution
* @param {Binding} bindings - An array of bindings to resolve
* @returns {ResolvedBinding} The array of resolvedBinding obtained
*/
static resolve(bindings){
let resolvedBindings = [];
for(var b of bindings){
resolvedBindings.push(b.resolve());
}
return resolvedBindings;
}
/**
* Return the factory execution value if the key matches
* @param {String} token - The key of the resolvedBinding factory to get
* @returns {Object} The value corresponding to the factory execution
*/
get(token){
for(var rb of this.resolvedBindings){
if(rb.key === token){
return this.resolveDependencies(rb);
}
}
return token;
}
/**
* Resolve the dependencies of the resolvedBinding
* @param {ResolvedBinding} resolvedBinding - The resolved binding concerned
* @returns {Object} The factory execution loaded
*/
resolveDependencies(resolvedBinding){
let dependencyArray = this.parseDependencies(resolvedBinding.dependencies);
let newInstance = this.resolveConstructor(resolvedBinding, dependencyArray.inConstructor);
newInstance = this.resolveProperty(newInstance, dependencyArray.inProperty);
newInstance = this.resolveSetters(newInstance, dependencyArray.inSetter);
return newInstance;
}
/**
* Split dependencies in an array of object
* @param {Object} dependencies - An array of dependencies
* @returns {Object} An array of dependencies splitted into 3 category
* inConstructor, inProperty, inSetter
*/
parseDependencies(dependencies){
let dependencyArray = {inConstructor:[], inProperty:[], inSetter:[]}
for(var d of dependencies){
if(d.inSetter){
dependencyArray.inSetter.push(d);
}else{
if(d.inProperty){
dependencyArray.inProperty.push(d);
}else{
dependencyArray.inConstructor.push(d);
}
}
}
return dependencyArray;
}
/**
* Resolve the constructor injector
* @param {ResolvedBinding} resolvedBinding - The resolved binding to loaded
* @param {Object} dependencies - The dependencies to inject
* @returns {Object} Return the object instance with constructor dependencies
*/
resolveConstructor(resolvedBinding, dependencies){
let newInstance = null;
switch(dependencies.length){
case 0:
newInstance = resolvedBinding.factory();
break;
case 1:
newInstance = resolvedBinding.factory(this.get(dependencies[0]));
break;
case 2:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]));
break;
case 3:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]));
break;
case 4:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]));
break;
case 5:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]), this.get(dependencies[4]));
break;
case 6:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]), this.get(dependencies[4]), this.get(dependencies[5]));
break;
case 7:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]), this.get(dependencies[4]), this.get(dependencies[5]), this.get(dependencies[6]));
break;
case 8:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]), this.get(dependencies[4]), this.get(dependencies[5]), this.get(dependencies[6]),
this.get(dependencies[7]));
break;
case 9:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]), this.get(dependencies[4]), this.get(dependencies[5]), this.get(dependencies[6]),
this.get(dependencies[7]), this.get(dependencies[8]));
break;
case 10:
newInstance = resolvedBinding.factory(this.get(dependencies[0]), this.get(dependencies[1]), this.get(dependencies[2]),
this.get(dependencies[3]), this.get(dependencies[4]), this.get(dependencies[5]), this.get(dependencies[6]),
this.get(dependencies[7]), this.get(dependencies[8]), this.get(dependencies[9]));
break;
}
return newInstance;
}
/**
* Resolve properties injection
* @param {Object} newInstance - The object instance where to inject properties
* @params {Object} dependencies - The property dependencies to inject
* @returns {Object} The object with property injected
*/
resolveProperty(newInstance, dependencies){
for(var d of dependencies){
newInstance[d.ref[0].toLowerCase() + d.ref.substring(1)] = this.get(d.ref);
}
return newInstance;
}
/**
* Resolve setters injection
* @param {Object} newInstance - The object where to make setter injection
* @params {Object} dependencies - The setter dependencies to inject
* @returns {Object} The object with setters injected
*/
resolveSetters(newInstance, dependencies){
for(var d of dependencies){
newInstance['set'+d.ref] = this.get(d.ref);
}
return newInstance;
}
}