123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- package inject
- import (
- "fmt"
- "reflect"
- )
- type Injector interface {
- Applicator
- Invoker
- TypeMapper
-
-
-
- SetParent(Injector)
- }
- type Applicator interface {
-
-
-
- Apply(interface{}) error
- }
- type Invoker interface {
-
-
-
-
- Invoke(interface{}) ([]reflect.Value, error)
- }
- type FastInvoker interface {
-
-
-
-
- Invoke([]interface{}) ([]reflect.Value, error)
- }
- func IsFastInvoker(h interface{}) bool {
- _, ok := h.(FastInvoker)
- return ok
- }
- type TypeMapper interface {
-
- Map(interface{}) TypeMapper
-
-
-
- MapTo(interface{}, interface{}) TypeMapper
-
-
-
- Set(reflect.Type, reflect.Value) TypeMapper
-
-
- GetVal(reflect.Type) reflect.Value
- }
- type injector struct {
- values map[reflect.Type]reflect.Value
- parent Injector
- }
- func InterfaceOf(value interface{}) reflect.Type {
- t := reflect.TypeOf(value)
- for t.Kind() == reflect.Ptr {
- t = t.Elem()
- }
- if t.Kind() != reflect.Interface {
- panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
- }
- return t
- }
- func New() Injector {
- return &injector{
- values: make(map[reflect.Type]reflect.Value),
- }
- }
- func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
- t := reflect.TypeOf(f)
- switch v := f.(type) {
- case FastInvoker:
- return inj.fastInvoke(v, t, t.NumIn())
- default:
- return inj.callInvoke(f, t, t.NumIn())
- }
- }
- func (inj *injector) fastInvoke(f FastInvoker, t reflect.Type, numIn int) ([]reflect.Value, error) {
- var in []interface{}
- if numIn > 0 {
- in = make([]interface{}, numIn)
- var argType reflect.Type
- var val reflect.Value
- for i := 0; i < numIn; i++ {
- argType = t.In(i)
- val = inj.GetVal(argType)
- if !val.IsValid() {
- return nil, fmt.Errorf("Value not found for type %v", argType)
- }
- in[i] = val.Interface()
- }
- }
- return f.Invoke(in)
- }
- func (inj *injector) callInvoke(f interface{}, t reflect.Type, numIn int) ([]reflect.Value, error) {
- var in []reflect.Value
- if numIn > 0 {
- in = make([]reflect.Value, numIn)
- var argType reflect.Type
- var val reflect.Value
- for i := 0; i < numIn; i++ {
- argType = t.In(i)
- val = inj.GetVal(argType)
- if !val.IsValid() {
- return nil, fmt.Errorf("Value not found for type %v", argType)
- }
- in[i] = val
- }
- }
- return reflect.ValueOf(f).Call(in), nil
- }
- func (inj *injector) Apply(val interface{}) error {
- v := reflect.ValueOf(val)
- for v.Kind() == reflect.Ptr {
- v = v.Elem()
- }
- if v.Kind() != reflect.Struct {
- return nil
- }
- t := v.Type()
- for i := 0; i < v.NumField(); i++ {
- f := v.Field(i)
- structField := t.Field(i)
- if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
- ft := f.Type()
- v := inj.GetVal(ft)
- if !v.IsValid() {
- return fmt.Errorf("Value not found for type %v", ft)
- }
- f.Set(v)
- }
- }
- return nil
- }
- func (i *injector) Map(val interface{}) TypeMapper {
- i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
- return i
- }
- func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
- i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
- return i
- }
- func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
- i.values[typ] = val
- return i
- }
- func (i *injector) GetVal(t reflect.Type) reflect.Value {
- val := i.values[t]
- if val.IsValid() {
- return val
- }
-
-
- if t.Kind() == reflect.Interface {
- for k, v := range i.values {
- if k.Implements(t) {
- val = v
- break
- }
- }
- }
-
- if !val.IsValid() && i.parent != nil {
- val = i.parent.GetVal(t)
- }
- return val
- }
- func (i *injector) SetParent(parent Injector) {
- i.parent = parent
- }
|