github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/injector/container_rw.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package injector 7 8 import ( 9 "fmt" 10 "sync" 11 12 "github.com/insolar/vanilla/throw" 13 ) 14 15 func NewDynamicContainer(parentRegistry DependencyRegistry) *DynamicContainer { 16 return &DynamicContainer{ parentRegistry: parentRegistry } 17 } 18 19 type DynamicContainer struct { 20 parentRegistry DependencyRegistry 21 localRegistry sync.Map 22 } 23 24 func (m *DynamicContainer) FindDependency(id string) (interface{}, bool) { 25 if m == nil { 26 return nil, false 27 } 28 29 if v, ok := m.localRegistry.Load(id); ok { 30 return v, true 31 } 32 if m.parentRegistry != nil { 33 return m.parentRegistry.FindDependency(id) 34 } 35 return nil, false 36 } 37 38 func (m *DynamicContainer) ScanDependencies(fn func(id string, v interface{}) bool) (found bool) { 39 if m == nil { 40 return false 41 } 42 43 if fn == nil { 44 panic(throw.IllegalValue()) 45 } 46 47 m.localRegistry.Range(func(key, value interface{}) bool { 48 if fn(key.(string), value) { 49 found = true 50 return false 51 } 52 return true 53 }) 54 55 if found { 56 return true 57 } 58 59 if sp, ok := m.parentRegistry.(ScanDependencyRegistry); ok { 60 return sp.ScanDependencies(fn) 61 } 62 return false 63 } 64 65 func AddDependency(m DependencyContainer, v interface{}) { 66 if !m.TryPutDependency(GetDefaultInjectionID(v), v) { 67 panic(fmt.Errorf("duplicate dependency: %T %[1]v", v)) 68 } 69 } 70 71 func AddInterfaceDependency(m DependencyContainer, v interface{}) { 72 vv, vt := GetInterfaceTypeAndValue(v) 73 if !m.TryPutDependency(GetDefaultInjectionIDByType(vt), vv) { 74 panic(fmt.Errorf("duplicate dependency: %T %[1]v", v)) 75 } 76 } 77 78 func NameOfDependency(v interface{}) string { 79 return GetDefaultInjectionID(v) 80 } 81 82 func NameOfInterfaceDependency(v interface{}) string { 83 _, vt := GetInterfaceTypeAndValue(v) 84 return GetDefaultInjectionIDByType(vt) 85 } 86 87 func (m *DynamicContainer) AddDependency(v interface{}) { 88 AddDependency(m, v) 89 } 90 91 func (m *DynamicContainer) AddInterfaceDependency(v interface{}) { 92 AddInterfaceDependency(m, v) 93 } 94 95 func (m *DynamicContainer) PutDependency(id string, v interface{}) { 96 if id == "" { 97 panic(throw.IllegalValue()) 98 } 99 m.localRegistry.Store(id, v) 100 } 101 102 func (m *DynamicContainer) TryPutDependency(id string, v interface{}) bool { 103 if id == "" { 104 panic(throw.IllegalValue()) 105 } 106 _, loaded := m.localRegistry.LoadOrStore(id, v) 107 return !loaded 108 } 109 110 func (m *DynamicContainer) DeleteDependency(id string) { 111 m.localRegistry.Delete(id) 112 } 113 114 func (m *DynamicContainer) CopyAsStatic() StaticContainer { 115 if m == nil { 116 return NewStaticContainer(nil, nil) 117 } 118 return NewStaticContainer(m.parentRegistry, m) 119 } 120 121 func (m *DynamicContainer) ReplaceDependency(v interface{}) { 122 id := GetDefaultInjectionID(v) 123 m.localRegistry.Delete(id) 124 m.PutDependency(id, v) 125 } 126 127 func (m *DynamicContainer) ReplaceInterfaceDependency(v interface{}) { 128 vv, vt := GetInterfaceTypeAndValue(v) 129 id := GetDefaultInjectionIDByType(vt) 130 m.localRegistry.Delete(id) 131 m.PutDependency(id, vv) 132 } 133