Register overloaded method with different argument type but same count of arguments

Hello,

Following with this :
https://support.tmssoftware.com/t/problem-with-overloaded-method-rtti-registered/15111/8

I would like to register method TCustomRESTRequest.AddBody to the scripter.
Problem there is a same number of arguments in this case :

procedure AddBody(const ABodyContent: string; AContentType: TRESTContentType = ctNone); overload;
procedure AddBody(AObject: TJsonObject; AOwnsObject: TRESTObjectOwnership = ooApp); overload;

I know how to detect argument count using TatVirualMachine.InputArgCount like this :

procedure TatRESTClientLibrary.__TRESTRequestParameterListAddItem(AMachine: TatVirtualMachine);
  var
  AResult: variant;
  TempVar:TRESTRequestParameterOptions;
begin
  with AMachine do
  begin
   case InputArgCount  of
   0,1:  AResult := ObjectToVar(TRESTRequestParameterList(CurrentObject).AddItem);
   2:  AResult := ObjectToVar(TRESTRequestParameterList(CurrentObject).AddItem(AMachine.GetInputArgAsString(0), AMachine.GetInputArgAsString(1)));
   3:  AResult := ObjectToVar(TRESTRequestParameterList(CurrentObject).AddItem(AMachine.GetInputArgAsString(0), AMachine.GetInputArgAsString(1),TRESTRequestParameterKind(AMachine.GetInputArgAsInteger(2))));
   4: begin
       IntToSet(TempVar, VarToInteger(GetInputArg(3)), SizeOf(TempVar));
       AResult := ObjectToVar(TRESTRequestParameterList(CurrentObject).AddItem(AMachine.GetInputArgAsString(0), AMachine.GetInputArgAsString(1),TRESTRequestParameterKind(AMachine.GetInputArgAsInteger(2)),TempVar));
      end;
   5: begin
       IntToSet(TempVar, VarToInteger(GetInputArg(3)), SizeOf(TempVar));
       AResult := ObjectToVar(TRESTRequestParameterList(CurrentObject).AddItem(AMachine.GetInputArgAsString(0), AMachine.GetInputArgAsString(1),TRESTRequestParameterKind(AMachine.GetInputArgAsInteger(2)),TempVar,TRESTContentType(AMachine.GetInputArgAsInteger(4))));
      end;
   6: begin
       IntToSet(TempVar, VarToInteger(GetInputArg(3)), SizeOf(TempVar));
       AResult := ObjectToVar(TRESTRequestParameterList(CurrentObject).AddItem(AMachine.GetInputArgAsString(0), TStream(AMachine.GetInputArgAsObject(1)),TRESTRequestParameterKind(AMachine.GetInputArgAsInteger(2)),TempVar,TRESTContentType(AMachine.GetInputArgAsInteger(4)),TRESTObjectOwnership(AMachine.GetInputArgAsInteger(5))));
      end;
   end;

    ReturnOutputArg(AResult);
  end;
end;

But what is the good way to detect is an argument is a String, an integer or a Object ?
Like the 1st argument of AddBody which can be a TJsonObject or a string.

In TIdCustomHTTP.Post have tried this ulgy :

     if assigned(AMachine.GetInputArgAsClass(1))  and (TObject(GetInputArgAsClass(1)) is TStrings ) and  assigned(GetInputArgAsClass(2)) and (TObject(NativeUInt(GetInputArg(2))) is TStream) then

Which doesn't seems to work fine.
Does the unique solution is to register a custom method with each case of arguments type ?

It would be cleaner if you register a different method, since Scripter is to strong typed. But in any case, the values passed as the arguments are Variant types, you can simply check for the variant type, if the variant is a string, call the method that receives a string, otherwise call the other one.

Rough example (not tested):

var
  Arg0: Variant;
begin
  Arg0 := AMachine.GetInputArg(0);
  if VarIsStr(Arg0) then
    CallAsString(VarToStr(Arg0))
  else
    CallAsObject(TSomeObject(VarToObject(Arg0)));
end;

Hello,

Thank you for your quick answer.

Yes your sample work for first version of AddBody :

procedure AddBody(const ABodyContent: string; AContentType: TRESTContentType = ctNone); overload;

But not to between these methods :

procedure AddBody(AObject: TJsonObject; AOwnsObject: TRESTObjectOwnership = ooApp); overload;
procedure AddBody(ABodyContent: TStream; AContentType: TRESTContentType = ctNone;  AOwnsStream: TRESTObjectOwnership = ooCopy); overload;

So I have done it :

procedure TatRESTClientLibrary.__TCustomRESTRequestAddBody(AMachine: TatVirtualMachine);
var
  ArgumentCheckOk:boolean;
begin
  ArgumentCheckOk:=false;
  if VarIsStr(AMachine.GetInputArg(0)) then
  begin
    if AMachine.InputArgCount=1 then
      begin
        ArgumentCheckOk:=true;
        TCustomRESTRequest(AMachine.CurrentObject).AddBody(AMachine.GetInputArgAsString(0));
      end
     else
     if AMachine.InputArgCount=2 then
     begin
        ArgumentCheckOk:=true;
        TCustomRESTRequest(AMachine.CurrentObject).AddBody(AMachine.GetInputArgAsString(0),TRestContentType(AMachine.GetInputArgAsInteger(1)));
     end;
  end
  else
  begin
    if AMachine.GetInputArgAsObject(0) is TJsonObject then
    begin
        if AMachine.InputArgCount=1 then
        begin
          ArgumentCheckOk:=true;
          TCustomRESTRequest(AMachine.CurrentObject).AddBody(TJsonObject(AMachine.GetInputArgAsObject(0)));
        end
        else
        if AMachine.InputArgCount=2 then
        begin
           ArgumentCheckOk:=true;
           TCustomRESTRequest(AMachine.CurrentObject).AddBody(TJsonObject(AMachine.GetInputArgAsObject(0)),TRestObjectOwnerShip(AMachine.GetInputArgAsInteger(1)));
        end;
    end
    else
    begin
       ArgumentCheckOk:=true;
       case AMachine.InputArgCount of
        1:  TCustomRESTRequest(AMachine.CurrentObject).AddBody(TStream(AMachine.GetInputArgAsObject(0)));
        2:  TCustomRESTRequest(AMachine.CurrentObject).AddBody(TStream(AMachine.GetInputArgAsObject(0)),TRESTContentType(AMachine.GetInputArgAsInteger(1)));
        3:  TCustomRESTRequest(AMachine.CurrentObject).AddBody(TStream(AMachine.GetInputArgAsObject(0)),TRESTContentType(AMachine.GetInputArgAsInteger(1)),TRESTObjectOwnership (AMachine.GetInputArgAsInteger(2)))
        else ArgumentCheckOk:=false;
       end;


    end;
  end;



  if not ArgumentCheckOk then
  begin
    RaiseRuntimeError('E2250 None overloaded version of TCustomRESTRequest.AddBody can be called with theses arguments');
  end;

end;

What do you think about it ?
Especially :

  if AMachine.GetInputArgAsObject(0) is TJsonObject then

That's fine. I assume it works for you?

Yes it's seems to work fine.
I wasn't sure about such a thing :

AMachine.GetInputArgAsObject(0) is TJsonObject
1 Like

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.