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]);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…