delphi – TRttiMethod.Invoke函数在重载方法中不起作用?
发布时间:2020-12-15 04:27:51 所属栏目:大数据 来源:网络整理
导读:我正在使用 TRttiMethod.Invoke函数创建一个类的实例,但是当构造函数或方法重载时,rtti不会调用正确的方法. 我写了一个示例应用来说明我的问题. program ProjectFoo;{$APPTYPE CONSOLE}{$R *.res}uses Rtti,System.SysUtils;type TFoo=class public construc
我正在使用
TRttiMethod.Invoke函数创建一个类的实例,但是当构造函数或方法重载时,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',['hello from constructor string']); r := RttiMethodInvokeEx('Create',[]); RttiMethodInvokeEx('Bar',r.AsObject,['this is a string']); RttiMethodInvokeEx('Bar',[9999]); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |