Delphi 在参数中传递类型
Delphi passing Types in parameters
一个例子,我需要这样做来解决我正在开发的框架中的问题:
//Unit2 :
procedure A(aForm : TForm; AClassType: TFormClass);
begin
ShowMessage (AClassType(aForm).edtUser.text);
end;
...
//Unit1 :
Uses Unit2;
begin
form1 := TForm1.Create;
Try
A(form1, TForm1);
Finally
form1.Free;
End;
end;
编译器不接受这一行:
AClassType (aform).edtUser.text
一种解决方案是使用:
Uses
UnitofTForm1;
The procedure (aform: TForm; AClassType: TForm1);
begin
ShowMessage (AClassType (aform).edtUser.text);
end;
但我不能这样做,因为他们给出了循环引用,我需要在我的框架中进行一些解耦
有什么方法可以使类型转换作为表单类型的参数传递,或者有其他方法可以做到这一点吗?
您所要求的可以通过以下任一方式完成:
从公开您要访问的字段的公共基础 class 派生各种表单 classes:
procedure A(aForm : TBaseForm);
begin
ShowMessage(aForm.edtUser.Text);
end;
type
TBaseForm = class(TForm)
edtUser: TEdit;
...
end;
TDerivedForm = class(TBaseForm)
...
end;
...
frm := TDerivedForm.Create;
try
A(frm);
finally
frm.Free;
end;
或者,使用泛型:
type
TBaseForm = class(TForm)
edtUser: TEdit;
...
end;
TMyClass = class
class procedure A<T: TBaseForm>(aForm : T);
end;
class procedure TMyClass.A<T>(aForm : T);
begin
ShowMessage(aForm.edtUser.Text);
end;
frm := TDerivedForm.Create;
try
A<TDerivedForm>(frm);
finally
frm.Free;
end;
如果无法使用通用基础 class,请改用接口:
type
IMyFormAccess = interface
function GetUserText: string;
end;
procedure A(aForm : IMyFormAccess);
begin
ShowMessage(aForm.GetUserText);
end;
type
TForm1 = class(TForm, IMyFormAccess)
...
function GetUserText: string;
...
end;
function TForm1.GetUserText: string;
begin
Result := edtUser.Text;
end;
...
frm := TForm1.Create;
try
A(frm as IMyFormAccess);
finally
frm.Free;
end;
或者,使用旧版 RTTI(仅适用于已发布的属性):
uses
TypInfo;
procedure A(aForm : TForm);
var
Edt: TEdit;
begin
Edt := TEdit(GetObjectProp(aForm, 'edtUser', TEdit));
if Edt <> nil then
ShowMessage(Edt.Text);
end;
frm := TForm1.Create;
try
A(frm);
finally
frm.Free;
end;
或者,使用扩展的 RTTI(适用于所有字段和可见性):
uses
System.Rtti;
procedure A(aForm : TForm);
var
Ctx: TRttiContext;
Fld: TRttiField;
Value: TValue;
Edt: TEdit;
begin
Fld := Ctx.GetType(aForm.ClassType).GetField('edtUser');
if Fld <> nil then
begin
Value := Fld.GetValue(aForm);
if (not Value.IsEmpty) and Value.IsObject then
begin
Edt := Value.AsObject as TEdit;
ShowMessage(Edt.Text);
end;
end;
end;
frm := TForm1.Create;
try
A(frm);
finally
frm.Free;
end;
一个例子,我需要这样做来解决我正在开发的框架中的问题:
//Unit2 :
procedure A(aForm : TForm; AClassType: TFormClass);
begin
ShowMessage (AClassType(aForm).edtUser.text);
end;
...
//Unit1 :
Uses Unit2;
begin
form1 := TForm1.Create;
Try
A(form1, TForm1);
Finally
form1.Free;
End;
end;
编译器不接受这一行:
AClassType (aform).edtUser.text
一种解决方案是使用:
Uses
UnitofTForm1;
The procedure (aform: TForm; AClassType: TForm1);
begin
ShowMessage (AClassType (aform).edtUser.text);
end;
但我不能这样做,因为他们给出了循环引用,我需要在我的框架中进行一些解耦
有什么方法可以使类型转换作为表单类型的参数传递,或者有其他方法可以做到这一点吗?
您所要求的可以通过以下任一方式完成:
从公开您要访问的字段的公共基础 class 派生各种表单 classes:
procedure A(aForm : TBaseForm); begin ShowMessage(aForm.edtUser.Text); end;
type TBaseForm = class(TForm) edtUser: TEdit; ... end; TDerivedForm = class(TBaseForm) ... end; ... frm := TDerivedForm.Create; try A(frm); finally frm.Free; end;
或者,使用泛型:
type TBaseForm = class(TForm) edtUser: TEdit; ... end; TMyClass = class class procedure A<T: TBaseForm>(aForm : T); end; class procedure TMyClass.A<T>(aForm : T); begin ShowMessage(aForm.edtUser.Text); end;
frm := TDerivedForm.Create; try A<TDerivedForm>(frm); finally frm.Free; end;
如果无法使用通用基础 class,请改用接口:
type IMyFormAccess = interface function GetUserText: string; end; procedure A(aForm : IMyFormAccess); begin ShowMessage(aForm.GetUserText); end;
type TForm1 = class(TForm, IMyFormAccess) ... function GetUserText: string; ... end; function TForm1.GetUserText: string; begin Result := edtUser.Text; end; ... frm := TForm1.Create; try A(frm as IMyFormAccess); finally frm.Free; end;
或者,使用旧版 RTTI(仅适用于已发布的属性):
uses TypInfo; procedure A(aForm : TForm); var Edt: TEdit; begin Edt := TEdit(GetObjectProp(aForm, 'edtUser', TEdit)); if Edt <> nil then ShowMessage(Edt.Text); end;
frm := TForm1.Create; try A(frm); finally frm.Free; end;
或者,使用扩展的 RTTI(适用于所有字段和可见性):
uses System.Rtti; procedure A(aForm : TForm); var Ctx: TRttiContext; Fld: TRttiField; Value: TValue; Edt: TEdit; begin Fld := Ctx.GetType(aForm.ClassType).GetField('edtUser'); if Fld <> nil then begin Value := Fld.GetValue(aForm); if (not Value.IsEmpty) and Value.IsObject then begin Edt := Value.AsObject as TEdit; ShowMessage(Edt.Text); end; end; end;
frm := TForm1.Create; try A(frm); finally frm.Free; end;