gpt4 book ai didi

Delphi 类帮助器 RTTI GetMethod

转载 作者:行者123 更新时间:2023-12-03 14:52:27 25 4
gpt4 key购买 nike

假设我有一个示例类助手

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?

关于Delphi 类帮助器 RTTI GetMethod,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17243328/

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