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;

但我不能这样做,因为他们给出了循环引用,我需要在我的框架中进行一些解耦

有什么方法可以使类型转换作为表单类型的参数传递,或者有其他方法可以做到这一点吗?

您所要求的可以通过以下任一方式完成:

  1. 从公开您要访问的字段的公共基础 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;
    
  2. 或者,使用泛型:

    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;
    
  3. 如果无法使用通用基础 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;
    
  4. 或者,使用旧版 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;
    
  5. 或者,使用扩展的 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;