Delphi类助手RTTI GetMethod

Delphi类助手RTTI GetMethod,delphi,rtti,class-helpers,Delphi,Rtti,Class Helpers,假设我有一个示例类助手 TSampleClassHelper = class helper for TSampleClass public procedure SomeHelper; end; 我做了以下工作: var obj :TSampleClass; begin obj:=TSampleClass.Create; obj.SomeHelper; end; 这一点与预期相符 但是如何使用RTTI来调用helper方法呢?以下似乎不起作用,GetMethod返回nil va

假设我有一个示例类助手

TSampleClassHelper = class helper for TSampleClass
public
  procedure SomeHelper;
end;
我做了以下工作:

var
  obj :TSampleClass;
begin
  obj:=TSampleClass.Create;
  obj.SomeHelper;
end;
这一点与预期相符

但是如何使用RTTI来调用helper方法呢?以下似乎不起作用,
GetMethod
返回nil

var
  obj :TSampleClass;
  ctx :TRTTIContext;
  rtype :TRTTIType;
  rmethod :TRTTIMethod;
begin
  obj:=TSampleClass.Create;
  rtype:=ctx.GetType(obj.ClassType);
  rmethod:=rtype.GetMethod('SomeHelper'); // rmethod is nil !
end;
那么RTTI对类助手中定义的方法不起作用吗?这有什么关系吗


谢谢。

代码返回
nil
方法的原因是对象的类型不包含名为
SomeHelper
的方法。包含该方法的类型是helper类型

因此,您可以编写以下代码,它将返回一个非nil方法:

obj:=TSampleClass.Create;
rtype:=ctx.GetType(TypeInfo(TSampleClassHelper));
rmethod:=rtype.GetMethod('SomeHelper');
当然,您应该立即看到第一个问题,即使用编译时指定的类型,
TSampleClassHelper
。我们是否可以使用RTTI在运行时根据实例的类型发现
TSampleClassHelper
?不,我们不能,我将在下面解释

即使我们把它放在一边,就我所见,也无法使用RTTI调用该方法。如果调用
rmethod.Invoke(obj,[])
,则
trttInstanceMethodex.DispatchInvoke
中的代码会阻止调用帮助器方法的尝试。它会阻止它,因为它规定实例的类型与方法的类不兼容。相关代码为:

if (cls <> nil) and not cls.InheritsFrom(TRttiInstanceType(Parent).MetaclassType) then
  raise EInvalidCast.CreateRes(@SInvalidCast);
if(cls nil)而不是cls.InheritsFrom(trttInstanceType(Parent.MetaclassType))那么
提高EInvalidCast.CreateRes(@SInvalidCast);
您可以使用
rmethod.CodeAddress
获取helper方法的代码地址,但是您需要找到其他方法来调用该方法。将它转换为具有适当签名的方法并调用它非常容易。但是在任何情况下,为什么还要麻烦使用
rmethod.CodeAddress
?为什么不使用
TSomeHelperClass.SomeMethod
并将RTTI从循环中删除

讨论

助手解析是在编译时基于活动助手静态执行的。一旦尝试使用RTTI调用帮助器方法,就没有活动的帮助器。您早就完成了编译。因此,您必须决定使用哪个帮助器类。在这一点上,您不需要RTTI

这里的基本问题是,类助手方法解析基本上是一个使用编译器上下文执行的静态过程。因为在运行时没有编译器上下文,所以不能使用RTTI执行类帮助器方法解析


要了解更多信息,请阅读Allen Bauer的回答:

我明白了,但在我的实际代码中,我正在针对任意对象测试“SomeMethod”。我不知道对象是否有通过助手定义的方法。所以我想它对通过类助手定义的“SomeMethod”不起作用。哦,这并不是说一个班级有多个帮手。有些类具有由助手定义的所需方法,有些则没有。例如,对于TStrings,我通过助手添加了方法,但是对于TMyClass,它是直接在类上定义的。@AJ。真正的问题是编译器基于编译上下文静态地执行helper方法解析。该概念与RTTI完全正交。