是否可以使用Rtti确定TRttiMethod
是否标记为overload
,override
或abstract
?
提前感谢。
答案 0 :(得分:2)
重载:我认为没有RTTI标志,但您可以检查是否有多个具有相同名称的方法。这并不完美,但它可能就像你要得到的那样接近。
覆盖:首先,确保该方法是虚拟的。 (或动态或消息调度。)然后检查类的祖先是否具有相同名称和VirtualIndex属性的其他方法。
摘要:深入rtti.pas的实现部分,带有一堆方法数据标志,是一个名为mfAbstract
的{{1}},定义为1 shl 7;
。没有引用它的代码,但它是在编译器生成的RTTI中实现的。当您拥有该方法的TRttiMethod参考时,您可以像这样测试它:
IsVirtual := PVmtMethodExEntry(method.Handle).Flags and (1 shl 7) <> 0;
PVmtMethodExEntry在TypInfo
单元中声明,因此您需要使用它来实现。
答案 1 :(得分:0)
如果仍然重要...... 我这样检查一下:
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 dkVtable
和dkDynamic
。因此,如果方法标记为abstract
,则必须具有其中之一。同时为避免获得class static
方法,我使用了第二个条件:not TRttiMethod.IsClassMethod
另见System.Rtti:
TDispatchKind = (dkStatic, dkVtable, dkDynamic, dkMessage, dkInterface);
您可以自行决定处理此枚举。
关于“覆盖”:请参阅TStream.Seek
,也许您会在那里找到对您有用的内容。
关于“过载”:@ mason-wheeler上面的答案看起来非常适合这种情况。