Вопрос

Я пытаюсь проанализировать объекты в XML в Delphi, поэтому я прочитал о вызове метода ClassInfo объекта, чтобы получить его информацию RTTI.

Дело в том, что это, очевидно, работает только для TPersistent объектов. В противном случае мне нужно специально добавить директиву компилятора {$ M +} в исходный код, чтобы компилятор генерировал информацию RTTI.

Итак, я с радостью добавил директиву, но обнаружил, что, даже если она действительно что-то возвращала из вызова ClassInfo (раньше он возвращал nil), теперь я не могу извлечь из него свойства, поля или методы класса. Как будто он создал объект пустым.

Есть идеи, что мне здесь не хватает? Спасибо!

Это было полезно?

Решение

Поместили ли вы эти свойства и методы в раздел опубликованный ?

Кроме того, «классический» RTTI ($ TYPEINFO ON) будет получать только информацию о свойствах, а не о методах. Для этого вам нужен расширенный RTTI ($ METHODINFO ON).

Хорошая отправная точка для расширенного RTTI: Дэвид Глассбороу по расширенному RTTI

(кто бы мог подумать, что именно в эту минуту я закончил писать код, использующий расширенный RTTI, и решил немного просмотреть переполнение стека:))

Другие советы

RTTI покажет только опубликованные свойства и т. д. - не только публичные.

Попробуйте свой код с TObject и посмотрите, что произойдет - если это не сработает, опубликуйте свой код , потому что не все экстрасенсы.

Рассматривали ли вы использование компонента TXMLDocument? Он будет смотреть на ваш XML, а затем создаст замечательную единицу классов Delphi, которая представляет ваш XML-файл, что делает его действительно, очень простым для чтения и записи XML-файлов.

Что касается проблемы RttiType, возвращающей только nil, это, вероятно, происходит по одной причине: в своем тесте вы не создавали экземпляр класса в любое время. Компилятор, поскольку он никогда не имеет ссылки на этот класс (потому что он вообще не является экземпляром), просто удаляет его из информации как форму оптимизации. Смотрите два примера ниже. Поведение отличается, когда у вас есть экземпляр класса в какой-то момент в вашем коде или нет.

Предположим, следующий класс:

type
  TTest = class
  public
    procedure Test;
  end;

и следующий код ниже:

var
  LContext: TRttiContext;
  LType: TRttiType;
  LTest: TTest;
begin
  LContext := TRttiContext.Create;
  for LType in LContext.GetTypes do
  begin
    if LType.IsInstance then
    begin
      WriteLn(LType.Name);
    end;
  end;
end;

Пока что информация о классе TTest недоступна для использования RTTI. Однако, когда мы создаем в какой-то момент в приложении, для него создается ссылка внутри компиляции, что делает эту информацию доступной:

var
  LContext: TRttiContext;
  LType: TRttiType;
  LTest: TTest;
begin
  LTest := TTest.Create; //Here i´m using TTest.
                         //Could be in another part of the program

  LContext := TRttiContext.Create;
  for LType in LContext.GetTypes do
  begin
    if LType.IsInstance then
    begin
      WriteLn(LType.Name);
    end;
  end;
end;

В этот момент, если вы используете LContext.FindType ('TTest') , возврата не будет, поскольку компилятор сохранил ссылку на класс. Это объясняет поведение, которое вы имели в своих тестах.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top