【问题标题】:Delphi Class Helper RTTI GetMethodDelphi 类助手 RTTI GetMethod
【发布时间】:2013-06-19 01:29:41
【问题描述】:

假设我有一个示例类助手

TSampleClassHelper = class helper for TSampleClass
public
  procedure SomeHelper;
end;

我执行以下操作:

var
  obj :TSampleClass;
begin
  obj:=TSampleClass.Create;
  obj.SomeHelper;
end;

这按预期工作。

但是我怎样才能使用 RTTI 来调用辅助方法呢?以下似乎不起作用,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 不适用于类助手中定义的方法吗?反正有这个吗?

谢谢。

【问题讨论】:

  • 我明白了,但在我的真实代码中,我正在针对任意对象测试“SomeMethod”。我不知道对象是否具有通过帮助程序定义的方法。所以我猜它不适用于通过类助手定义的“SomeMethod”。哦,好吧。

标签: delphi rtti class-helpers


【解决方案1】:

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

所以,你可以这样写,它会返回一个非 nil 方法:

obj:=TSampleClass.Create;
rtype:=ctx.GetType(TypeInfo(TSampleClassHelper));
rmethod:=rtype.GetMethod('SomeHelper');

当然,您应该立即看到第一个问题,即使用编译时指定类型,TSampleClassHelper。我们可以使用 RTTI 根据实例的类型在运行时发现TSampleClassHelper 吗?不,我们不能,我将在下面解释。

即使我们把它放在一边,据我所知,没有办法使用 RTTI 调用该方法。如果您调用rmethod.Invoke(obj, []),那么TRttiInstanceMethodEx.DispatchInvoke 中的代码会阻止调用辅助方法的尝试。它阻止它,因为它规定实例的类型与方法的类不兼容。相关代码为:

if (cls <> nil) and not cls.InheritsFrom(TRttiInstanceType(Parent).MetaclassType) then
  raise EInvalidCast.CreateRes(@SInvalidCast);

好吧,您可以使用rmethod.CodeAddress 获取辅助方法的代码地址,但您需要找到其他方法来调用该方法。将其转换为具有适当签名的方法并调用它很容易。但无论如何,为什么要打扰rmethod.CodeAddress?为什么不使用TSomeHelperClass.SomeMethod 并将RTTI 排除在循环之外?

讨论

Helper 解析是基于编译时的活动助手静态执行的。一旦您尝试使用 RTTI 调用辅助方法,则没有 active 辅助方法。你早就完成编译了。所以你必须决定使用哪个助手类。此时,您不需要 RTTI。

这里的根本问题是类帮助方法解析基本上是一个使用编译器上下文执行的静态过程。由于在运行时没有编译器上下文,因此无法使用 RTTI 执行类帮助方法解析。

要更深入地了解这一点,请在此处阅读 Allen Bauer 的回答:Find all Class Helpers in Delphi at runtime using RTTI?

【讨论】:

  • 并不是一个类有多个助手。就是有些类具有由助手定义的所需方法,有些则没有。例如,对于 TStrings,我通过帮助程序添加了该方法,但对于 TMyClass,它直接在类上定义。
  • @AJ。真正的问题是帮助方法解析是由编译器根据编译上下文静态执行的。该概念与 RTTI 完全正交。
猜你喜欢
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
相关资源
最近更新 更多