Как использовать delphi TForm в IoC / DI с Spring4d? - PullRequest
0 голосов
/ 27 августа 2018

Я очень плохо знаком с 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.
...