Archives For circular dependencies

… or how to leverage AMD’s require/define semantics for fine-grained dependency injection.

update: code now available on gist.github.com: https://gist.github.com/4089076

update2: better implementation of calling the service constructor in resolveInstance() to follow operator new semantics.

i’ve become a big fan of the asynchronous module definition (AMD) pattern for managing dependencies between libraries and script files in large JavaScript projects. requirejs is my current favourite AMD library. TypeScript also provides excellent support for compiling and consuming modules in AMD-compatible formats.

i’ve also become a big fan of Ninject for its lightweight but very effective dependency injection library for .Net.

when looking for a simple Ninject-like dependency injection container for JavaScript, I attempted to find something that would be as familiar as using the requirejs/AMD approach. I thought about using the requirejs plugin API, but it is too resource/file oriented and would require resource naming contortions to support named identities for containers and object instances.

during my research I came across Coffeescripter’s post regarding dependency injection and IoC in javascript, and I admired the simple and straightforward modeling of the relationship between an array of dependency names and a constructor function.  To me, this approach represented a very effective and lightweight way to adapt existing code for use in a dependency injection framework without having to make any modifications to that code.  The constructor functions act as shims between the dependency injection framework and existing code, and work much the same way as the requirejs/AMD define() function does with its associated callback.

this inspired me to implement a dependency injection container using define()/require()-like semantics, including support for circular dependency resolution.

the source…

you can download the source files for the ServiceKernel class described in this post, including unit tests, from here: https://gist.github.com/4089076

note: the source code provided has a few dependencies on ECMAScript 5 features, such as Array.isArray, Array.prototype.indexOf, and Function.prototype.bind. You can easily find replacements for these functions should you need to target an older platform.

Continue Reading…