Angular style injection
var Controller = function(Greeter) {
/*Greeter is 'constructor' injected*/
Greeter.greet()
};
Container has three responsibilities
var Dependency = {
register: function(name, dependency){
},
resolve: function(name) {
},
inject: function(target){
}
};
Registration
var Greeter = {
greet: function(){
Alert("Hello Developer User Group!");
}
};
Dependency.register("Greeter", Greeter);
Inject by key, because JS has no 'interfaces'
Registration
var Dependency = {
dependencies: {}, // Simple object hash
register: function(name, dependency){
this.dependencies[name] = dependency;
}
};
Resolution
var greeter = Dependency.resolve("Greeter");
greeter.Greet();
Resolution
var Dependency = {
resolve: function(name){
return this.dependencies[name];
}
};
Easy.
But not what we're after..
Constructor Injection
(Where the real money is)
var Controller = function(Greeter) {
Greeter.greet()
};
Dependency.inject(Controller);
Magic strings
- We want to deal in objects, but resolution is by key.
- Simple string representation of the object.
Controller.toString();
/*
"function (Greeter){
Greeter.greet();
}"
*/
Magic strings
Relax.
Embrace it.
The feeling of discomfort will pass.
Magic strings
The incantation:
var regex = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var arguments = Controller.toString()
.match(regex)[1]
.split(',');
Injection
var Dependency = {
inject: function(target){
var regex = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var arguments = target.toString()
.match(regex)[1]
.split(',');
var self = this;
var dependencies = arguments.map(function(key){
return self.resolve(key);
});
target.apply(target, dependencies);
}
};
The whole picture
var Dependency = {
dependencies: {},
register: function(name, dependency){
this.dependencies[name] = dependency;
},
resolve: function(name){
return this.dependencies[name];
},
inject: function(target){
var regex = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var arguments = target.toString()
.match(regex)[1]
.split(',');
var self = this;
var dependencies = arguments.map(function(key){
return self.resolve(key);
});
target.apply(target, dependencies);
}
};
How Angular wires it up
<script>
function Controller(Greeter) {
Greeter.greet();
}
</script>
<div ng-app="" ng-controller="Controller">
<!-- -->
</div>
Ng hides the injection behind Controller injection.
(Much like ASP.NET MVC)