Причина, по которой ваш код возвращает метод 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 из петли?
Обсуждение
разрешение Helper выполняется статически на основе активного помощника в точке компиляции. Когда вы пытаетесь вызвать вспомогательный метод с использованием RTTI, нет active helper. Вы уже давно закончили компиляцию. Поэтому вам нужно решить, какой класс помощника использовать. В этот момент вам не нужен RTTI.
Основная проблема здесь заключается в том, что разрешение класса-помощника класса является в основном статическим процессом, выполняемым с использованием контекста компилятора. Поскольку во время выполнения нет контекста компилятора, разрешение метода вспомогательного класса класса не может быть выполнено с использованием RTTI.
Для большего понимания в этом есть Распознать ответ Аллена Бауэра здесь: Find all Class Helpers in Delphi at runtime using RTTI?
я вижу, но в моей реальной жизни кода я тестирование на «SomeMethod» против любого произвольного объекта. Я не знаю, имеет ли объект метод, определенный с помощью помощника или нет.Поэтому я думаю, что это не будет работать для «SomeMethod», определенного через помощник класса. Ну что ж. –