Определите, когда TRttiMethod помечен как перегрузка, переопределение или абстракция - PullRequest
1 голос
/ 10 октября 2010

Возможно с помощью Rtti определить, помечен ли TRttiMethod как overload, override или abstract?

заранее.

Ответы [ 2 ]

2 голосов
/ 10 октября 2010

Перегрузка: я не думаю, что для этого есть флаг RTTI, но вы можете проверить, существует ли более одного метода с одинаковым именем. Это не идеально, но это, вероятно, так близко, как вы собираетесь получить.

Переопределение: сначала убедитесь, что метод является виртуальным. (Или динамическая или отправка сообщения.) Затем проверьте предков класса на наличие других методов с тем же именем и свойством VirtualIndex.

Аннотация: Глубоко в разделе реализации файла rtti.pas, вместе с набором флагов данных метода, находится один из них, называемый mfAbstract, определяемый как 1 shl 7;. Нет кода, который ссылается на это, но он реализован в RTTI, сгенерированном компилятором. Если у вас есть ссылка TRttiMethod для метода, вы можете проверить его следующим образом:

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

PVmtMethodExEntry объявлен в модуле TypInfo, поэтому вам нужно использовать его для работы.

0 голосов
/ 27 марта 2018

Если это все еще имеет значение ... Я проверяю это так:

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 выше выглядит довольно хорошо для этого случая.

...