-
Notifications
You must be signed in to change notification settings - Fork 1
/
options.go
93 lines (73 loc) · 2.34 KB
/
options.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
package cronos
import "reflect"
//OptionsList - list of options
type OptionsList []Options
// Options - dependency injection options
type Options struct {
key key
task func(objectKey key, cronos *Cronos)
priority int
}
func (ol OptionsList) Len() int {
return len(ol)
}
func (ol OptionsList) Less(i, j int) bool {
return ol[i].priority < ol[j].priority
}
func (ol OptionsList) Swap(i, j int) {
ol[i], ol[j] = ol[j], ol[i]
}
// Singleton - determines whether the dependency is a singleton, the default is true.
func Singleton(isSingleton bool) Options {
return Options{
task: func(objectKey key, cronos *Cronos) {
if !isSingleton {
cronos.cache.notSingletons[objectKey] = !isSingleton
}
},
priority: 1,
}
}
// As - specify whether constructor returns an interface
func As(typei interface{}) Options {
return Options{
task: func(objectKey key, cronos *Cronos) {
object, ok := cronos.cache.components[objectKey]
if !ok {
object = cronos.Fetch(objectKey.typed)
}
ikey := key{reflect.TypeOf(typei).Elem()}
if _, ok := cronos.cache.components[ikey]; !ok {
cronos.cache.components[ikey] = object
}
},
priority: 2,
}
}
// Qualifier - determines the specific type of dependency injected as an interface.
func Qualifier(typeObject, typeInterface interface{}) Options {
return Options{
task: func(objectKey key, cronos *Cronos) {
qualifierObjectKey := key{reflect.TypeOf(typeObject).Elem()}
qualificerInterfaceKey := key{reflect.TypeOf(typeInterface)}
qualifierObject := cronos.Fetch(qualifierObjectKey.typed)
qualifierObjectValue := reflect.ValueOf(qualifierObject)
constructor := cronos.cache.constructors[objectKey]
argsOldConstructor := cronos.getArgs(constructor)
args := make([]reflect.Value, len(argsOldConstructor))
for i := 0; i < len(argsOldConstructor); i++ {
objectInterfaceType := qualificerInterfaceKey.typed.Elem()
if argsOldConstructor[i].Implements(objectInterfaceType) {
args[i] = qualifierObjectValue
} else {
args[i] = reflect.ValueOf(cronos.Fetch(argsOldConstructor[i]))
}
}
newConstructor := reflect.MakeFunc(reflect.TypeOf(constructor), func(arguments []reflect.Value) []reflect.Value {
return reflect.ValueOf(constructor).Call(args)
})
cronos.cache.constructors[objectKey] = newConstructor.Interface()
},
priority: 3,
}
}