2015-12-08 1 views
3

Я использую Spring4d framework для инъекций зависимостей и прочего.Delphi, как избежать application.CreateForm?

В пункте ввода приложения я должен создать форму приложения «Главная». Хотя, я не знаю никого другого, кроме

Application.CreateForm(TMainForm, MainForm) 

для создания этой информации.

Возможно ли создать основную форму с использованием инъекции зависимостей Spring4d? Например:

MainForm := GlobalContainer.Resolve<IMainForm>; 

, а затем установить его как форму, которая будет отображаться при открытии приложения?

+1

В конце концов что-то должно назвать 'Application.CreateForm (...)' для основной формы. В противном случае структура VCL не будет знать, что есть основная форма. Вы действительно делаете DI для основной формы? Это точно хорошая идея? –

+0

Я думал, что это было, пока вы не спросили ... Я думаю, что это хорошая идея, потому что в главном представлении может быть несколько зависимостей, которые нужно было бы решить. Это могут быть просмотры фабрик (TFunc или ленивые виды TLazy ). И выполнение DI на этом облегчит процесс тестирования. – Ludo

+0

Почему это плохая идея? – Ludo

ответ

9

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

На мой взгляд, нет необходимости разрешать основную форму как интерфейс, потому что это корень композиции, и он не будет передаваться нигде, поэтому я зарегистрирую его, как показано ниже.

container.RegisterType<TMainForm,TMainForm>.DelegateTo(
    function: TMainForm 
    begin 
    Application.CreateForm(TMainForm, Result); 
    end); 

И тогда вы можете просто разрешить это вызывая

container.Resolve<TMainForm>; 

Однако преимущество позволяя контейнер решить форму, что она может придать зависимостей в него, не будет здесь с кодом внутри CreateForm создает экземпляр. Вот в чем заключается возможность вызова дополнительных методов через контейнер после строительства. Таким образом, вместо того, чтобы передавать зависимость в конструктор, как обычно, вы можете добавить метод let: Init к классу форм, который принимает необходимые ему зависимости и добавляет к нему атрибут [Inject]. Это укажет контейнеру вызов этого метода после создания экземпляра (в нашем случае через функцию фабрики, переданного методу DelegateTo) и передать все необходимые ему зависимости.

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

TMainForm = class(TForm) 
public 
    [Inject] 
    procedure Init(...); 
end; 
+2

Я не вижу никакой пользы от вызова Application.CreateForm в dpr-файле. Предположительно, есть некоторые. Что я пропустил? –

+1

Если вы просто вызываете 'Application.CreateForm', то контейнер не вступает в игру, поэтому DI не может произойти (вам нужно будет вызвать' MainForm.Init (container.Resolve , container.Resolve , ...) ' сам). Также контейнер не регистрирует экземпляр «MainForm» в себе, поэтому вы не можете вводить его в классы, зависящие от него. –

+0

Спасибо, Стефан, это именно то, что я искал. – Ludo

 Смежные вопросы

  • Нет связанных вопросов^_^