Delphi: RTTI и TObjectList <TObject> - PullRequest
       51

Delphi: RTTI и TObjectList <TObject>

4 голосов
/ 01 апреля 2010

Основываясь на одном ответе на более раннюю публикацию , я изучаю возможность следующего дизайна

TChildClass = class(TObject)
private
  FField1:  string;
  FField2:  string;
end;

TMyClass = class(TObject)
private
  FField1:  TChildClass;
  FField2:  TObjectList<TChildClass>;
end;

Теперь в реальном мире TMyClass будет иметь 10 различных списков, подобных этому, поэтому я хотел бы иметь возможность обращаться к этим спискам с помощью RTTI. Однако я не заинтересован в других полях этого класса, поэтому мне нужно проверить, является ли определенное поле каким-либо видом TObjectList. Это то, что у меня так далеко:

procedure InitializeClass(RContext: TRttiContext; AObject: TObject);
var
  ROwnerType:   TRttiType;
  RObjListType: TRttiType;
  RField:       TRttiField;
  SchInf:       TSchemaInfoDetail;
begin
ROwnerType := RContext.GetType(AObject.ClassInfo);
RObjListType := RContext.GetType(TObjectList<TObject>);
for RField in ROwnerType.GetFields do begin
  // How do I check if the type of TMyClass.FField2 (which is TObjectList<TChildClass>) is some sort of TObjectList?
end;

Понятно, RField.FieldType <> RObjListType.FieldType. Тем не менее, они имеют какое-то отношение, не так ли? Кажется ужасным (и неправильным!) Очень тщательно проверять общую функциональность, чтобы повысить вероятность того, что RField.FieldType на самом деле TObjectList.

Если честно, я довольно неудобен с дженериками, поэтому вопрос может быть очень наивным. Тем не менее, я более чем счастлив учиться. Возможно ли реализовать вышеуказанное решение? ТИА!

Ответы [ 2 ]

6 голосов
/ 01 апреля 2010

Каждый общий экземпляр уникален и не имеет отношения к другим экземплярам в отношении RTTI. Поскольку Delphi не может создавать экземпляры универсальных типов во время выполнения, нет эквивалента, например, например. .NET GetGenericTypeDefinition. Лучшее, что вы можете сделать, это посмотреть на форму типа - например, он реализует GetEnumerator, Add и т. д.

Это также может быть достаточно гибким для работы с общими типами коллекций, а не только с экземплярами TObjectList<T>. C # делает нечто подобное со своими инициализаторами коллекции - он ищет метод Add и вставляет в него вызовы:

http://msdn.microsoft.com/en-us/library/bb384062.aspx

2 голосов
/ 11 декабря 2010

Delphi может создавать экземпляры универсальных типов во время выполнения. Проблема в том, что универсальные типы обычно не хранятся в информации времени выполнения. Если вы храните глобальную переменную определенного типа (TObjectList в вашем случае), создаете (и освобождаете) ее в разделе инициализации, информация о времени выполнения этого конкретного класса не будет удалена компоновщиком, и вы сможете ее создать динамически позже. (Для правильной работы context.findType () необходимо указать полное имя классов.) Я потратил некоторое время на выяснение того, как это можно сделать, и я определенно не доволен этим, но так как я не нашел другого способа, я должен сейчас иметь дело с этим. Если кто-нибудь знает лучший способ сделать это, дайте мне знать.

...