确定 TRttiMethod 何时被标记为重载、覆盖或抽象

发布于 2024-09-26 18:58:49 字数 136 浏览 7 评论 0原文

是否可以使用 Rtti 确定 TRttiMethod 是否标记为 overloadoverrideabstract

提前致谢。

Is possible using the Rtti determine if a TRttiMethod is a marked as overload,override or abstract ?

thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天冷不及心凉 2024-10-03 18:58:49

重载:我认为没有 RTTI 标志,但您可以检查是否有多个同名方法。这并不完美,但它可能是您所能达到的最接近的结果。

覆盖:首先,确保该方法是虚拟的。 (或者动态或消息调度。)然后检查类的祖先是否有具有相同名称和 VirtualIndex 属性的其他方法。

摘要:在 rtti.pas 的 implementation 部分的深处,有一堆方法数据标志,是一个名为 mfAbstract 的部分,定义为 1 shl 7;< /代码>。没有代码引用它,但它是在编译器生成的 RTTI 中实现的。当您有该方法的 TRttiMethod 引用时,您可以像这样测试它:

IsVirtual := PVmtMethodExEntry(method.Handle).Flags and (1 shl 7) <> 0;

PVmtMethodExEntry 在 TypInfo 单元中声明,因此您需要使用它才能工作。

Overload: I don't think there's an RTTI flag for this, but you can check to see if there's more than one method with the same name. That's not perfect, but it's probably as close as you're going to get.

Override: First, make sure the method is virtual. (Or dynamic or message dispatch.) Then check the class's ancestors for other methods with the same name and VirtualIndex property.

Abstract: Deep in the implementation section of rtti.pas, in with a bunch of method data flags, is one called mfAbstract, defined as 1 shl 7;. There's no code that references this, but it is implemented in the RTTI generated by the compiler. When you have a TRttiMethod reference for the method, you can test it like this:

IsVirtual := PVmtMethodExEntry(method.Handle).Flags and (1 shl 7) <> 0;

PVmtMethodExEntry is declared in the TypInfo unit, so you'll need to use it for that to work.

噩梦成真你也成魔 2024-10-03 18:58:49

如果这仍然重要的话...
我这样检查:

1. function GetCloneProc: TRttiMethod;
2. var
3.   methods: TArray<TRttiMethod>;
4.   parameters: TArray<TRttiParameter>;
5. begin
6.   methods := BaseType.GetDeclaredMethods;
7.   for Result in methods do
8.   begin
9.     if (Result.MethodKind = mkProcedure) and (Result.Name = 'CloneTo') and
10.       (Result.DispatchKind = dkStatic) and not Result.IsClassMethod then
11.    begin
12.       parameters := Result.GetParameters;
13.       if (Length(parameters) = 1) and (parameters[0].Flags = [pfAddress]) and
14.         (parameters[0].ParamType.TypeKind = tkClass) and
15.         ((parameters[0].ParamType as TRttiInstanceType).MetaclassType = (BaseType as TRttiInstanceType).MetaclassType) then
16.         Exit;
17.     end;
18.   end;
19.   Result := nil;
20. end;

你应该注意第 10 行。虚拟或动态方法分别具有 DispatchKind dkVtabledkDynamic。因此,如果方法标记为abstract,则它必须具有其中之一。同时,为了避免得到 class static 方法作为结果,我使用第二个条件:not TRttiMethod.IsClassMethod

另请参阅 System.Rtti:

TDispatchKind = (dkStatic, dkVtable, dkDynamic, dkMessage, dkInterface);

您可以自行处理此枚举。

关于“覆盖”:请参阅TStream.Seek,也许您会在那里找到对您有用的东西。

关于“过载”:上面@mason-wheeler 的答案对于这种情况看起来相当不错。

If it still matters...
I check it this way:

1. function GetCloneProc: TRttiMethod;
2. var
3.   methods: TArray<TRttiMethod>;
4.   parameters: TArray<TRttiParameter>;
5. begin
6.   methods := BaseType.GetDeclaredMethods;
7.   for Result in methods do
8.   begin
9.     if (Result.MethodKind = mkProcedure) and (Result.Name = 'CloneTo') and
10.       (Result.DispatchKind = dkStatic) and not Result.IsClassMethod then
11.    begin
12.       parameters := Result.GetParameters;
13.       if (Length(parameters) = 1) and (parameters[0].Flags = [pfAddress]) and
14.         (parameters[0].ParamType.TypeKind = tkClass) and
15.         ((parameters[0].ParamType as TRttiInstanceType).MetaclassType = (BaseType as TRttiInstanceType).MetaclassType) then
16.         Exit;
17.     end;
18.   end;
19.   Result := nil;
20. end;

You should pay attention to line #10. Virtual or Dynamic methods have DispatchKind dkVtable and dkDynamic respectively. So if method marked as abstract it must have one of them. In the same time to avoid getting class static method as the result I use second condition: not TRttiMethod.IsClassMethod

See also System.Rtti:

TDispatchKind = (dkStatic, dkVtable, dkDynamic, dkMessage, dkInterface);

You can handle this enumeration at one's discretion.

About "override": see TStream.Seek, maybe you'll find something useful for you there.

About "overload": the answer of @mason-wheeler above looks pretty good for this case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文