如何动态地向框架的uses子句添加单元?

时间:2013-09-05 02:16:29

标签: delphi

假设我有一个主要表格。主窗体包含两个按钮(打开关闭),单击每个按钮会创建一个框架,主窗体作为父/所有者。 该框架包含3个按钮(添加,编辑和删除),下面的示例代码为:

框架代码:

unit UntFrame;

...

  type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
   AddBtnClick;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
   EditBtnClick;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
   DelBtnClick;
end;

end.

框架使用的3种方法( AddBtnClick EditBtnClick DelBtnClick )存在于两个不同的单元,即UntOpen和UntClose但是做了一些事情取决于创建的框架。单击打开按钮时框架应使用UntOpen,当从主菜单中单击关闭按钮时,UntClose适用。

UntOpen代码:

unit UntOpen;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add open');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit open');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.

UntClose代码:

unit UntClose;

...

procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;

implementation

procedure AddBtnClick;
begin
    ShowMessage('add close');
end;

procedure EditBtnClick;
begin
   ShowMessage('edit close');
end;

procedure DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.

我希望每次创建一个动态单元(如果可能的话)添加到frames的uses子句中,以便单击框架的添加,编辑或删除按钮激发正确的方法(如果打开则从UntOpen中获取方法)如果单击“关闭”按钮,则单击按钮或从UntClose中获取方法。

或者有更有效的方法吗?

感谢。

3 个答案:

答案 0 :(得分:5)

您无法动态使用单位; uses子句不能在运行时操作。您似乎想要更改单位列表,以便您的框架代码(已调用AddBtnClick)将从一个单元或另一个单元中神奇地选择该功能。

Delphi没有这样的方式。如果真的想要类似的东西,请尝试使用Python。

Delphi单元是一个编译时构造。它们无法在运行时进行操作。在编译时,编译器会看到您对AddBtnClick的调用,然后根据您已使用的单位结算 - 绑定 - 名称。你以后不能再重新命名。

相反,您可以将参数传递给帧类构造函数。将按钮功能放入数据结构中,然后将这些对象传递给框架。 (这也称为依赖注入。)例如,您可以从这个抽象类开始:

type
  TButtonBehavior = class
    class procedure AddBtnClick; virtual; abstract;
    class procedure EditBtnClick; virtual; abstract;
    class procedure DelBtnClick; virtual; abstract;
  end;

然后,定义您的框架以接收该类的后代,并根据该值编写您的按钮处理程序:

type
  TButtonBehaviorClass = class of TButtonBehavior;

  TMainFrame = class(TFrame)
  private
    FBehavior: TButtonBehaviorClass;
  ...

constructor TMainFrame.Create(AOwner: TComponent; ABehavior: TButtonBehaviorClass);
begin
  inherited Create(AOwner);
  FBehavior := ABehavior;
end;

procedure TMainFrame.AddBtnClick(Sender: TObject);
begin
  FBehavior.AddBtnClick;
end;

接下来,为您希望框架支持的每组行为定义抽象类的后代。如果需要,您可以在不同的单元中定义它们,但由于它们已经在单独的类中,因此不需要进一步分离。

type
  TOpenBehavior = class(TButtonBehavior)
    class procedure AddBtnClick; override;
    class procedure EditBtnClick; override;
    class procedure DelBtnClick; override;
  end;

  TCloseBehavior = class(TButtonBehavior)
    class procedure AddBtnClick; override;
    class procedure EditBtnClick; override;
    class procedure DelBtnClick; override;
  end;

最后,在创建框架的新实例时,将其中一个类传递给框架构造函数。

Frame := TMainFrame.Create(Self, TOpenBehavior);

答案 1 :(得分:0)

尝试更像这样的东西:

unit UntFrame;

...

type
  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  public
    OnAdd: procedure;
    OnEdit: procedure;
    OnDelete: procedure;
  end;

implementation

{$R *.dfm}

procedure TFmeMain.AddClick(Sender: TObject);
begin
  if Assigned(OnAdd) then OnAdd;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
  if Assigned(OnEdit) then OnEdit;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
  if Assigned(OnDelete) then OnDelete;
end;

end.

unit MainForm;

...

uses
  ..., UntFrame, UntOpen, UntClose;

...

procedure TFormMain.OpenClick(Sender: TObject);
begin
  with TFmeMain.Create(Self) do
  begin
    Parent := ...;
    OnAdd := Addr(UntOpen.AddBtnClick);
    OnEdit := Addr(UntOpen.EditBtnClick);
    OnDelete := Addr(UntOpen.DelBtnClick);
  end;
end;

procedure TFormMain.CloseClick(Sender: TObject);
begin
  with TFmeMain.Create(Self) do
  begin
    Parent := ...;
    OnAdd := Addr(UntClose.AddBtnClick);
    OnEdit := Addr(UntClose.EditBtnClick);
    OnDelete := Addr(UntClose.DelBtnClick);
  end;
end;

end.

答案 2 :(得分:0)

如果我是你,我会尝试这个解决方案:

主框架:

unit UntFrame;

...

uses
  UntOpen, UntClose, ...;

type
  TSelectedPage = (spOpen, spClose);

  TFmeMain = class(TFrame)
    procedure AddClick(Sender: TObject);
    procedure EditClick(Sender: TObject);
    procedure DeleteClick(Sender: TObject);
  private 
    FSelectedPage: TSelectedPage;
    ...
  public ...
  end;

implementation

{$R *.dfm}

uses ...

procedure TFmeMain.AddClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.AddBtnClick;
    spClose: TUntClose.AddBtnClick;
  end;
end;

procedure TFmeMain.EditClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.EditBtnClick;
    spClose: TUntClose.EditBtnClick;
  end;
end;

procedure TFmeMain.DeleteClick(Sender: TObject);
begin
  case FSelectedPage of:
    spOpen: TUntOpen.DelBtnClick;
    spClose: TUntClose.DelBtnClick;
  end;
end;

end.

打开单位:

unit UntOpen;

...
type
  TUntOpen = class 
  public
    class procedure AddBtnClick;
    class procedure EditBtnClick;
    class procedure DelBtnClick;
  end;

implementation

class procedure TUntOpen.AddBtnClick;
begin
    ShowMessage('add open');
end;

class procedure TUntOpen.EditBtnClick;
begin
   ShowMessage('edit open');
end;

class procedure TUntOpen.DelBtnClick;
begin
   ShowMessage('delete open');
end;
end.

关闭单位:

unit UntClose;

...
type
  TUntClose = class 
  public
    class procedure AddBtnClick;
    class procedure EditBtnClick;
    class procedure DelBtnClick;
  end;

implementation

class procedure TUntClose.AddBtnClick;
begin
    ShowMessage('add close');
end;

class procedure TUntClose.EditBtnClick;
begin
   ShowMessage('edit close');
end;

class procedure TUntClose.DelBtnClick;
begin
   ShowMessage('delete close');
end;
end.

这是 OOP 的方式来实现您想要实现的目标,并且在Delphi中 是可能的。