Skip to content

Supports injecting multiple same property fields #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"reflect"
)

const(
MAXPARANUMS uint8 = 10
)
// Injector represents an interface for mapping and injecting dependencies into structs
// and function arguments.
type Injector interface {
Expand All @@ -16,6 +19,7 @@ type Injector interface {
// dependency in its Type map it will check its parent before returning an
// error.
SetParent(Injector)
Reset()
}

// Applicator represents an interface for mapping dependencies to a struct.
Expand Down Expand Up @@ -53,7 +57,8 @@ type TypeMapper interface {
}

type injector struct {
values map[reflect.Type]reflect.Value
values map[reflect.Type][]reflect.Value
index map[reflect.Type]uint8
parent Injector
}

Expand All @@ -76,7 +81,8 @@ func InterfaceOf(value interface{}) reflect.Type {
// New returns a new Injector.
func New() Injector {
return &injector{
values: make(map[reflect.Type]reflect.Value),
values: make(map[reflect.Type][]reflect.Value),
index: make(map[reflect.Type]uint8),
}
}

Expand All @@ -92,6 +98,7 @@ func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
for i := 0; i < t.NumIn(); i++ {
argType := t.In(i)
val := inj.Get(argType)
inj.index[argType]++
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}
Expand Down Expand Up @@ -124,6 +131,7 @@ func (inj *injector) Apply(val interface{}) error {
if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
ft := f.Type()
v := inj.Get(ft)
inj.index[ft]++
if !v.IsValid() {
return fmt.Errorf("Value not found for type %v", ft)
}
Expand All @@ -139,35 +147,43 @@ func (inj *injector) Apply(val interface{}) error {
// Maps the concrete value of val to its dynamic type using reflect.TypeOf,
// It returns the TypeMapper registered in.
func (i *injector) Map(val interface{}) TypeMapper {
i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
i.Set(reflect.TypeOf(val), reflect.ValueOf(val))
return i
}

func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
i.Set(InterfaceOf(ifacePtr), reflect.ValueOf(val))
return i
}

// Maps the given reflect.Type to the given reflect.Value and returns
// the Typemapper the mapping has been registered in.
func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
i.values[typ] = val
if _,ok:=i.index[typ];!ok{
i.index[typ] = 0
i.values[typ] = make([]reflect.Value,0)
}
i.values[typ] = append(i.values[typ],val)
return i
}

func (i *injector) Get(t reflect.Type) reflect.Value {
val := i.values[t]
var val reflect.Value
if i.values[t] != nil {
val = i.values[t][i.index[t]]

if val.IsValid() {
return val
if val.IsValid() {
return val
}
}

// no concrete types found, try to find implementors
// if t is an interface
if t.Kind() == reflect.Interface {
for k, v := range i.values {
if k.Implements(t) {
val = v
val = v[i.index[t]]
fmt.Println(k,val)
break
}
}
Expand All @@ -179,9 +195,14 @@ func (i *injector) Get(t reflect.Type) reflect.Value {
}

return val

}

func (i *injector) SetParent(parent Injector) {
i.parent = parent
}

func (i *injector) Reset(){
for k,_:=range i.index{
i.index[k] = 0
}
}