-
Notifications
You must be signed in to change notification settings - Fork 0
/
container_filter.go
135 lines (111 loc) · 2.51 KB
/
container_filter.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package di
import (
"context"
"reflect"
"sort"
)
type FilteredFactories struct {
container Container
factories []*Factory
}
func (f *FilteredFactories) Sort(less func(a, b *Factory) bool) *FilteredFactories {
if less == nil {
less = DefaultFactorySortLessFn
}
sort.Slice(f.factories, func(i, j int) bool {
return less(f.factories[i], f.factories[j])
})
return f
}
func (f *FilteredFactories) Foreach(visitor func(f *Factory) (stop bool, err error)) error {
for _, p := range f.factories {
if stop, err := visitor(p); err != nil {
return err
} else if stop {
return nil
}
}
return nil
}
func (f *FilteredFactories) Instances(ctx context.Context) ([]any, error) {
var objects []any
err := f.Foreach(func(factory *Factory) (bool, error) {
if obj, _, err := f.container.GetObjectFactory(factory, true, ctx)(); err != nil {
return true, err
} else if obj != nil {
objects = append(objects, obj)
}
return false, nil
})
return objects, err
}
func (c *container) Filter(options ...FactoryConfig) *FilteredFactories {
filter := &Factory{
qualifiers: make(map[reflect.Type]bool),
}
for _, option := range options {
option(filter)
}
var factories []*Factory
for _, candidates := range c.factories {
for _, factory := range candidates {
matchAll := true
for _, match := range filter.conditions {
if !match(c, factory) {
matchAll = false
break
}
}
if !matchAll {
continue
}
if filter.Primary() && !factory.Primary() {
continue
}
if filter.startup && !factory.startup {
continue
}
if filter.scope != "" && filter.scope != factory.scope {
continue
}
if len(filter.qualifiers) > 0 {
found := false
for qualifier := range filter.qualifiers {
if factory.qualifiers[qualifier] {
found = true
break
}
}
if !found {
continue
}
}
factories = append(factories, factory)
}
}
return (&FilteredFactories{
container: c,
factories: factories,
}).Sort(DefaultFactorySortLessFn)
}
// DefaultFactorySortLessFn is the default sorting function
// used by the Filter method, which sorts the factories in
// the following order:
//
// 1) Mock (test)
// 2) Primary
// 3) NOT Alternative
// 4) Lower Order
func DefaultFactorySortLessFn(a, b *Factory) bool {
if a.Mock() != b.Mock() {
// mock first (testing)
return a.Mock()
}
if a.Primary() != b.Primary() {
return a.Primary()
}
if a.Alternative() != b.Alternative() {
return b.Alternative()
}
return a.Order() < b.Order()
}