Существует, вероятно, более простой способ для достижения этой цели. Кажется, я помню, что нашел встроенный объект TClassList, который обрабатывал это, но что этот момент у меня уже был такой. У TClassList нет способа поиска сохраненных объектов по имени строки, но это все еще может быть полезно.
В основном для выполнения этой работы вам необходимо зарегистрировать классы с помощью глобального объекта. Таким образом, он может принимать строковый ввод для имени класса, искать это имя в списке, чтобы найти правильный объект класса.
В моем случае я использовал TStringList для хранения зарегистрированных классов, и я использую имя класса в качестве идентификатора для класса. Чтобы добавить класс к элементу «object» в списке строк, мне нужно было обернуть класс в реальном объекте. Я признаю, что я действительно не понимаю «класс», поэтому это может не понадобиться, если вы все исправите.
// Needed to put "Class" in the Object member of the
// TStringList class
TClassWrapper = class(TObject)
private
FGuiPluginClass: TAgCustomPluginClass;
public
property GuiPluginClass: TAgCustomPluginClass read FGuiPluginClass;
constructor Create(GuiPluginClass: TAgCustomPluginClass);
end;
У меня есть глобальный объект «PluginManager». Здесь классы регистрируются и создаются. Метод AddClass помещает класс в TStringList, поэтому я могу посмотреть его позже.
procedure TAgPluginManager.AddClass(GuiPluginClass: TAgCustomPluginClass);
begin
FClassList.AddObject(GuiPluginClass.ClassName,
TClassWrapper.Create(GuiPluginClass));
end;
В каждом классе, который я создаю, я добавляю его в список классов в разделе «Инициализация».
initialization;
AgPluginManager.AddClass(TMyPluginObject);
Затем, когда приходит время, чтобы создать класс, я могу поиска имен в списке строк, найти класс и создать его. В моей фактической функции я проверяю, чтобы убедиться, что запись существует и справиться с ошибками и т. Д. Я также передаю больше данных конструктору класса. В моем случае я создаю формы, поэтому я фактически не возвращаю объект обратно вызывающему (я отслеживаю их в своем PluginManager), но это было бы легко сделать, если это необходимо.
procedure TAgPluginManager.Execute(PluginName: string);
var
ClassIndex: integer;
NewPluginWrapper: TClassWrapper;
begin
ClassIndex := FClassList.IndexOf(PluginName);
if ClassIndex > -1 then
begin
NewPluginWrapper := TClassWrapper(FClassList.Objects[ClassIndex]);
FActivePlugin := NewPluginWrapper.GuiPluginClass.Create();
end;
end;
Поскольку я впервые написал это, мне не нужно было трогать код. Я просто хочу добавить свои новые классы в список в разделе инициализации, и все работает.
Чтобы создать объект, я просто называю
PluginManger.Execute('TMyPluginObject');
Привет, Малкольм, спасибо за ваш ответ.Я попытался реализовать очень элегантное решение, но столкнулся с утечкой памяти. Я поставил комментарий на сообщение вашего блога – Fred
Спасибо Фред, Да, это была ошибка в тесте TestGetInstance, а не в самой фабрике. Я исправил загрузку, так что теперь вам будет хорошо. –
Спасибо Малкольм за ваше обновление. – Fred