Я очень плохо знаком с IoC / DI и пытаюсь понять, как можно / нужно использовать Delphi TForm с Spring4d.
Я включил пример того, что я пытаюсь очистить (это в основном процедура TestIt, где создается форма). Поскольку TForm не имеет интерфейса с подсчетом ссылок, он, вероятно, не может использоваться контейнером для его создания.
Я включил весь тестовый модуль, чтобы я мог получить комментарии о том, понял ли я использование MVP и в этой среде.
Такое ощущение, что должен быть более чистый способ создания lPresenter без необходимости создавать TForm вручную и вставлять его в презентатор, а затем вводить презентатора в представление.
Я видел другой пост, в котором упоминалось о реализации методов подсчета ссылок TInterfacedObject для реализации подсчета ссылок, но это, похоже, не помогло.
Возможно, лучшим решением было бы использование DelegateTo и создание в нем всех необходимых классов со всеми инъекциями свойств, но это также кажется неправильным.
Unit UI;
Interface
Uses
Vcl.Forms;
Procedure TestIt;
Implementation
Uses
Spring.Container,
WinApi.Windows,
Vcl.StdCtrls,
System.SysUtils,
System.Classes;
Type
IPresenter = Interface;
IModel = Interface(IInterface) ['{D1B8418C-4EC5-473D-9473-C385D6E2A12C}']
Function GetUsersName: String;
Procedure SetUsersName(aName: String);
Function GetAge: Integer;
Procedure SetAge(aAge: Integer);
Property UsersName: String Read GetUsersName Write SetUsersName;
Property Age: Integer Read GetAge Write SetAge;
Procedure FirstUser;
End;
IView = Interface(IInterface) ['{108E61F5-EDC8-48EC-9687-F6D38DA89BC4}']
Procedure Execute;
Function GetPresenter: IPresenter;
Procedure SetPresenter(aPresenter: IPresenter);
Function GetUsersName: String;
Procedure SetUsersName(aName: String);
Function GetAge: Integer;
Procedure SetAge(aAge: Integer);
Property Presenter: IPresenter Read GetPresenter Write SetPresenter;
Property UsersName: String Read GetUsersName Write SetUsersName;
Property Age: Integer Read GetAge Write SetAge;
End;
IPresenter = Interface(IInterface) ['{988D7D21-399A-45E6-B4E7-8E2670080385}']
Function Model: IModel;
Function GetView: IView;
Procedure SetView(aView: IView);
Procedure Execute;
Procedure LoadData;
Procedure SaveData;
Function DataValid: Boolean;
Property View: IView Read GetView Write SetView;
End;
TView = Class(TForm, IView)
Private
FPresenter: IPresenter;
FUsersName: TEdit;
FAge: TEdit;
FButton: TButton;
Procedure DoOk(aSender: TObject);
Public
Constructor Create; Reintroduce;
Procedure Execute;
Function GetPresenter: IPresenter;
Procedure SetPresenter(aPresenter: IPresenter);
Function GetUsersName: String;
Procedure SetUsersName(aName: String);
Function GetAge: Integer;
Procedure SetAge(aAge: Integer);
End;
TModel = Class(TInterfacedObject, IModel)
FUsersName: String;
FAge: Integer;
Public
Function GetUsersName: String;
Procedure SetUsersName(aName: String);
Function GetAge: Integer;
Procedure SetAge(aAge: Integer);
Procedure FirstUser;
End;
TPresenter = Class(TInterfacedObject, IPresenter)
FModel: IModel;
FView: IView;
Public
Constructor Create(aModel: IModel);
Function Model: IModel;
Function GetView: IView;
Procedure SetView(aView: IView);
Procedure Execute;
Procedure LoadData;
Procedure SaveData;
Function DataValid: Boolean;
End;
Procedure TestIt;
Var
lPresenter: IPresenter;
lView: IView;
Begin
GlobalContainer.RegisterType<IModel, TModel>;
GlobalContainer.RegisterType<IPresenter, TPresenter>;
GlobalContainer.Build;
lView := TView.Create;
lPresenter := GlobalContainer.Resolve<IPresenter>;
lPresenter.View := lView;
LView.Presenter := lPresenter;
lPresenter.Model.FirstUser;
lPresenter.Execute;
End;
{ TView }
Constructor TView.Create;
Begin
Inherited CreateNew(Nil);
FUsersName := TEdit.Create(Self);
FUsersName.Top := 20;
FUsersName.Left := 10;
InsertControl(FUsersName);
FAge := TEdit.Create(Self);
FAge.Top := 50;
FAge.Left := 10;
InsertControl(FAge);
FButton := TButton.Create(Self);
FButton.Top := 100;
FButton.Left := 10;
FButton.Caption := 'Ok';
InsertControl(FButton);
FButton.OnClick := DoOk;
End;
Procedure TView.DoOk(aSender: TObject);
Begin
If FPresenter.DataValid Then
Close
Else
MessageBeep(MB_ICONEXCLAMATION);
End;
Procedure TView.Execute;
Begin
ShowModal;
End;
Function TView.GetAge: Integer;
Begin
Result := StrToInt(FAge.Text);
End;
Function TView.GetUsersName: String;
Begin
Result := FUsersName.Text;
End;
Function TView.GetPresenter: IPresenter;
Begin
Result := FPresenter;
End;
Procedure TView.SetAge(aAge: Integer);
Begin
FAge.Text := IntToStr(aAge);
End;
Procedure TView.SetPresenter(aPresenter: IPresenter);
Begin
FPresenter := aPresenter;
End;
Procedure TView.SetUsersName(aName: String);
Begin
FUsersName.Text := aName;
End;
{ TModel }
Procedure TModel.FirstUser;
Begin
FUsersName := 'Peter Piper';
FAge := 25;
End;
Function TModel.GetAge: Integer;
Begin
Result := FAge;
End;
Function TModel.GetUsersName: String;
Begin
Result := FUsersName;
End;
Procedure TModel.SetAge(aAge: Integer);
Begin
FAge := aAge;
End;
Procedure TModel.SetUsersName(aName: String);
Begin
FUsersName := aName;
End;
{ TPresenter }
Constructor TPresenter.Create(aModel: IModel);
Begin
FModel := aModel;
End;
Function TPresenter.DataValid: Boolean;
Begin
Result := (FView.Age > 18) And (FView.Age < 100);
End;
Procedure TPresenter.Execute;
Begin
LoadData;
FView.Execute;
SaveData;
End;
Procedure TPresenter.LoadData;
Begin
FView.UsersName := FModel.UsersName;
FView.Age := FModel.Age;
End;
Function TPresenter.Model: IModel;
Begin
Result := FModel;
End;
Procedure TPresenter.SaveData;
Begin
FModel.UsersName := FView.UsersName;
FView.Age := FModel.Age;
End;
Procedure TPresenter.SetView(aView: IView);
Begin
FView := aView;
End;
Function TPresenter.GetView: IView;
Begin
Result := FView;
End;
end.