package rpc import ( "errors" "fmt" "reflect" ) var errorType = reflect.TypeOf((*error)(nil)).Elem() func getFullName(t reflect.Type) string { if "" == t.PkgPath() { return t.Name() } else { return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()) } } type MethodInvokerBuilder struct { valueParserBuilder *ValueParserBuilder presetTypes map[reflect.Type]valueParser } func (builder *MethodInvokerBuilder) checkOutType(parameterType reflect.Type) (bool, string) { switch parameterType.Kind() { case reflect.Invalid: return false, parameterType.Name() case reflect.Bool: return true, parameterType.Name() case reflect.Int: return true, parameterType.Name() case reflect.Int8: return true, parameterType.Name() case reflect.Int16: return true, parameterType.Name() case reflect.Int32: return true, parameterType.Name() case reflect.Int64: return true, parameterType.Name() case reflect.Uint: return true, parameterType.Name() case reflect.Uint8: return true, parameterType.Name() case reflect.Uint16: return true, parameterType.Name() case reflect.Uint32: return true, parameterType.Name() case reflect.Uint64: return true, parameterType.Name() case reflect.Uintptr: return false, parameterType.Name() case reflect.Float32: return true, parameterType.Name() case reflect.Float64: return true, parameterType.Name() case reflect.Complex64: return false, parameterType.Name() case reflect.Complex128: return false, parameterType.Name() case reflect.Array: if ok, typeText := builder.checkOutType(parameterType.Elem()); ok { return true, fmt.Sprintf("[%d]%s", parameterType.Len(), typeText) } else { return false, fmt.Sprintf("[%d]%s", parameterType.Len(), typeText) } case reflect.Chan: return false, parameterType.Name() case reflect.Func: return false, parameterType.Name() case reflect.Interface: return true, getFullName(parameterType) case reflect.Map: keyOk, keyTypeText := builder.checkOutType(parameterType.Key()) valueOk, valueTypeText := builder.checkOutType(parameterType.Elem()) if keyOk && valueOk { return true, fmt.Sprintf("*map[%s]%s", keyTypeText, valueTypeText) } else { return false, fmt.Sprintf("*map[%s]%s", keyTypeText, valueTypeText) } case reflect.Ptr: if ok, typeText := builder.checkOutType(parameterType.Elem()); ok { return true, fmt.Sprintf("*%s", typeText) } else { return false, fmt.Sprintf("*%s", typeText) } case reflect.Slice: if ok, typeText := builder.checkOutType(parameterType.Elem()); ok { return true, fmt.Sprintf("[]%s", typeText) } else { return false, fmt.Sprintf("[]%s", typeText) } case reflect.String: return true, parameterType.Name() case reflect.Struct: return true, getFullName(parameterType) case reflect.UnsafePointer: return false, parameterType.Name() default: return false, "Unknown" } } func (builder *MethodInvokerBuilder) buildParameterParser(serviceName string, parameterType reflect.Type, parameterIndex int) (valueParser, error) { if presetParameterParser, ok := builder.presetTypes[parameterType]; ok { return presetParameterParser, nil } else if parameterParser, err := builder.valueParserBuilder.Build(fmt.Sprintf("%s-in#%d", serviceName, parameterIndex), parameterType); err != nil { return nil, err } else { return parameterParser, nil } } func (builder *MethodInvokerBuilder) buildParameterParsers(serviceMethodName string, methodType reflect.Type) ([]valueParser, error) { if methodType.NumOut() < 1 || 2 < methodType.NumOut() { return nil, errors.New(fmt.Sprintf("返回值数量错误! Service: %s 返回值数量: %d", serviceMethodName, methodType.NumOut())) } if methodType.Out(methodType.NumOut()-1) != errorType { return nil, errors.New(fmt.Sprintf("最后一个返回值类型错误! Service: %s 类型:%s", serviceMethodName, methodType.Out(methodType.NumOut()-1))) } for i := 0; i < methodType.NumOut(); i++ { if ok, typeText := builder.checkOutType(methodType.Out(i)); !ok { return nil, errors.New(fmt.Sprintf("不支持的返回值类型! Service: %s 参数: #%d 类型: %s", serviceMethodName, i+1, typeText)) } } parameterParsers := make([]valueParser, 0, 10) for i := 0; i < methodType.NumIn(); i++ { if parameterParser, err := builder.buildParameterParser(serviceMethodName, methodType.In(i), i); err != nil { return nil, err } else { parameterParsers = append(parameterParsers, parameterParser) } } return parameterParsers, nil } func (builder *MethodInvokerBuilder) buildMethodInvoker(serviceName string, methodType reflect.Type, call func([]reflect.Value) []reflect.Value) (*MethodInvoker, error) { parameterParsers, err := builder.buildParameterParsers(serviceName, methodType) if err != nil { return nil, err } return NewMethodInvoker(call, parameterParsers), nil }