in proxy/proxy.go [233:283]
func refectAndMakeObjectFunc(valueOfElem reflect.Value, makeDubboCallProxy func(methodName string, outs []reflect.Type) func(in []reflect.Value) []reflect.Value) error {
typeOf := valueOfElem.Type()
// check incoming interface, incoming interface's elem must be a struct.
if typeOf.Kind() != reflect.Struct {
return errors.New("invalid type kind")
}
numField := valueOfElem.NumField()
for i := 0; i < numField; i++ {
t := typeOf.Field(i)
methodName := t.Tag.Get("dubbo")
if methodName == "" {
methodName = t.Name
}
f := valueOfElem.Field(i)
if f.Kind() == reflect.Func && f.IsValid() && f.CanSet() {
outNum := t.Type.NumOut()
if outNum != 1 && outNum != 2 {
logger.Warnf("method %s of mtype %v has wrong number of in out parameters %d; needs exactly 1/2",
t.Name, t.Type.String(), outNum)
continue
}
// The latest return type of the method must be error.
if returnType := t.Type.Out(outNum - 1); returnType != typError {
logger.Warnf("the latest return type %s of method %q is not error", returnType, t.Name)
continue
}
funcOuts := make([]reflect.Type, outNum)
for i := 0; i < outNum; i++ {
funcOuts[i] = t.Type.Out(i)
}
// do method proxy here:
f.Set(reflect.MakeFunc(f.Type(), makeDubboCallProxy(methodName, funcOuts)))
logger.Debugf("set method [%s]", methodName)
} else if f.IsValid() && f.CanSet() {
// for struct combination
valueOfSub := reflect.New(t.Type)
valueOfElemInterface := valueOfSub.Elem()
if valueOfElemInterface.Type().Kind() == reflect.Struct {
if err := refectAndMakeObjectFunc(valueOfElemInterface, makeDubboCallProxy); err != nil {
return err
}
f.Set(valueOfElemInterface)
}
}
}
return nil
}