TRttiMethod.Invoke function doesn't work in overloaded methods?

后端 未结 1 553
情深已故
情深已故 2020-12-18 04:57

I\'m creating an instance of a class using the TRttiMethod.Invoke function , but when the constructor or a method is overloaded, the rtti does not call the proper method.

相关标签:
1条回答
  • 2020-12-18 05:43

    There is nothing wrong with the TRttiMethod.Invoke method, your issue is located in the GetMethod. This function internally call to the TRttiType.GetMethods and retrieves a pointer to the first method which match with the name passed as parameter. So when you are executing this code t.GetMethod('Create') you always are getting a pointer to the same method.

    To execute an overloaded version of the constructor or another method you must resolve the method address to execute based in the parameters, and then call the TRttiMethod.Invoke function.

    Check this sample function.

    function RttiMethodInvokeEx(const MethodName:string; RttiType : TRttiType; Instance: TValue; const Args: array of TValue): TValue;
    var
     Found   : Boolean;
     LMethod : TRttiMethod;
     LIndex  : Integer;
     LParams : TArray<TRttiParameter>;
    begin
      Result:=nil;
      LMethod:=nil;
      Found:=False;
      for LMethod in RttiType.GetMethods do
       if SameText(LMethod.Name, MethodName) then
       begin
         LParams:=LMethod.GetParameters;
         if Length(Args)=Length(LParams) then
         begin
           Found:=True;
           for LIndex:=0 to Length(LParams)-1 do
           if LParams[LIndex].ParamType.Handle<>Args[LIndex].TypeInfo then
           begin
             Found:=False;
             Break;
           end;
         end;
    
         if Found then Break;
       end;
    
       if (LMethod<>nil) and Found then
         Result:=LMethod.Invoke(Instance, Args)
       else
         raise Exception.CreateFmt('method %s not found',[MethodName]);
    end;
    

    Now you can call the constructors or methods of your class in one of these ways

       r := RttiMethodInvokeEx('Create', t, t.MetaclassType, [444]);
       r := RttiMethodInvokeEx('Create', t, t.MetaclassType, ['hello from constructor string']);
       r := RttiMethodInvokeEx('Create', t, t.MetaclassType, []);
       RttiMethodInvokeEx('Bar', t, r.AsObject , ['this is a string']);
       RttiMethodInvokeEx('Bar', t, r.AsObject , [9999]);
    
    0 讨论(0)
提交回复
热议问题