gpt4 book ai didi

delphi - 当 View 非模态时,如何在 View 之前销毁适配器?

转载 作者:行者123 更新时间:2023-12-01 16:50:34 25 4
gpt4 key购买 nike

我正在为我的所有应用程序模块使用某种(类似 MVA)模式。

观看次数为 TForm后代:

TSomeView = class(TForm)
...
end;

数据在模型中管理:
TSomeModel = class
public
property DataSet: TDataSet read ...;
end;

View 和模型通过适配器粘合在一起。
uses
Some.Model, Some.View;

type
TSomeAdapter = class
private
FView : TSomeView;
FModel : TSomeModel;
procedure ClickHandler(Sender: TObject);
public
constructor Create(AOwner: TComponent);
destructor Destroy; override;
procedure Run;
end;

虽然这可能看起来有点乏味,但它可以很好地分离事物。

到目前为止,我一直使用模态形式,因此适配器实现如下所示:
constructor TSomeAdapter.Create(AOwner: TComponent);
begin
inherited Create;
FModel := TSomeModel.Create,
FView := TSomeView.Create(AOwner);
FView.DataSource.DataSet := FModel.DataSet;
FView.SomeButton.OnClick := ClickHandler;
end;

procedure TSomeAdapter.Run;
begin
FView.ShowModal;
end;

destructor TSomeAdapter.Destroy;
begin
FView.Free;
FModel.Free;
inherited;
end;

这里重要的是我不会在析构函数中断开事件处理程序和数据集,因为 View 总是首先被销毁。

调用者使用此模式创建应用程序模块:
procedure CallSome;
var
Adapter: TSomeAdapter;
begin
Adapter := TSomeAdapter.Create(...);
try
Adapter.Run;
finally
Adapter.Free;
end;
end;

我正在尝试将其调整为非模态形式。

调用者无法释放适配器,因为它不知道何时。所以调用者代码现在看起来像这样:
procedure CallSome;
var
Adapter: TSomeAdapter;
begin
Adapter := TSomeAdapter.Create(...);
Adapter.Run;
// Adapter is now a memory leak
end;

我不想更改销毁顺序,因为我依赖于不需要断开处理程序和数据集的事实。

使用非模态表单时如何保持销毁顺序( View <模型<适配器)?

最佳答案

您必须更改适配器,以便适​​配器是 View 的所有者,并使 View 在关闭时自毁。当 View 将被销毁时,适配器会收到通知。

type
TSomeAdapter = class( TComponent )
private
FView : TSomeView;
FModel : TSomeModel;
FOnEndsRunning : TNotifyEvent;
function GetModel : TSomeModel;
function GetView : TSomeView;
function GetIsRunning : Boolean;
protected
procedure Notification( AComponent : TComponent; Operation : TOperation ); override;
property View : TSomeView read GetView;
property Model : TSomeModel read GetModel;
procedure ClickHandler( Sender : TObject );
public
destructor Destroy; override;
procedure Run;
property IsRunning : Boolean read GetIsRunning;
property OnEndsRunning : TNotifyEvent read FOnEndsRunning write FOnEndsRunning;
end;

{ TSomeAdapter }

destructor TSomeAdapter.Destroy;
begin
FModel.Free;
inherited;
end;

procedure TSomeAdapter.ClickHandler( Sender : TObject );
begin
// DoSomething
end;

function TSomeAdapter.GetIsRunning : Boolean;
begin
Result := Assigned( FView );
end;

function TSomeAdapter.GetModel : TSomeModel;
begin
// lazy initialization of model
if not Assigned( FModel ) then
FModel := TSomeModel.Create;
Result := FModel;
end;

function TSomeAdapter.GetView : TSomeView;
begin
// lazy initialization of view
if not Assigned( FView ) then
begin
FView := TSomeView.Create( Self ); // Owner is this Adapter
FView.DataSource.DataSet := Model.DataSet;
FView.SomeButton.OnClick := ClickHandler;
end;
Result := FView;
end;

procedure TSomeAdapter.Notification( AComponent : TComponent; Operation : TOperation );
begin
inherited;
case Operation of
opInsert :
;
opRemove :
if AComponent = FView then
begin
// forget the view reference
FView := nil;
// destroy the model (optional)
FreeAndNil( FModel );
// notify
if Assigned( OnEndsRunning ) then
OnEndsRunning( Self );
end;
end;

end;

procedure TSomeAdapter.Run;
begin
View.Show;
end;

View 应该在关闭时自行释放
TSomeView = class( TForm )
procedure FormClose(Sender: TObject; var Action: TCloseAction);
end;

procedure TSomeView.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

现在,如果适配器结束运行,您将收到通知

关于delphi - 当 View 非模态时,如何在 View 之前销毁适配器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21810102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com