-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathinjector.go
120 lines (89 loc) · 2.32 KB
/
injector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package digo
import (
"errors"
"reflect"
)
func NewInjector(nodeMap map[string]*NodeData) *Injector {
return &Injector{
cache: map[string]interface{}{},
nodeMap: nodeMap,
}
}
var depInjector *Injector
type Injector struct {
cache map[string]interface{}
nodeMap map[string]*NodeData
}
func (this *Injector) resolve(node *NodeData, alias string) (interface{}, error) {
if node.Scope == "singleton" {
node.IsPtr = true
if i, err := this.getFromCache(alias); err == nil {
return i, nil
}
}
cp, err := this.newTypeOf(node.Type, node.IsPtr)
if err != nil {
return struct{}{}, errors.New("Error creating new Type -> " + err.Error())
}
for _, dependency := range node.Deps {
err := this.assignValues(cp, dependency, node.IsPtr)
if err != nil {
return struct{}{}, errors.New("Error resolving dependencies -> " + err.Error())
}
}
i := cp.Interface()
if init, isInit := i.(Initializer); isInit {
err := init.BeforeInject()
if err != nil {
return struct{}{}, nil
}
}
if node.Scope == "singleton" {
this.cache[alias] = i
}
return i, nil
}
func (this *Injector) getFromCache(key string) (interface{}, error) {
if item, exists := this.cache[key]; exists {
return item, nil
}
return struct{}{}, errors.New("Not in cache")
}
func (this *Injector) newTypeOf(key string, isPtr bool) (reflect.Value, error) {
t, err := TypeRegistry.Get(key)
if err != nil {
return reflect.Value{}, errors.New("Error getting the type from TypeRegistry -> " + err.Error())
}
if isPtr {
return reflect.New(t), nil
}
return reflect.New(t).Elem(), nil
}
func (this *Injector) assignValues(cp reflect.Value, dependency *DepData, isPtr bool) error {
var depRoot *NodeData
if depNode, exists := this.nodeMap[dependency.ID]; exists {
depRoot = depNode
} else {
return errors.New("Dependency Id: " + dependency.ID + " not found")
}
var f reflect.Value
if isPtr {
f = reflect.Indirect(cp).FieldByName(dependency.Field)
} else {
f = cp.FieldByName(dependency.Field)
}
if f.IsValid() {
if f.CanSet() {
depcp, err := this.resolve(depRoot, dependency.ID)
if err != nil {
return err
}
f.Set(reflect.ValueOf(depcp))
} else {
return errors.New("Field cannot be set")
}
} else {
return errors.New("Invalid Field: " + dependency.Field + " from dep: " + depRoot.Type)
}
return nil
}