Skip to content

Commit 1a2bea6

Browse files
committed
support custom key
fix register interface add factory add IsShared make exists
1 parent a509f7f commit 1a2bea6

File tree

5 files changed

+175
-47
lines changed

5 files changed

+175
-47
lines changed

container.go

Lines changed: 64 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,66 @@ import (
55
)
66

77
type Container struct {
8-
instances map[reflect.Type]any
9-
registers map[reflect.Type]any
8+
instances map[any]any
9+
registers map[any]any
10+
factories []Factory
1011
}
1112

1213
var DefaultContainer = NewContainer()
1314

1415
func NewContainer() *Container {
1516
return &Container{
16-
instances: make(map[reflect.Type]any),
17-
registers: make(map[reflect.Type]any),
17+
instances: make(map[any]any),
18+
registers: make(map[any]any),
1819
}
1920
}
2021

22+
func (c *Container) AddFactory(factory Factory) {
23+
c.factories = append(c.factories, factory)
24+
}
25+
2126
func (c *Container) Register(key any, value any) {
22-
c.registers[bindKey(key)] = value
27+
c.registers[key] = value
2328
}
2429

2530
func (c *Container) Make(key any) any {
26-
if a, ok := c.registers[bindKey(key)]; ok {
31+
if a, ok := c.instances[key]; ok {
32+
return a
33+
}
34+
35+
if a, ok := c.registers[key]; ok {
2736
of := reflect.ValueOf(a)
2837
if of.Kind() == reflect.Func {
2938
return of.Call(nil)[0].Interface()
3039
}
3140
} else {
32-
if of, ok := key.(reflect.Type); ok {
33-
if of.Kind() == reflect.Ptr {
34-
return reflect.New(of.Elem()).Interface()
35-
} else {
36-
return reflect.New(of).Elem().Interface()
41+
for _, factory := range c.factories {
42+
if factory.Resolvable(key) {
43+
v := factory.Resolve(key)
44+
if factory.IsShared(key) {
45+
c.instances[key] = v
46+
}
47+
48+
return v
3749
}
38-
} else {
39-
return reflect.New(reflect.TypeOf(key)).Elem().Interface()
4050
}
51+
52+
return DefaultFactoryInstance.Resolve(key)
4153
}
4254

4355
return nil
4456
}
4557

4658
func (c *Container) Set(key any, ins any) {
47-
c.instances[bindKey(key)] = ins
59+
c.instances[key] = ins
4860
}
4961

5062
func (c *Container) Get(key any) any {
51-
return c.instances[bindKey(key)]
63+
return c.instances[key]
5264
}
5365

5466
func (c *Container) Has(key any) bool {
55-
_, ok := c.instances[bindKey(key)]
67+
_, ok := c.instances[key]
5668

5769
return ok
5870
}
@@ -61,61 +73,71 @@ func (c *Container) RegisteredKeys() []string {
6173
var keys []string
6274

6375
for k, _ := range c.registers {
64-
keys = append(keys, k.String())
76+
keys = append(keys, reflect.TypeOf(k).String())
6577
}
6678

6779
return keys
6880
}
6981

7082
func (c *Container) Clear() {
71-
c.instances = make(map[reflect.Type]any)
72-
c.registers = make(map[reflect.Type]any)
73-
}
74-
75-
func bindKey(key any) reflect.Type {
76-
var of reflect.Type
77-
78-
// if key is reflect.Type
79-
if t, ok := key.(reflect.Type); ok {
80-
of = t
81-
} else {
82-
of = reflect.TypeOf(key)
83-
}
84-
85-
return of
83+
c.instances = make(map[any]any)
84+
c.registers = make(map[any]any)
8685
}
8786

8887
func Set[T any](ins T) {
89-
var t T
88+
var t *T
9089

91-
DefaultContainer.Set(reflect.TypeOf(t), ins)
90+
DefaultContainer.Set(reflect.TypeOf(t).Elem(), ins)
9291
}
9392

9493
func Get[T any]() T {
95-
var t T
96-
return DefaultContainer.Get(reflect.TypeOf(t)).(T)
94+
var t *T
95+
96+
return DefaultContainer.Get(reflect.TypeOf(t).Elem()).(T)
9797
}
9898

9999
func Has[T any]() bool {
100-
var t T
101-
return DefaultContainer.Has(reflect.TypeOf(t))
100+
var t *T
101+
102+
return DefaultContainer.Has(reflect.TypeOf(t).Elem())
102103
}
103104

104105
func Make[T any]() T {
105-
var t T
106+
var t *T
106107

107-
return DefaultContainer.Make(reflect.TypeOf(t)).(T)
108+
return DefaultContainer.Make(reflect.TypeOf(t).Elem()).(T)
108109
}
109110

110111
func Register[T any](callback any) {
111-
var t T
112-
DefaultContainer.Register(reflect.TypeOf(t), callback)
112+
var t *T
113+
114+
DefaultContainer.Register(reflect.TypeOf(t).Elem(), callback)
113115
}
114116

115117
func RegisteredKeys() []string {
116118
return DefaultContainer.RegisteredKeys()
117119
}
118120

121+
func RegisterK(key string, callback any) {
122+
DefaultContainer.Register(key, callback)
123+
}
124+
125+
func SetK(key string, ins any) {
126+
DefaultContainer.Set(key, ins)
127+
}
128+
129+
func MakeK[T any](key string) T {
130+
return DefaultContainer.Make(key).(T)
131+
}
132+
133+
func GetK[T any](key string) T {
134+
return DefaultContainer.Get(key).(T)
135+
}
136+
119137
func Clear() {
120138
DefaultContainer.Clear()
121139
}
140+
141+
func AddFactory(factory Factory) {
142+
DefaultContainer.AddFactory(factory)
143+
}

container_test.go

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package container
22

33
import (
44
"fmt"
5-
"strings"
5+
"golang.org/x/exp/slices"
66
"testing"
77
)
88

@@ -18,6 +18,10 @@ type I interface {
1818
Key() string
1919
}
2020

21+
type II interface {
22+
Key() string
23+
}
24+
2125
func testSetup() {
2226
Clear()
2327
}
@@ -146,7 +150,7 @@ func TestNotRegister(t *testing.T) {
146150
defer func() {
147151
if err := recover(); err != nil {
148152
e := fmt.Sprintf("%s", err)
149-
if e != "reflect: New(nil)" {
153+
if e != "interface conversion: interface is nil, not container.I" {
150154
t.Error("test fail: " + e)
151155
}
152156
}
@@ -227,10 +231,66 @@ func TestRegisteredKeys(t *testing.T) {
227231
Name: "test_interface",
228232
}
229233
})
234+
keys := DefaultContainer.RegisteredKeys()
235+
236+
for _, s := range []string{"*container.Test", "container.Test", "*container.I"} {
237+
if !slices.Contains(keys, s) {
238+
t.Error("keys is not contain: " + s)
239+
}
240+
}
241+
}
242+
243+
func TestRegisterWithKey(t *testing.T) {
244+
testSetup()
245+
246+
SetK("test1", Test{
247+
Name: "set1",
248+
})
249+
k := GetK[Test]("test1")
250+
if k.Name != "set1" {
251+
t.Error("test fail")
252+
}
230253

231-
strings.Join(DefaultContainer.RegisteredKeys(), ",")
254+
RegisterK("test2", func() any {
255+
return Test{
256+
Name: "test_struct",
257+
}
258+
})
232259

233-
if strings.Join(DefaultContainer.RegisteredKeys(), ",") != "*container.Test,container.Test,*container.I" {
234-
t.Error("keys is not equal")
260+
v1 := MakeK[Test]("test2")
261+
if v1.Name != "test_struct" {
262+
t.Error("test fail")
263+
}
264+
}
265+
266+
func TestRegisterInterfaces(t *testing.T) {
267+
Set[I](Test{
268+
Name: "set1",
269+
})
270+
271+
Set[II](Test{
272+
Name: "set2",
273+
})
274+
275+
v1 := Get[I]()
276+
if v1.Key() != "set1" {
277+
t.Error("test fail")
278+
}
279+
280+
v2 := Get[II]()
281+
if v2.Key() != "set2" {
282+
t.Error("test fail")
283+
}
284+
}
285+
286+
func TestMakeRegistered(t *testing.T) {
287+
testSetup()
288+
Set[I](Test{
289+
Name: "set1",
290+
})
291+
292+
v1 := Make[I]()
293+
if v1.Key() != "set1" {
294+
t.Error("test fail")
235295
}
236296
}

factory.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package container
2+
3+
import "reflect"
4+
5+
type Factory interface {
6+
Resolvable(key any) bool
7+
Resolve(key any) any
8+
IsShared(key any) bool
9+
}
10+
11+
var DefaultFactoryInstance = DefaultFactory{}
12+
13+
type DefaultFactory struct {
14+
}
15+
16+
func (d DefaultFactory) Resolvable(key any) bool {
17+
return true
18+
}
19+
20+
func (d DefaultFactory) IsShared(key any) bool {
21+
return false
22+
}
23+
24+
func (d DefaultFactory) Resolve(key any) any {
25+
var typ reflect.Type
26+
27+
if of, ok := key.(reflect.Type); ok {
28+
typ = of
29+
} else {
30+
typ = reflect.TypeOf(key)
31+
}
32+
33+
if typ == nil {
34+
return nil
35+
}
36+
37+
if typ.Kind() == reflect.Ptr {
38+
return reflect.New(typ.Elem()).Interface()
39+
} else {
40+
return reflect.New(typ).Elem().Interface()
41+
}
42+
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/attson/container
22

33
go 1.19
4+
5+
require golang.org/x/exp v0.0.0-20231006140011-7918f672742d

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
2+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=

0 commit comments

Comments
 (0)