-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
111 lines (94 loc) · 2.47 KB
/
utils.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
package di
import (
"context"
"reflect"
)
var (
_typeErr = Key[error]()
_keyContext = Key[context.Context]()
_keyContainer = Key[Container]()
_typeNilReturn = Key[nilReturn]()
_typeDisposable = Key[Disposable]()
_typeInitializer = Key[Initializable]()
_typeReflectType = Key[reflect.Type]()
)
func isError(t reflect.Type) bool {
return t.Implements(_typeErr)
}
func getContext(contexts ...context.Context) (ctx context.Context) {
if len(contexts) > 0 {
ctx = contexts[0]
}
if ctx != nil {
return ctx
}
return context.Background()
}
// Key is a pointer to a type
func Key[T any]() reflect.Type {
return reflect.TypeOf((*T)(nil)).Elem()
}
// KeyOf get a key for a value
func KeyOf(t any) reflect.Type {
if tt, ok := t.(reflect.Type); ok {
return tt
} else if tt, ok := t.(reflect.Value); ok {
return tt.Type()
}
return reflect.TypeOf(t)
}
// Injector simplifies component registration through reflection.
//
// Example:
//
// type myController struct {
// MyService Service `inject:""`
// }
//
// di.InjectedTo[*myController](di.Global())
//
// In the example above, the MyService dependency will be injected automatically.
func InjectedTo[T any](c Container, opts ...FactoryConfig) {
c.Register(Injector[T](), opts...)
}
// GetFrom get a instance from container using generics (returns error)
func GetFrom[T any](c Container, contexts ...context.Context) (o T, e error) {
if v, err := c.Get(Key[T](), contexts...); err != nil {
e = err
} else {
o = v.(T)
}
return
}
// MustGetFrom get a instance from container using generics (panic on error)
func MustGetFrom[T any](c Container, ctx ...context.Context) T {
o, err := GetFrom[T](c, ctx...)
if err != nil {
panic(err)
}
return o
}
func FilterOf[T any](c Container) *FilteredFactories {
key := Key[T]()
cond := Condition(func(c Container, f *Factory) bool {
return f.key == key || f.Type().AssignableTo(key)
})
return c.Filter(cond)
}
func AllOf[T any](c Container, ctx context.Context) (o []T, e error) {
return AllOfFilter[T](FilterOf[T](c), ctx)
}
func AllOfFilter[T any](filter *FilteredFactories, ctx context.Context) (o []T, e error) {
var objects []T
err := filter.Foreach(func(f *Factory) (bool, error) {
if obj, disposer, err := filter.container.GetObjectFactory(f, true, ctx)(); err != nil {
return true, err
} else if o, ok := obj.(T); ok {
objects = append(objects, o)
} else if disposer != nil {
disposer.Dispose()
}
return false, nil
})
return objects, err
}