func (i *inject) IntoMethod(object interface{}, m interface{}) (retVal interface{}, err error) {
	if object != nil && m != nil {
		switch m.(type) {
		case reflect.Method:
			method := m.(reflect.Method)
			numIn := method.Type.NumIn()
			inputs := make([]reflect.Value, numIn)
			inputs[0] = reflect.ValueOf(object)
			for n := 1; n < numIn; n++ {
				fnInType := method.Type.In(n)
				val, ok := i.parseFuncOrMethodInput(fnInType)
				if ok {
					inputs[n] = val
				} else {
					return nil, fmt.Errorf("%v is not injected", fnInType.Name())
				}
				paramObject := reflect.Indirect(val)
				if val.IsValid() && paramObject.IsValid() && paramObject.Kind() == reflect.Struct {
					err = i.IntoObject(val.Interface())
				}
			}
			results := method.Func.Call(inputs)
			if len(results) != 0 {
				retVal = results[0].Interface()
				return
			}
		}
	}
	err = ErrInvalidMethod
	return
}
IntoMethod inject object into func and return instance
TODO: IntoMethod or IntoFunc should accept metaData, because it contains dependencies
package inject
import (
	"errors"
	"fmt"
	"hidevops.io/hiboot/pkg/at"
	"hidevops.io/hiboot/pkg/factory"
	"hidevops.io/hiboot/pkg/inject/annotation"
	"hidevops.io/hiboot/pkg/log"
	"hidevops.io/hiboot/pkg/utils/reflector"
	"hidevops.io/hiboot/pkg/utils/str"
	"reflect"
	"strings"
)
const (
	value          = "value"
)
var (
	ErrNotImplemented = errors.New("[inject] interface is not implemented")
	ErrInvalidObject = errors.New("[inject] invalid object")
	ErrInvalidTagName = errors.New("[inject] invalid tag name, e.g. exampleTag")
	ErrSystemConfiguration = errors.New("[inject] system is not configured")
	ErrInvalidFunc = errors.New("[inject] invalid func")
	ErrInvalidMethod = errors.New("[inject] invalid method")
	ErrFactoryIsNil = errors.New("[inject] factory is nil")
	ErrAnnotationsIsNil = fmt.Errorf("err: annotations is nil")
	tagsContainer []Tag
)
type Inject interface {
	DefaultValue(object interface{}) error
	IntoObject(object interface{}) error
	IntoObjectValue(object reflect.Value, property string, tags ...Tag) error
	IntoMethod(object interface{}, m interface{}) (retVal interface{}, err error)
	IntoFunc(object interface{}) (retVal interface{}, err error)
	IntoAnnotations(annotations *annotation.Annotations) (err error)
}
type inject struct {
	factory factory.InstantiateFactory
}
func NewInject(factory factory.InstantiateFactory) Inject {
	return &inject{factory: factory}
}
func InitTag(tag Tag) (t Tag) {
	if annotation.Contains(tag, at.Tag{}) {
		err := annotation.InjectAll(tag)
		if err == nil {
			t = tag
		}
	}
	return
}
func AddTag(tag Tag) {
	if tag != nil {
		t := InitTag(tag)
		if t != nil {
			tagsContainer = append(tagsContainer, t)
		}
	}
}
func (i *inject) getInstance(typ reflect.Type) (inst interface{}) {
	n := reflector.GetLowerCamelFullNameByType(typ)
	inst = i.factory.GetInstance(n)
	return
}
func (i *inject) DefaultValue(object interface{}) error {
	return i.IntoObjectValue(reflect.ValueOf(object), "", InitTag(new(defaultTag)))
}
func (i *inject) IntoAnnotations(annotations *annotation.Annotations) (err error) {
	if annotations == nil {
		err = ErrAnnotationsIsNil
		return
	}
	for _, a := range annotations.Items {
		err = annotation.Inject(a)
		if err == nil {
			err = i.IntoObjectValue(a.Field.Value.Addr(), "")
		}
	}
	for _, c := range annotations.Children {
		err = i.IntoAnnotations(c)
	}
	return
}
func (i *inject) IntoObject(object interface{}) (err error) {
	err = i.IntoObjectValue(reflect.ValueOf(object), "")
	if err == nil {
		annotations := annotation.GetAnnotations(object)
		err = i.IntoAnnotations(annotations)
	}
	return
}
func (i *inject) convert(f reflect.StructField, src interface{}) (fov reflect.Value) {
	fov = reflect.ValueOf(src)
	switch src.(type) {
	case []interface{}:
		switch f.Type.Elem().Kind() {
		case reflect.String:
			var sv []string
			src := src.([]interface{})
			for _, elm := range src {
				sv = append(sv, elm.(string))
			}
			fov = reflect.ValueOf(sv)
		}
	}
	return
}
func (i *inject) IntoObjectValue(object reflect.Value, property string, tags ...Tag) error {
	var err error
	obj := reflector.Indirect(object)
	if obj.Kind() != reflect.Struct {
		log.Debugf("[inject] ignore object: %v, kind: %v", object, obj.Kind())
		return ErrInvalidObject
	}
	var targetTags []Tag
	if len(tags) != 0 {
		targetTags = tags
	} else {
		targetTags = tagsContainer
	}
	for _, f := range reflector.DeepFields(object.Type()) {
		var injectedObject interface{}
		var prop string
		pn, ok := f.Tag.Lookup("json")
		if ok {
			pns := strings.Split(pn, ",")
			if len(pns) > 1 {
				prop = pns[0]
			}
		} else {
			prop = str.ToLowerCamel(f.Name)
		}
		if property != "" {
			prop = property + "." + prop
		}
		ft := f.Type
		if f.Type.Kind() == reflect.Ptr {
			ft = ft.Elem()
		}
		var fieldObjValue reflect.Value
		if obj.IsValid() && obj.Kind() == reflect.Struct {
			fieldObjValue = obj.FieldByName(f.Name)
		}
		injectedObject = i.getInstance(f.Type)
		if injectedObject == nil {
			for _, tagImpl := range targetTags {
				tagImpl.Init(i.factory)
				injectedObject = tagImpl.Decode(object, f, prop)
				if injectedObject != nil {
					break
				}
			}
		}
		if injectedObject != nil && fieldObjValue.CanSet() {
			fov := i.convert(f, injectedObject)
			if fov.Type().AssignableTo(fieldObjValue.Type()) {
				fieldObjValue.Set(fov)
			}
		}
		filedObject := reflect.Indirect(fieldObjValue)
		filedKind := filedObject.Kind()
		canNested := filedKind == reflect.Struct
		if canNested && fieldObjValue.IsValid() && fieldObjValue.CanSet() && filedObject.Type() != obj.Type() {
			err = i.IntoObjectValue(fieldObjValue, prop, tags...)
		}
	}
	if atFields := annotation.FindAll(object, at.ConfigurationProperties{}); len(atFields) > 0 {
		obj := object.Interface()
		err = i.factory.Builder().Load(obj)
	}
	return err
}
func (i *inject) parseFuncOrMethodInput(inType reflect.Type) (paramValue reflect.Value, ok bool) {
	inType = reflector.IndirectType(inType)
	inst := i.getInstance(inType)
	ok = true
	if inst == nil {
		switch inType.Kind() {
		case reflect.Interface, reflect.Slice:
			ok = false
			break
		default:
			paramValue = reflect.New(inType)
			inst = paramValue.Interface()
			i.factory.SetInstance(inst)
		}
	}
	if inst != nil {
		paramValue = reflect.ValueOf(inst)
	}
	return
}
func (i *inject) IntoFunc(object interface{}) (retVal interface{}, err error) {
	fn := reflect.ValueOf(object)
	if fn.Kind() == reflect.Func {
		numIn := fn.Type().NumIn()
		inputs := make([]reflect.Value, numIn)
		for n := 0; n < numIn; n++ {
			fnInType := fn.Type().In(n)
			val, ok := i.parseFuncOrMethodInput(fnInType)
			if ok {
				inputs[n] = val
			} else {
				return nil, fmt.Errorf("%v is not injected", fnInType.Name())
			}
			paramValue := reflect.Indirect(val)
			if val.IsValid() && paramValue.IsValid() && paramValue.Kind() == reflect.Struct {
				err = i.IntoObject(val.Interface())
			}
		}
		results := fn.Call(inputs)
		if len(results) != 0 {
			retVal = results[0].Interface()
			return
		}
		return
	}
	err = ErrInvalidFunc
	return
}