-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscope.go
121 lines (100 loc) · 2.75 KB
/
scope.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
package di
import (
"fmt"
"reflect"
"sync"
"github.com/fluffy-bunny/fluffy-dozm-di/errorx"
"github.com/fluffy-bunny/fluffy-dozm-di/reflectx"
)
type ContainerEngineScope struct {
RootContainer *container
IsRootScope bool
ResolvedServices map[ServiceCacheKey]any
Locker *sync.Mutex
disposed bool
disposables []Disposable
}
func (c *ContainerEngineScope) GetDescriptors() []*Descriptor {
return c.RootContainer.GetDescriptors()
}
func (s *ContainerEngineScope) Get(serviceType reflect.Type) (any, error) {
if s.disposed {
return nil, &errorx.ObjectDisposedError{Message: reflectx.TypeOf[Container]().String()}
}
return s.RootContainer.GetWithScope(serviceType, s)
}
func (s *ContainerEngineScope) GetByLookupKey(serviceType reflect.Type, key string) (any, error) {
if s.disposed {
return nil, &errorx.ObjectDisposedError{Message: reflectx.TypeOf[Container]().String()}
}
return s.RootContainer.GetWithScopeWithLookupKey(serviceType, key, s)
}
func (s *ContainerEngineScope) Container() Container {
return s
}
func (s *ContainerEngineScope) CreateScope() Scope {
return s.RootContainer.CreateScope()
}
func (s *ContainerEngineScope) Dispose() {
disposables := s.BeginDispose()
for i := len(disposables) - 1; i >= 0; i-- {
disposables[i].Dispose()
}
}
func (s *ContainerEngineScope) Disposables() []Disposable {
return s.disposables
}
func (s *ContainerEngineScope) BeginDispose() []Disposable {
s.Locker.Lock()
if s.disposed {
s.Locker.Unlock()
return nil
}
s.disposed = true
s.Locker.Unlock()
if s.IsRootScope && !s.RootContainer.IsDisposed() {
s.RootContainer.Dispose()
}
return s.disposables
}
func (s *ContainerEngineScope) CaptureDisposable(service any) (Disposable, error) {
d, ok := service.(Disposable)
if service == s || !ok {
return d, nil
}
disposed := false
s.Locker.Lock()
if s.disposed {
disposed = true
} else {
s.disposables = append(s.disposables, d)
}
s.Locker.Unlock()
if disposed {
d.Dispose()
return d, fmt.Errorf("capture disposable service '%v', scope disposed", reflect.TypeOf(service))
}
return d, nil
}
func (s *ContainerEngineScope) CaptureDisposableWithoutLock(service any) (Disposable, error) {
d, ok := service.(Disposable)
if service == s || !ok {
return d, nil
}
if s.disposed {
d.Dispose()
return d, fmt.Errorf("capture disposable service '%v', scope disposed", reflect.TypeOf(service))
} else {
s.disposables = append(s.disposables, d)
return d, nil
}
}
func newEngineScope(c *container, isRootScope bool) *ContainerEngineScope {
return &ContainerEngineScope{
RootContainer: c,
IsRootScope: isRootScope,
ResolvedServices: make(map[ServiceCacheKey]any),
Locker: new(sync.Mutex),
disposables: make([]Disposable, 0),
}
}