1 | ClassMap = require './class_map'
|
2 |
|
3 | class Injector
|
4 | constructor: (@binders...) ->
|
5 | @_singletons = new ClassMap()
|
6 |
|
7 | getInstance: (cls, args...) ->
|
8 | for binder in @binders
|
9 | for binding in binder.bindings
|
10 | instance = @_resolve(cls, binding)
|
11 | if instance? then return instance
|
12 |
|
13 | unless cls.prototype? then throw Error('Could not resolve')
|
14 | @_createNew(cls, undefined, args...)
|
15 |
|
16 | _createNew: (cls, scope, args...) ->
|
17 | if cls is Injector then return this
|
18 | singleton = @_singletons.get(cls)
|
19 | if singleton? then return singleton
|
20 |
|
21 | ptype = ->
|
22 | ptype.prototype = cls.prototype
|
23 | instance = new ptype()
|
24 | @_injectFields(cls.prototype, instance)
|
25 | cls.apply(instance, args)
|
26 |
|
27 | if scope?.toUpperCase?() is 'SINGLETON' or cls.scope?.toUpperCase?() is 'SINGLETON'
|
28 | @_singletons.set(cls, instance)
|
29 |
|
30 | instance
|
31 |
|
32 | _resolve: (cls, binding) ->
|
33 | if binding.matches(cls)
|
34 | defaultFactory = =>
|
35 | @_createNew(binding.impl, binding.scope)
|
36 | binding.create(defaultFactory)
|
37 |
|
38 | _injectFields: (ptype, instance) ->
|
39 | for k, v of ptype
|
40 | if v? and v._requiresInjection_
|
41 | instance[k] = @getInstance(v.cls, v.args...)
|
42 |
|
43 | module.exports = Injector
|