Как преобразовать имя класса как строку в класс? - PullRequest
4 голосов
/ 28 апреля 2010

У меня есть имена классов в списке строк. Например, это может быть TPlanEvent, TParcel, TCountry и т. Д.

Теперь я хочу узнать размеры, зациклив список.

Работает так:

Size := TCountry.InstanceSize;

Но я хочу вот так:

for i := 0 to ClassList.Count - 1 do
  Size := StringToClass(ClassList[i]).InstanceSize;

Очевидно, мой вопрос в том, что написать вместо метода StringToClass для преобразования строки в класс.

Ответы [ 4 ]

10 голосов
/ 28 апреля 2010

Поскольку вы используете список строк, вы также можете хранить классы там:

var
  C: TClass;

  StringList.AddObject(C.ClassName, TObject(C));

...

for I := 0 to StringList.Count - 1 do
  Size := TClass(StringList.Objects[I]).InstanceSize;

...

8 голосов
/ 28 апреля 2010

Если ваши классы получены из TPersistent, вы можете использовать RegisterClass и FindClass или GetClass . В противном случае вы могли бы написать какой-то механизм регистрации самостоятельно.

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

В Delphi 2010 вы можете использовать:

function StringToClass(AName: string): TClass;
var
  LCtx: TRttiContext;
  LTp: TRttiType;
begin
  Result := nil;

  try
    LTp := LCtx.FindType(AClassName);
  except
    Exit;
  end;

  if (LTp <> nil) and (LTp is TRttiInstanceType) then
    Result := TRttiInstanceType(LTp).Metaclass;
end;

Одна нота. Поскольку вы сохраняете только имена классов в списке, этот метод не будет работать, потому что TRttiContext.FindType ожидает полного имени типа (например, uMyUnit.TMyClass). Исправление заключается в том, чтобы прикрепить модуль, в котором вы храните эти классы, в цикле или в списке.

2 голосов
/ 28 апреля 2010
  1. Вы должны использовать FindClass, чтобы найти ссылку на класс по его имени. Если класс не найден, будет сгенерировано исключение.
  2. Опционально, вы должны вызывать RegisterClass для ваших классов, если они явно не указаны в коде.
...