Skip to content

Commit

Permalink
more refactorizification
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmfoley committed Apr 19, 2012
1 parent 2b043e9 commit d374c87
Showing 1 changed file with 46 additions and 33 deletions.
79 changes: 46 additions & 33 deletions lib/container.coffee
Original file line number Diff line number Diff line change
@@ -1,53 +1,41 @@
module.exports = class Container
constructor: ->
@typeMap = {}
@map = new TypeMap

register : (args...) =>
if typeof args[1] is 'object'
@addRegistration(args[0], {instance : args[1]})
@map.addRegistration(args[0], {instance : args[1]})
else if typeof args[0] is 'function'
@addConstructorRegistration(args[0].name, args[0], args[1..])
else
@addConstructorRegistration(args[0], args[1], args[2..])

get : (thingToGet, chain = [])->
if typeof thingToGet is 'function'
unless @map.hasRegistration(thingToGet.name)
@register(thingToGet)
name = thingToGet.name
else
name = thingToGet

info = @map.getRegistration(name)
@checkForMissingRegistration(name, info, chain)

info.instance ?= @buildInstance(name, info, chain)

buildInstance: (name, info, chain) ->
@checkForCircularDependency(name, chain)
deps = (@get(dep, chain.concat([name])) for dep in info.dependencies)
new info.ctor(deps...)

addConstructorRegistration: (name, constructor, dependencies) ->
unless dependencies && (dependencies.length > 0)
dependencies = @determineDependencies(constructor)
dependencies = new FunctionInfo(constructor).argumentNames()

@addRegistration name,
@map.addRegistration name,
ctor: constructor
dependencies : dependencies ? []

determineDependencies: (constructor) ->
firstLine = constructor.toString().split("\n")[0]
argFinder= /(?:\(|\, )(\w+)/g
args = []
while (arg = argFinder.exec(firstLine))
args.push(arg[1])
args

addRegistration: (name, props) ->
@typeMap[name.toLowerCase()] = props

get : (name, chain = [])->
if typeof name is 'function'
unless @typeMap[name.name.toLowerCase()]
@register(name)
name = name.name

info = @getRegistration(name)
@checkForMissingRegistration(name, info, chain)

unless info.instance
@checkForCircularDependency(name, chain)
deps = (@get(dep, chain.concat([name])) for dep in info.dependencies)
info.instance = new info.ctor(deps...)
info.instance

getRegistration: (name) ->
@typeMap[name.toLowerCase()]

checkForMissingRegistration: (name, info, chain) ->
unless info
@throwWithDependencyChain "No registration for '#{name}'", chain.concat([name])
Expand All @@ -67,3 +55,28 @@ module.exports = class Container
for step in chain[1..]
message = message + " -> #{step}"
message

class FunctionInfo
constructor: (@fn) ->

argumentNames : =>
firstLine = @fn.toString().split("\n")[0]
argFinder= /(?:\(|\, )(\w+)/g
args = []
while (arg = argFinder.exec(firstLine))
args.push(arg[1])
args

class TypeMap
constructor: ->
@typeMap = {}

hasRegistration: (name) ->
!!@typeMap[name.toLowerCase()]

getRegistration: (name) ->
@typeMap[name.toLowerCase()]

addRegistration: (name, props) ->
@typeMap[name.toLowerCase()] = props

0 comments on commit d374c87

Please sign in to comment.