Инъекция зависимостей в дочерние классы: решение проблемы с Spring4D и GlobalContainer
Вопрос, заданный пользователем, связан с использованием фреймворка Spring4D для инъекции зависимостей в объекты и их дочерние классы в среде разработки на Delphi. Проблема заключается в том, что при попытке создать дочерний класс TSurvey, например TFieldSurvey, возникает исключение, поскольку стандартный вызов конструктора не учитывает механизмы инъекции, настроенные в GlobalContainer. Вопрос состоит в том, как корректно инстанцировать объект для класса TFieldSurvey, используя возможности Spring4D.
Описание проблемы
Рассмотрим пример класса TSurvey, который использует интерфейс ISurvey и имеет поле _organization типа IOrganization. Пример использования GlobalContainer для создания экземпляра TSurvey демонстрирует корректную работу системы инъекции зависимостей. Однако, при попытке создать дочерний класс TFieldSurvey с помощью метода Create, возникает исключение, так как механизм инъекции зависимостей не активируется.
type
TSurvey = class (TInterfacedObject, ISurvey)
private
_id: Integer;
_organization: IOrganization;
// ...
public
property Id: Integer read GetId write SetId;
property Organization: IOrganization read GetOrganization write SetOrganization;
end;
initialization
GlobalContainer.RegisterType<TSurvey>.Implements<ISurvey>.InjectField('_organization');
type
TFieldSurvey = class(TSurvey)
// ...
end;
var
fieldSurvey: TFieldSurvey;
begin
fieldSurvey := TFieldSurvey.Create; // Вызовет исключение
fieldSurvey.Organization.Id := 5; // <--- Исключение здесь
end;
Подтвержденное решение
Чтобы решить проблему, необходимо зарегистрировать класс TFieldSurvey в GlobalContainer и затем использовать его для получения экземпляра через Resolve. Это позволит активировать механизм инъекции зависимостей.
GlobalContainer.RegisterType<TSurvey>.Implements<ISurvey>('SPRING_SURVEY').InjectField('_organization');
GlobalContainer.RegisterType<TFieldSurvey>.Implements<ISurvey>('SPRING_FIELD_SURVEY').InjectField('_organization');
var
fieldSurvey: TFieldSurvey;
begin
fieldSurvey := GlobalContainer.Resolve<TFieldSurvey>('SPRING_FIELD_SURVEY');
fieldSurvey.Organization.Id := 5; // Теперь все работает корректно
end;
Также возможно использование атрибута [Inject] для поля _organization в классе TSurvey, что исключает необходимость явного вызова метода InjectField:
type
TSurvey = class (TInterfacedObject, ISurvey)
private
_id: Integer;
[Inject]
_organization: IOrganization;
// ...
end;
И регистрация класса будет выглядеть следующим образом:
В альтернативном ответе подчеркивается важность избегания зависимостей от DI контейнера и рекомендуется использовать инъекцию через конструктор или свойства вместо поля, что позволяет писать более чистый код и упрощает его обслуживание. Также упоминается антипаттерн "Service Locator", который следует избегать.
Важно: Перед использованием DI контейнера рекомендуется изучить принципы работы DI и техники, которые позволяют писать чистый код с использованием DI.
В данной статье был рассмотрен вопрос инъекции зависимостей в дочерние классы с использованием фреймворка Spring4D в среде разработки на Delphi. Представлены решения, которые позволяют корректно инстанцировать объекты, используя механизмы GlobalContainer, и обсуждаются альтернативные подходы к инъекции зависимостей.
Пользователь столкнулся с проблемой инъекции зависимостей в дочерние классы при использовании фреймворка Spring4D в среде Delphi и ищет решение, чтобы корректно создать экземпляр класса `TFieldSurvey`.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.