Как вызвать GetEnumerator для произвольного типа? - PullRequest
1 голос
/ 24 августа 2009

Я пишу элемент управления, который должен отображать любой список данных.Я хотел имитировать конструкцию for-in, проверяя общедоступную функцию GetEnumerator, которая содержит свойство Current и метод MoveNext.

Я определил следующее:

  1. Я могу проверить существование метода, просто вызвав MethodAddress для моего объекта.Если я получу адрес, метод существует.
  2. Я могу использовать RTTI, чтобы проверить тип возвращаемого значения метода.
  3. Я могу использовать RTTI, чтобы проверить свойство и прочитать его.

Между прочим, мне не хватает небольшой информации:

  1. Как мне вызвать метод, учитывая его адрес?Должен ли я просто написать определение (как я бы для импорта), привести адрес и вызвать его?
  2. Проверка типа возврата метода требует вызова GetTypeData с его PTypeInfo.Я получаю PTypeInfo, вызывая TypeInfo для типа.Итак, как мне получить PTypeInfo для данного метода, учитывая только его адрес?

Ответы [ 2 ]

2 голосов
/ 24 августа 2009
  1. Чтобы вызвать метод, вы берете возвращенный адрес и помещаете его в указатель кода TMethod. Поместите объект в указатель Data, а затем приведите его к указателю метода с правильной подписью.
  2. Чтобы проанализировать сигнатуру функции, вам нужны довольно сложные RTTI. Смотрите http://hallvards.blogspot.com/2006/05/hack-10-getting-parameters-of.html для деталей. Но обратите внимание на предостережение внизу:

Обратите внимание, что это работает, только если экземпляр (или один из его компонентов) также имеет опубликованную собственность, которая указывает на опубликованный метод. Хорошая новость заключается в том, что это имеет место для большинство существующих опубликованных методов - такие как обработчики событий в TForm пример. Плохая новость в том, что это не будет иметь место для любого опубликованные методы, которые мы хотели бы динамически вызывать во время выполнения (и, таким образом, не будет назначен никаким событиям).

Так что то, что вы пытаетесь сделать, может оказаться невозможным при текущей модели RTTI. Но Delphi 2010 должен иметь расширенную систему RTTI, которая позволит вам делать такие вещи намного проще, и это из-за RSN. (Раньше на сайте Embarcadero велся обратный отсчет времени до полуночи. Они сняли его, однако, поэтому я не уверен, является ли это официальной датой выпуска или нет.)

1 голос
/ 24 августа 2009

Сначала обратите внимание, что RTTI доступен только для опубликованных свойств и методов.

Чтобы вызвать метод, полученный MethodAdress, просто выполните:

TMyMethod = procedure (Self : TObject; const Param : String);
...
var
  MyMethod : TMyMethod;
...
MyMethod := Obj.MethodAdress ('MethodName');
if Assigned (MyMethod) then
  MyMethod (Obj, 'Hallo');

Относительно вашего второго вопроса, это может помочь:

Link

...