// Copyright 2013 Jeremy Saenz // Copyright 2015 The Macaron Authors // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. // Package inject provides utilities for mapping and injecting dependencies in various ways. package inject import ( "fmt" "reflect" ) // Injector represents an interface for mapping and injecting dependencies into structs // and function arguments. type Injector interface { Applicator Invoker TypeMapper // SetParent sets the parent of the injector. If the injector cannot find a // dependency in its Type map it will check its parent before returning an // error. SetParent(Injector) } // Applicator represents an interface for mapping dependencies to a struct. type Applicator interface { // Maps dependencies in the Type map to each field in the struct // that is tagged with 'inject'. Returns an error if the injection // fails. Apply(interface{}) error } // Invoker represents an interface for calling functions via reflection. type Invoker interface { // Invoke attempts to call the interface{} provided as a function, // providing dependencies for function arguments based on Type. Returns // a slice of reflect.Value representing the returned values of the function. // Returns an error if the injection fails. Invoke(interface{}) ([]reflect.Value, error) } // FastInvoker represents an interface in order to avoid the calling function via reflection. // // example: // type handlerFuncHandler func(http.ResponseWriter, *http.Request) error // func (f handlerFuncHandler)Invoke([]interface{}) ([]reflect.Value, error){ // ret := f(p[0].(http.ResponseWriter), p[1].(*http.Request)) // return []reflect.Value{reflect.ValueOf(ret)}, nil // } // // type funcHandler func(int, string) // func (f funcHandler)Invoke([]interface{}) ([]reflect.Value, error){ // f(p[0].(int), p[1].(string)) // return nil, nil // } type FastInvoker interface { // Invoke attempts to call the ordinary functions. If f is a function // with the appropriate signature, f.Invoke([]interface{}) is a Call that calls f. // Returns a slice of reflect.Value representing the returned values of the function. // Returns an error if the injection fails. Invoke([]interface{}) ([]reflect.Value, error) } // IsFastInvoker check interface is FastInvoker func IsFastInvoker(h interface{}) bool { _, ok := h.(FastInvoker) return ok } // TypeMapper represents an interface for mapping interface{} values based on type. type TypeMapper interface { // Maps the interface{} value based on its immediate type from reflect.TypeOf. Map(interface{}) TypeMapper // Maps the interface{} value based on the pointer of an Interface provided. // This is really only useful for mapping a value as an interface, as interfaces // cannot at this time be referenced directly without a pointer. MapTo(interface{}, interface{}) TypeMapper // Provides a possibility to directly insert a mapping based on type and value. // This makes it possible to directly map type arguments not possible to instantiate // with reflect like unidirectional channels. Set(reflect.Type, reflect.Value) TypeMapper // Returns the Value that is mapped to the current type. Returns a zeroed Value if // the Type has not been mapped. GetVal(reflect.Type) reflect.Value } type injector struct { values map[reflect.Type]reflect.Value parent Injector } // InterfaceOf dereferences a pointer to an Interface type. // It panics if value is not an pointer to an interface. 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 } // New returns a new Injector. func New() Injector { return &injector{ values: make(map[reflect.Type]reflect.Value), } } // Invoke attempts to call the interface{} provided as a function, // providing dependencies for function arguments based on Type. // Returns a slice of reflect.Value representing the returned values of the function. // Returns an error if the injection fails. // It panics if f is not a function 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) // Panic if t is not kind of Func 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) } // callInvoke reflect.Value.Call 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 } // Maps dependencies in the Type map to each field in the struct // that is tagged with 'inject'. // Returns an error if the injection fails. 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 // Should not panic here ? } 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 } // 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) return i } func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper { i.values[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 return i } func (i *injector) GetVal(t reflect.Type) reflect.Value { val := i.values[t] 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 break } } } // Still no type found, try to look it up on the parent if !val.IsValid() && i.parent != nil { val = i.parent.GetVal(t) } return val } func (i *injector) SetParent(parent Injector) { i.parent = parent }