gpt4 book ai didi

delphi - TRttiMethod.Invoke 函数在重载方法中不起作用?

转载 作者:行者123 更新时间:2023-12-03 14:56:54 28 4
gpt4 key购买 nike

我正在使用 TRttiMethod.Invoke 创建类的实例function ,但是当构造函数或方法重载时,rtti 不会调用正确的方法。

我编写了一个示例应用程序来说明我的问题。

program ProjectFoo;

{$APPTYPE CONSOLE}

{$R *.res}

uses
Rtti,
System.SysUtils;

type
TFoo=class
public
constructor Create(Value : Integer);overload;
constructor Create(const Value : string);overload;
function Bar(value : integer) : Integer; overload;
function Bar(const value : string) : string; overload;
end;

{ TFoo }

constructor TFoo.Create(Value: Integer);
begin
Writeln(Value);
end;

function TFoo.Bar(value: integer): Integer;
begin
Writeln(Value);
Result:=value;
end;

function TFoo.Bar(const value: string): string;
begin
Writeln(Value);
Result:=value;
end;


constructor TFoo.Create(const Value: string);
begin
Writeln(Value);
end;

var
c : TRttiContext;
t : TRttiInstanceType;
r : TValue;
begin
try
c := TRttiContext.Create;
t := (c.GetType(TFoo) as TRttiInstanceType);
r := t.GetMethod('Create').Invoke(t.MetaclassType,[444]);//this works
//r := t.GetMethod('Create').Invoke(t.MetaclassType,['hello from constructor string']);//this fails : EInvalidCast: Invalid class typecast
t.GetMethod('Bar').Invoke(r,[1]);// this works
//t.GetMethod('Bar').Invoke(r,['Hello from bar']); //this fails : EInvalidCast: Invalid class typecast
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.

这是一个 RTTI 错误?或者存在另一种方法来使用 RTTI 调用类的重载方法?

最佳答案

TRttiMethod.Invoke方法没有任何问题,您的问题位于 GetMethod 。该函数内部调用TRttiType.GetMethods并检索指向与作为参数传递的名称匹配的第一个方法的指针。因此,当您执行此代码t.GetMethod('Create')时,您总是会获得指向同一方法的指针。

要执行构造函数或其他方法的重载版本,您必须根据参数解析要执行的方法地址,然后调用 TRttiMethod.Invoke 函数。

检查此示例函数。

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;

现在您可以通过以下方式之一调用类的构造函数或方法

   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]);

关于delphi - TRttiMethod.Invoke 函数在重载方法中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10083448/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com