加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi Class Helper RTTI GetMethod

发布时间:2020-12-15 04:33:45 所属栏目:大数据 来源:网络整理
导读:让我们说我有一个示例类助手 TSampleClassHelper = class helper for TSampleClasspublic procedure SomeHelper;end; 我做以下事情: var obj :TSampleClass;begin obj:=TSampleClass.Create; obj.SomeHelper;end; 这按预期工作. 但是,我如何使用RTTI来调用
让我们说我有一个示例类助手
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不适用于类助手中定义的方法吗?有没有办法解决?

谢谢.

解决方法

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

所以,你可以写这个将返回一个非零方法:

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切断出来?

讨论

辅助分辨率是根据编译点的活动帮助程序静态执行的.一旦尝试使用RTTI调用辅助方法,就没有活动的帮助器.你早就完成编译了.所以你必须决定使用哪个助手类.此时,您不需要RTTI.

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

有关这方面的更多信息,请阅读Allen Bauer的答案:Find all Class Helpers in Delphi at runtime using RTTI?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读