Delphi在参数中传递类型

Delphi在参数中传递类型,delphi,delphi-xe2,Delphi,Delphi Xe2,例如,我需要这样做来解决我正在开发的框架中的问题: //Unit2 : procedure A(aForm : TForm; AClassType: TFormClass); begin ShowMessage (AClassType(aForm).edtUser.text); end; ... //Unit1 : Uses Unit2; begin form1 := TForm1.Create;

例如,我需要这样做来解决我正在开发的框架中的问题:

//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;
但我不能这样做,因为它们提供了循环引用,我需要在我的框架中进行一些解耦


是否有任何方法可以使typecast作为参数传递为表单的类型,或者有其他方法可以做到这一点?

您所要求的可以通过以下方式之一实现:

  • 从公开要访问的字段的公共基类派生各种表单类:

    procedure A(aForm : TBaseForm); 
    begin 
      ShowMessage(aForm.edtUser.Text);
    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; 
    

  • 或者,使用传统RTTI(仅适用于已发布的属性):

  • 或者,使用扩展RTTI(适用于所有字段和可见性):


  • 您是否有多个不同的
    TFormxxx
    类?它们都是从同一个基类派生的吗?是的,我有多个Tformxx类,它们是从TFORM派生的。我将尝试其中一些方法并返回,ThanksI分析了所有方法,最后一种方法可以解决我的问题,但似乎有一个错误。字段Fld从未初始化,并导致运行时错误地址冲突。你能看到最新代码中缺少了什么吗?我修复了错误。这只是一个输入错误,
    Value:=
    调用
    TRttiType.GetField()
    时应该是
    Fld:=
    。解决了我的问题。再次感谢雷米!
    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;
    
    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;
    
    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;
    
    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;