Tsukikage7 commented on code in PR #3154:
URL: https://github.com/apache/dubbo-go/pull/3154#discussion_r2693330585


##########
protocol/triple/server.go:
##########
@@ -503,51 +503,101 @@ func createServiceInfoWithReflection(svc 
common.RPCService) *common.ServiceInfo
                if methodType.Name == "Reference" {
                        continue
                }
-               paramsNum := methodType.Type.NumIn()
-               // the first param is receiver itself, the second param is ctx
-               // just ignore them
-               if paramsNum < 2 {
-                       logger.Fatalf("TRIPLE does not support %s method that 
does not have any parameter", methodType.Name)
-                       continue
-               }
-               paramsTypes := make([]reflect.Type, paramsNum-2)
-               for j := 2; j < paramsNum; j++ {
-                       paramsTypes[j-2] = methodType.Type.In(j)
-               }
-               methodInfo := common.MethodInfo{
-                       Name: methodType.Name,
-                       // only support Unary invocation now
-                       Type: constant.CallUnary,
-                       ReqInitFunc: func() any {
-                               params := make([]any, len(paramsTypes))
-                               for k, paramType := range paramsTypes {
-                                       params[k] = 
reflect.New(paramType).Interface()
-                               }
-                               return params
-                       },
+               methodInfo := buildMethodInfoWithReflection(methodType)
+               if methodInfo != nil {
+                       methodInfos = append(methodInfos, *methodInfo)
                }
-               methodInfos = append(methodInfos, methodInfo)
        }
 
-       // only support no-idl mod call unary
-       genericMethodInfo := common.MethodInfo{
-               Name: "$invoke",
-               Type: constant.CallUnary,
+       // Add $invoke method for generic call support
+       methodInfos = append(methodInfos, buildGenericMethodInfo())
+
+       info.Methods = methodInfos
+       return &info
+}
+
+// buildMethodInfoWithReflection creates MethodInfo for a single method using 
reflection.
+func buildMethodInfoWithReflection(methodType reflect.Method) 
*common.MethodInfo {
+       paramsNum := methodType.Type.NumIn()
+       // the first param is receiver itself, the second param is ctx
+       if paramsNum < 2 {
+               logger.Fatalf("TRIPLE does not support %s method that does not 
have any parameter", methodType.Name)
+               return nil
+       }
+
+       // Extract parameter types (skip receiver and context)
+       paramsTypes := make([]reflect.Type, paramsNum-2)
+       for j := 2; j < paramsNum; j++ {
+               paramsTypes[j-2] = methodType.Type.In(j)
+       }
+
+       // Capture method for closure
+       method := methodType
+       return &common.MethodInfo{
+               Name: methodType.Name,
+               Type: constant.CallUnary, // only support Unary invocation now
                ReqInitFunc: func() any {
-                       params := make([]any, 3)
-                       // params must be pointer
-                       params[0] = func(s string) *string { return &s 
}("methodName") // methodName *string
-                       params[1] = &[]string{}                                 
       // argv type  *[]string
-                       params[2] = &[]hessian.Object{}                         
       // argv       *[]hessian.Object
+                       params := make([]any, len(paramsTypes))
+                       for k, paramType := range paramsTypes {
+                               params[k] = reflect.New(paramType).Interface()
+                       }
                        return params
                },
+               MethodFunc: func(ctx context.Context, args []any, handler any) 
(any, error) {
+                       in := []reflect.Value{reflect.ValueOf(handler)}
+                       in = append(in, reflect.ValueOf(ctx))
+                       for _, arg := range args {
+                               in = append(in, reflect.ValueOf(arg))
+                       }
+                       returnValues := method.Func.Call(in)
+                       if len(returnValues) == 1 {
+                               if isReflectValueNil(returnValues[0]) {
+                                       return nil, nil
+                               }
+                               if err, ok := 
returnValues[0].Interface().(error); ok {
+                                       return nil, err
+                               }
+                               return nil, nil
+                       }
+                       var result any
+                       var err error
+                       if !isReflectValueNil(returnValues[0]) {
+                               result = returnValues[0].Interface()
+                       }
+                       if len(returnValues) > 1 && 
!isReflectValueNil(returnValues[1]) {
+                               if e, ok := 
returnValues[1].Interface().(error); ok {
+                                       err = e
+                               }
+                       }
+                       return result, err
+               },
        }
+}
 
-       methodInfos = append(methodInfos, genericMethodInfo)
-
-       info.Methods = methodInfos
+// buildGenericMethodInfo creates MethodInfo for $invoke generic call method.
+func buildGenericMethodInfo() common.MethodInfo {
+       return common.MethodInfo{
+               Name: constant.Generic,
+               Type: constant.CallUnary,
+               ReqInitFunc: func() any {
+                       return []any{
+                               func(s string) *string { return &s }(""), // 
methodName *string
+                               &[]string{},                              // 
types *[]string
+                               &[]hessian.Object{},                      // 
args *[]hessian.Object
+                       }
+               },
+       }
+}
 
-       return &info
+// isReflectValueNil safely checks if a reflect.Value is nil.
+// It first checks if the value's kind supports nil checking to avoid panic.
+func isReflectValueNil(v reflect.Value) bool {

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to