确定何时将TRttiMethod标记为重载,覆盖或抽象

时间:2010-10-09 22:33:13

标签: delphi delphi-2010 rtti delphi-xe

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

提前感谢。

2 个答案:

答案 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 dkVtabledkDynamic。因此,如果方法标记为abstract,则必须具有其中之一。同时为避免获得class static方法,我使用了第二个条件:not TRttiMethod.IsClassMethod

另见System.Rtti:

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

您可以自行决定处理此枚举。

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

关于“过载”:@ mason-wheeler上面的答案看起来非常适合这种情况。