Delphi在参数中传递类型

时间:2015-06-10 19:41:29

标签: delphi delphi-xe2

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

//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 个答案:

答案 0 :(得分:3)

你要求的是:

  1. 从公开要暴露您要访问的字段的公共基类派生各种Form类:

    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. 如果无法使用公共基类,请改用接口:

    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;