UNPKG

1.43 kBtext/coffeescriptView Raw
1ClassMap = require './class_map'
2
3name = (injectable) ->
4 if injectable.name? then injectable.name
5 else "'#{injectable}'"
6
7class Injector
8 constructor: (@binders...) ->
9 @_singletons = new ClassMap()
10 @_stack = []
11
12 getInstance: (cls, args...) ->
13 @_stack.push(name(cls))
14
15 try
16 for binder in @binders
17 for binding in binder.bindings
18 instance = @_resolve(cls, binding)
19 if instance? then return instance
20
21 unless cls.prototype?
22 throw Error("Could not resolve: #{@_stack.join(' -> ')}")
23 @_createNew(cls, undefined, args...)
24
25 finally
26 @_stack.pop()
27
28 _createNew: (cls, scope, args...) ->
29 if cls is Injector then return this
30 singleton = @_singletons.get(cls)
31 if singleton? then return singleton
32
33 ptype = ->
34 ptype.prototype = cls.prototype
35 instance = new ptype()
36 @_injectFields(cls.prototype, instance)
37 cls.apply(instance, args)
38
39 if scope?.toUpperCase?() is 'SINGLETON' or cls.scope?.toUpperCase?() is 'SINGLETON'
40 @_singletons.set(cls, instance)
41
42 instance
43
44 _resolve: (cls, binding) ->
45 if binding.matches(cls)
46 defaultFactory = =>
47 @_createNew(binding.impl, binding.scope)
48 binding.create(defaultFactory)
49
50 _injectFields: (ptype, instance) ->
51 for k, v of ptype
52 if v? and v._requiresInjection_
53 instance[k] = @getInstance(v.cls, v.args...)
54
55module.exports = Injector