From 5bd025099ffed5eddda11bbbbb080939b82e41e7 Mon Sep 17 00:00:00 2001 From: Cosmin Date: Wed, 5 Feb 2020 01:52:38 +0200 Subject: [PATCH] Apply to struct without connect --- container.go | 127 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 37 deletions(-) diff --git a/container.go b/container.go index d8df5f8..91cfdf9 100644 --- a/container.go +++ b/container.go @@ -57,41 +57,9 @@ func New() Container { } } -// Connect a component, optionally identified by id. -func (container Container) Connect(val interface{}, id ...string) { - ptr := false - rv := reflect.ValueOf(val) - rt := rv.Type() - nam := "" - _, file, no, _ := runtime.Caller(container.callerSkip + 1) - - if len(id) > 0 { - nam = id[0] - } - - comp := component{ - id: nam, - value: rv, - declaredAt: file + ":" + strconv.Itoa(no), - } - - if rt.Kind() == reflect.Ptr { - rt = rt.Elem() - rv = rv.Elem() - comp.value = rv - ptr = true - } - - if gr, ok := container.components[rt]; ok { - if comp, ok := gr.find(nam); ok { - panic(duplicateError{previous: comp}) - } - } +func dependinces(container Container, rt reflect.Type, rv reflect.Value) []dependency { - if rt.Kind() != reflect.Struct { - container.components[rt] = append(container.components[rt], comp) - return - } + dependinces := make([]dependency, 0) for i := 0; i < rt.NumField(); i++ { sf := rt.Field(i) @@ -121,15 +89,17 @@ func (container Container) Connect(val interface{}, id ...string) { impl = idAndImpl[1] } - comp.dependencies = append(comp.dependencies, dependency{ + dependinces = append(dependinces, dependency{ id: id, name: sf.Name, index: i, typ: depRt, impl: impl, }) + } else if (sf.Type.Kind() == reflect.Ptr || sf.Type.Kind() == reflect.Interface) && rv.Field(i).IsNil() { - panic(tagMissingError{field: sf}) + // Is this required + // panic(tagMissingError{field: sf}) } else if sf.Type.Kind() == reflect.Struct { // check forgotten tag only for struct. if _, exist := container.components[sf.Type]; exist { @@ -138,6 +108,47 @@ func (container Container) Connect(val interface{}, id ...string) { } } + return dependinces +} + +// Connect a component, optionally identified by id. +func (container Container) Connect(val interface{}, id ...string) { + ptr := false + rv := reflect.ValueOf(val) + rt := rv.Type() + nam := "" + _, file, no, _ := runtime.Caller(container.callerSkip + 1) + + if len(id) > 0 { + nam = id[0] + } + + comp := component{ + id: nam, + value: rv, + declaredAt: file + ":" + strconv.Itoa(no), + } + + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + rv = rv.Elem() + comp.value = rv + ptr = true + } + + if gr, ok := container.components[rt]; ok { + if comp, ok := gr.find(nam); ok { + panic(duplicateError{previous: comp}) + } + } + + if rt.Kind() != reflect.Struct { + container.components[rt] = append(container.components[rt], comp) + return + } + + comp.dependencies = dependinces(container, rt, rv) + if len(comp.dependencies) != 0 && !ptr { panic(incompletedError{}) } @@ -173,6 +184,18 @@ func (container Container) Resolve(out interface{}, id ...string) { panic(notAddressableError{id: nam, paramType: rt, component: comp}) } } else { + + if rt.Kind() == reflect.Interface { + for _, group := range container.components { + if v, e := group.find(nam); e { + if v.value.Addr().Type().Implements(rt) { + reflect.Indirect(rv).Set(v.value) + return + } + } + } + } + if gr, ok := container.components[rt]; ok { rv.Set(gr.get(nam).value) return @@ -183,7 +206,37 @@ func (container Container) Resolve(out interface{}, id ...string) { } // Apply wiring to all components. -func (container Container) Apply() { +func (container Container) Apply(to ...interface{}) { + + if len(to) > 0 { + + rv := reflect.ValueOf(to[0]) + rt := rv.Type() + _, file, no, _ := runtime.Caller(container.callerSkip + 1) + + comp := component{ + id: "", + value: rv, + declaredAt: file + ":" + strconv.Itoa(no), + } + + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + rv = rv.Elem() + comp.value = rv + } + + comp.dependencies = dependinces( + container, + rt, + rv, + ) + + container.fill(comp) + + return + } + for _, gr := range container.components { for _, comp := range gr { container.fill(comp)