an example, I need to do this to solve a problem in a framework I am developing :
//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;
The compiler does not accept this line:
AClassType (aform).edtUser.text
One solution would be to use:
Uses
UnitofTForm1;
The procedure (aform: TForm; AClassType: TForm1);
begin
ShowMessage (AClassType (aform).edtUser.text);
end;
But I can not do so because they are giving circular reference and I need some decoupling in my framework
Is there any way to make typecast passing as parameter the type of form or is there another way to do this ?
What you are asking for can be done by either:
deriving the various Form classes from a common base class that exposes the field you want to access:
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;
or, use Generics:
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;
if a common base class is not possible, use an interface instead:
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;
or, use legacy RTTI (only works with published properties):
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;
or, use extended RTTI (works with all fields and visibility):
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;