Я хотел бы добавить некоторые комментарии к вашему текущему решению, отвечая здесь, поскольку это не может быть сделано в разделе комментариев:
type
IComponentFrobber = interface
end;
TComponentFrobberClass = class of TComponentFrobber;
TComponentFrobber = class(TInterfacedObject, IComponentFrobber)
strict private
FComponent: TComponent;
protected
constructor Create(AComponent: TComponent);
property Component: TComponent read FComponent;
public
class function FindFrobberClass(AComponentClass: TComponentClass):
TComponentFrobberClass; overload; static;
class function FindFrobberClass(AComponent: TComponent):
TComponentFrobberClass; overload; static;
class procedure RegisterFrobber(AComponentClass: TComponentClass;
AFrobberClass: TComponentFrobberClass); static;
end;
Нет особого смысла в использовании TInterfacedObject для базового класса, поскольку вам всегда будет нужен объект, а не интерфейс, который он реализует - как еще вы найдете конкретный класс Frobber? Я бы разделил это на TComponentFrobber, происходящий из TInterfacedObject, и класс TComponentRegistry (происходящий из TObject), который имеет методы класса. Затем вы, конечно, можете сделать класс реестра более общим, он не привязан к TComponentFrobber и может быть использован повторно.
Редактировать: Я использовал подобные реестры классов, например, при загрузке файлов: загрузите идентификатор для следующего объекта (может быть, например, строка, целое число или GUID), затем получите правильный класс для создания экземпляра из реестра, затем создайте и загрузите объект.
type
TComponentFrobberRegistryItem = record
ComponentClass: TComponentClass;
FrobberClass: TComponentFrobberClass;
end;
var
FComponentFrobberRegistry: array of TComponentFrobberRegistryItem;
Это нормально, если вы никогда не будете добавлять или удалять классы в / из реестра, но обычно я бы не использовал массив, а список для записей в реестре.
class function TComponentFrobber.FindFrobberClass(AComponentClass: TComponentClass):
TComponentFrobberClass;
var
i: Integer;
begin
// Search backwards, so that more specialized frobbers are found first:
for i := High(FComponentFrobberRegistry) downto Low(FComponentFrobberRegistry) do
if FComponentFrobberRegistry[i].ComponentClass = AComponentClass then
begin
Result := FComponentFrobberRegistry[i].FrobberClass;
Exit;
end;
Result := nil;
end;
Поиск в массиве в обратном направлении не поможет найти наиболее специализированный фроббер, если вы не добавите их в правильном порядке (сначала наименее специализированный). Почему бы вам не проверить, чтобы ClassType был равен? Существует также ClassParent для обхода иерархии классов, если вам нужно проверить и базовые классы.