Skip to content

Commit e52c623

Browse files
committed
ref: Reestructured, refactored and splitted code
1 parent 1f1700c commit e52c623

14 files changed

+419
-158
lines changed

.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"remotePath": "",
1010
"port": 2345,
1111
"host": "127.0.0.1",
12-
"program": "${workspaceRoot}/main.go",
12+
"program": "${workspaceRoot}/test/main.go",
1313
"env": {},
1414
"args": [],
1515
"showLog": true

container/container.go

-146
This file was deleted.

container/container_test.go

-1
This file was deleted.

injector.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package gocodi
2+
3+
import (
4+
"github.com/xxxtonixxx/gocodi/injector"
5+
"github.com/xxxtonixxx/gocodi/provider"
6+
)
7+
8+
var mainInjector = injector.New()
9+
10+
func Provide(provider *provider.Provider) error {
11+
return mainInjector.Provide(provider)
12+
}
13+
14+
func Get(token interface{}) interface{} {
15+
return mainInjector.Get(token)
16+
}
17+
18+
func New() *injector.Injector {
19+
return injector.NewWithParent(mainInjector)
20+
}

injector/injector.go

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package injector
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
7+
"github.com/xxxtonixxx/gocodi/provider"
8+
"github.com/xxxtonixxx/gocodi/providers"
9+
"github.com/xxxtonixxx/gocodi/tokens"
10+
"github.com/xxxtonixxx/gocodi/utils"
11+
)
12+
13+
type Injector struct {
14+
deps []providers.Provider
15+
parent *Injector
16+
}
17+
18+
// NewChildInjector() *Injector
19+
func (injector *Injector) Provide(provider *provider.Provider) error {
20+
if provider.Provide == nil {
21+
return fmt.Errorf("You must set a kind of Provider and its use(Value/Factory)/aliasOf")
22+
}
23+
24+
var newProvider providers.Provider
25+
token := tokens.New(provider.Provide)
26+
27+
switch token.GetType() {
28+
case tokens.Interface:
29+
if provider.UseValue == nil && provider.UseFactory == nil {
30+
return fmt.Errorf("You must provide a value or factory when token is %s", reflect.TypeOf(provider.Provide))
31+
}
32+
33+
if !utils.ImplementsInterface(provider.Provide, provider.UseValue) {
34+
return fmt.Errorf(
35+
"%s does not implements %s",
36+
reflect.TypeOf(provider.UseValue),
37+
reflect.TypeOf(provider.Provide),
38+
)
39+
}
40+
41+
newProvider = &providers.Interface{
42+
Token: token,
43+
Value: provider.UseValue,
44+
}
45+
case tokens.PtrStruct, tokens.Struct:
46+
// if provider.UseValue != nil {
47+
// if !utils.IsPtrToStruct(provider.UseValue) && !utils.IsStruct(provider.UseValue) {
48+
// return fmt.Errorf("When provide an struct or pointer to one, you must return an struct of same type")
49+
// }
50+
// } else if provider.UseFactory != nil {
51+
52+
// } else {
53+
// return fmt.Errorf(`
54+
// If you provide a struct or pointer to one,
55+
// you must set UseValue or UseFactory
56+
// `)
57+
// }
58+
if provider.UseValue != nil &&
59+
(!utils.IsPtrToStruct(provider.UseValue) || !utils.IsStruct(provider.UseValue)) {
60+
return fmt.Errorf("If you provide a struct, the value must be a struct")
61+
}
62+
63+
newProvider = &providers.Struct{
64+
Token: token,
65+
Value: provider.UseValue,
66+
IsCreated: provider.UseValue != nil,
67+
}
68+
case tokens.String:
69+
if provider.UseValue == nil && provider.UseFactory == nil {
70+
return fmt.Errorf("You must provide a value or factory when token is %s", reflect.TypeOf(provider.Provide))
71+
}
72+
73+
newProvider = &providers.Primitive{
74+
Token: token,
75+
Value: provider.UseValue,
76+
}
77+
}
78+
79+
injector.deps = append(injector.deps, newProvider)
80+
81+
return nil
82+
}
83+
84+
func (injector *Injector) Get(token interface{}) interface{} {
85+
for _, dep := range injector.deps {
86+
if dep.Match(token) {
87+
value := dep.GetValue()
88+
89+
tokenType := dep.GetToken().GetType()
90+
switch tokenType {
91+
case tokens.Struct:
92+
typeOf := reflect.TypeOf(dep.GetToken().Get())
93+
valueOf := reflect.ValueOf(value)
94+
95+
injector.deepInit(typeOf, valueOf)
96+
case tokens.PtrStruct:
97+
typeOf := reflect.TypeOf(dep.GetToken().Get()).Elem()
98+
valueOf := reflect.ValueOf(value).Elem()
99+
100+
injector.deepInit(typeOf, valueOf)
101+
}
102+
103+
return value
104+
}
105+
}
106+
107+
return nil
108+
}
109+
110+
func (injector *Injector) deepInit(typeOf reflect.Type, valueOf reflect.Value) {
111+
for i := 0; i < valueOf.NumField(); i++ {
112+
fieldValue := valueOf.Field(i)
113+
fieldType := typeOf.Field(i)
114+
tags := fieldType.Tag.Get("gocodi")
115+
116+
if !fieldValue.CanSet() || tags == "-" {
117+
continue
118+
}
119+
120+
var dep interface{}
121+
switch fieldType.Type.Kind() {
122+
case reflect.Interface:
123+
token := reflect.New(fieldType.Type).Interface()
124+
dep = injector.Get(token)
125+
case reflect.Struct:
126+
dep = injector.Get(fieldType.Type)
127+
case reflect.Ptr:
128+
if tags == "" {
129+
token := reflect.New(fieldType.Type.Elem()).Interface()
130+
dep = injector.Get(token)
131+
} else {
132+
dep = injector.Get(tags)
133+
}
134+
default:
135+
if tags != "" {
136+
dep = injector.Get(tags)
137+
}
138+
}
139+
140+
if reflect.ValueOf(dep).IsValid() {
141+
fieldValue.Set(reflect.ValueOf(dep))
142+
} else {
143+
panic(fmt.Errorf(
144+
"%s can not be provided as dependency when resolved %s",
145+
fieldType.Type,
146+
typeOf,
147+
))
148+
}
149+
}
150+
}
151+
152+
func New() *Injector {
153+
return &Injector{
154+
deps: make([]providers.Provider, 0),
155+
}
156+
}
157+
158+
func NewWithParent(parent *Injector) *Injector {
159+
return &Injector{
160+
parent: parent,
161+
deps: make([]providers.Provider, 0),
162+
}
163+
}

injector/injector_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package injector

provider/provider.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package provider
2+
3+
type Provider struct {
4+
Provide interface{}
5+
UseValue interface{}
6+
UseFactory interface{}
7+
deps []interface{}
8+
aliasOf interface{}
9+
}

providers/interface.provider.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package providers
2+
3+
import (
4+
"github.com/xxxtonixxx/gocodi/tokens"
5+
)
6+
7+
type Interface struct {
8+
Token *tokens.Token
9+
Value interface{}
10+
IsFactory bool
11+
}
12+
13+
func (provider *Interface) GetValue() interface{} {
14+
if provider.IsFactory {
15+
// fmt.Println("Is factory")
16+
}
17+
18+
return provider.Value
19+
}
20+
21+
func (provider *Interface) GetToken() *tokens.Token {
22+
return provider.Token
23+
}
24+
25+
func (provider *Interface) Match(token interface{}) bool {
26+
return provider.Token.Match(tokens.New(token))
27+
}

0 commit comments

Comments
 (0)