如何在Spring4d的IoC / DI中使用delphi TForm

时间:2018-08-27 14:42:44

标签: delphi spring4d

我对IoC / DI还是很陌生,我正试图了解如何/应该在Spring4d中使用Delphi TForm。

我提供了一个示例,说明了我要清除的内容(主要是创建表单的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.

0 个答案:

没有答案