我有一个应用程序,其中包括“主”表单以及其他四种表单(formA,formB,formC,formD)。四种表格中的每一种都有一个独特的class function execute()
。
现在,在formD中,我放了一个编辑框和一个按钮。在按钮的OnClick
事件中,根据我在编辑框中传递的表单名称,我想运行相应的类函数。
我尝试通过创建TDictionary
来实现此任务,其中我添加了3对值,但它不起作用。具体来说,我做了以下事情:
unit FormDU;
interface
type
TFormD = class(TForm)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
.............
.............
public
class function execute:boolean;
..........
..........
end;
var
FormD: TFormD;
MyList:TDictionary<string,TForm>;
implementation
class function TFormD.execute:boolean;
begin
FormD:= TFormD.Create(nil);
MyList:= TDictionary<string,TForm>.create;
MyList.Add('FormA',TFormA);
MyList.Add('FormB',TFormB);
MyList.Add('FormC',TFormC);
FormD.showmodal;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
begin
// Here I check whether the text in Edit1 box has the value of one of the
// keys that are included in the MyList dictionary and if yes I want to
// trigger the class function execute of the appropriate form...
if MyList.ContainsKey(Edit1.text) then // suppose that text= formA
MyList.Items[Edit1.text].execute // which doesn't work....
// I thought that the 'Items' method of the dictionary would return back
// to me the appropriate form type - which is connected to the specific
// key - and thus I could call each form's class function execute()
end;
我不知道如何解决这个问题。
答案 0 :(得分:2)
您的方法存在两个问题:
您的TDictionary
被声明为保存TForm
个对象指针,但您的代码正在尝试插入TForm
- 派生类类型。那将无法编译。
您的表单类不是从具有Execute()
方法的公共基类派生的。因此,您无法直接从TDictionary
检索值并直接致电Execute
。您将不得不求助于使用RTTI来查找和调用Execute()
。
有一些可行的方法可以解决这个问题:
从公共基类派生您的Form类,并在TDictionary
中存储该基类的派生类:
unit FormBaseU;
interface
uses
Forms;
type
TFormBase = class(TForm)
public
class function Execute: Boolean; virtual;
end;
TFormBaseClass = class of TFormBase;
implementation
class function TFormBase.Execute: Boolean;
begin
Result := False;
end;
end.
unit FormDU;
interface
uses
..., FormBaseU;
type
TFormD = class(TFormBase)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
...
public
class function Execute: Boolean; override;
...
end;
var
FormD: TFormD;
MyList: TDictionary<string, TFormBaseClass>;
implementation
uses
FormAU, FormBU, FormCU;
class function TFormD.Execute: Boolean;
begin
MyList := TDictionary<string, TFormBaseClass>.Create;
// make sure TFormA, TFormB, and TFormC all derive
// from TFormBase and override Execute() ...
MyList.Add('FormA', TFormA);
MyList.Add('FormB', TFormB);
MyList.Add('FormC', TFormC);
FormD := TFormD.Create(nil);
FormD.ShowModal;
FormD.Free;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
var
FormClass: TFormBaseClass;
begin
if MyList.TryGetValue(Edit1.Text, FormClass) then
FormClass.Execute;
end;
做类似的事情,但使用interface
而不是基类(这只适用于对象,而不是类类型):
unit MyIntfU;
interface
type
IMyIntf = interface
['{41BEF2B6-C27F-440E-A88B-9E5CF8840034}']
function Execute: Boolean;
end;
implementation
end.
unit FormDU;
interface
uses
..., MyIntfU;
type
TFormD = class(TForm, MyIntf)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
...
public
function Execute: Boolean;
...
end;
var
FormD: TFormD;
MyList: TDictionary<string, TForm>;
implementation
uses
FormAU, FormBU, FormCU;
function TFormD.Execute: Boolean;
begin
MyList := TDictionary<string, TForm>.Create;
// make sure TFormA, TFormB, and TFormC are all
// instantiated beforehand and implement IMyIntf ...
MyList.Add('FormA', FormA);
MyList.Add('FormB', FormB);
MyList.Add('FormC', FormC);
FormD := TFormD.Create(nil);
FormD.ShowModal;
FormD.Free;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
var
Form: TForm;
Intf: IMyIntf;
begin
if MyList.TryGetValue(Edit1.Text, Form) then
begin
if Supports(Form, IMyIntf, Intf) then
Intf.Execute;
end;
end;
根本不在TDictionary
中存储类/对象,而是存储实际的类方法:
unit FormDU;
interface
uses
...;
type
TFormD = class(TForm)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
...
public
class function Execute: Boolean;
...
end;
TMyClassMethod = function: Boolean of object;
var
FormD: TFormD;
MyList: TDictionary<string, TMyClassMethod>;
implementation
uses
FormAU, FormBU, FormCU;
class function TFormD.Execute: Boolean;
begin
MyList := TDictionary<string, TMyClassMethod>.Create;
MyList.Add('FormA', TFormA.Execute);
MyList.Add('FormB', TFormB.Execute);
MyList.Add('FormC', TFormC.Execute);
FormD := TFormD.Create(nil);
FormD.ShowModal;
FormD.Free;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
var
Meth: TMyClassMethod;
begin
if MyList.TryGetValue(Edit1.Text, Meth) then
Meth;
end;