接口引用 如何从一个接口变量取得其接口类型

http://blog.sina.com.cn/s/blog_5d10e5410100hjna.html

近期在写一个类pascal解释器,对borland的RTTI机制进行了一番学习,了解了borland的RTTI机制,但本人水平有限,在学习有关接口的RTTI过程中,遇到了些无法解释的问题,在这里提出来,大家共同探讨。 
 首先说明“接口引用”这个概念在delphi中也许不存在,是我相对于“类引用”提出来的。我们知道在delphi  中有类引用的概念,定义方式如TClass   class   of  TObject,其实质是指向类RTTI的一个指针,我们可以用这个类引用实现好多动态功能。可接口就比较特殊,虽然定义语法和类定义类似,但只是一个空壳,需要通过某个具体的类来实现。虽然接口是一个空壳,但是这个空壳也有RTTI信息,可以通过TypeInfo函数得到。 
  在VCL中其实也运用了好多  “接口引用”的概念,比如IInterface中的QueryInterface函数,查询接口支持的函数supports等,但在delphi并没有类似“  Interface   of Interface”这样的句法来定义一个接口引用,而是使用一个TGUID来完成接口引用的功能。TGUID其实被定义为一个结构类型,delphi的编译器知道如何把TGUID类型转换成接口引用来使用,但对开发者来说却是不公布的。比如: 
  var  
      Obj  :   TObject; 
     m:TComponent;  
      ClassRef:  TClass;  
      Intf:  IInterface;  
      IID:  TGUID;  
  begin  
      obj  :=   TComponent.Create(nil); 
      ClassRef  :=   obj.ClassType;  //对于类变量,我们可以用类函数classType来取得它的类类型。 
      :=   obj   as  TComponent;  
      Intf  :=   m;  //把M赋给接口变量,因为TComponent实现了IInterface接口。  
     
       IID   :=   intf   ;//无法取得接口变量的接口类型?! 
       }  
  end;  
   
  归结起来,写一个函数,取得一个接口变量的接口类型(GUID): 
  function   GetIntfGUID(AIntf:  IInterface):TGUID;  
  begin  
      Result  :=   ;//如何实现?和各位继续探讨 
  end;

 

 

 

 

解释:

 unit   Unit1; 
   
  interface  
   
  uses  
      Windows,  Messages,   SysUtils,  Variants,   Classes,  Graphics,   Controls,  Forms,  
      Dialogs,  StdCtrls;  
   
  type  
     IFirstIntf=interface  
        ['{64C25101-E002-40EF-92DC-F0DFBF876B1C}']  
         function  GetName:string;  
         function  GetGUID:string;  
         function  GetIntfGUID(AIntf:   IInterface):TGUID; 
      end; 
   
     TFirstIntfClass=class(TInterfacedObject,  IFirstIntf)  
         //IFirstIntf 
         function  GetName:string;  
         function  GetGUID:string;  
         function  GetIntfGUID(AIntf:   IInterface):TGUID; 
      end; 
   
  type  
      TForm1  =   class(TForm) 
         btnSayHello:  TButton;  
         btnGUIID:  TButton;  
         lst1:  TListBox;  
         btnAllGUID:  TButton;  
         btnIntfaceToGUID:  TButton;  
         procedure  btnSayHelloClick(Sender:   TObject); 
         procedure  btnGUIIDClick(Sender:   TObject); 
         procedure  btnAllGUIDClick(Sender:   TObject); 
         procedure  btnIntfaceToGUIDClick(Sender:   TObject); 
      private 
         {   Private  declarations  
      public 
         {   Public  declarations  
      end; 
   
  var  
      Form1:  TForm1;  
   
  implementation  
   
  {$R   *.dfm} 
   
  function  TFirstIntfClass.GetName;  
  begin  
     Result:='Hello   World';  
  end;  
  procedure  TForm1.btnSayHelloClick(Sender:   TObject); 
  var  
     FirstIntfClass:TFirstIntfClass;  
     FirstIntf:IFirstIntf;  
  begin  
     FirstIntfClass:=TFirstIntfClass.Create;  
      try 
         FirstIntf:=FirstIntfClass; 
        ShowMessage(FirstIntf.GetName);  
      finally 
         FirstIntf:=nil; 
      end; 
  end;  
   
  function  TFirstIntfClass.GetGUID;  
  begin  
      if self.GetInterfaceTable.EntryCount>0  then  
        Result:=GUIDToString(Self.GetInterfaceTable.entries[0].iid) 
  end;  
  procedure  TForm1.btnGUIIDClick(Sender:   TObject); 
  var  
     FirstIntfClass:TFirstIntfClass;  
     FirstIntf:IFirstIntf;  
  begin  
     FirstIntfClass:=TFirstIntfClass.Create;  
      try 
         FirstIntf:=FirstIntfClass; 
        ShowMessage(FirstIntf.GetGUID);  
      finally 
         FirstIntf:=nil; 
      end; 
  end;  
   
  procedure  TForm1.btnAllGUIDClick(Sender:   TObject); 
  var  
      I:Integer; 
     FirstIntfClass:TFirstIntfClass;  
     FirstIntf:IFirstIntf;  
  begin  
     FirstIntfClass:=TFirstIntfClass.Create;  
      for  I:=   0   to   FirstIntfClass.GetInterfaceTable.EntryCount-1   do  begin  
        lst1.Items.Add(GUIDToString(FirstIntfClass.GetInterfaceTable.Entries[I].IID)); 
      end; 
     FirstIntfClass.Free;  
  end;  
   
  function  TFirstIntfClass.GetIntfGUID(AIntf:  IInterface):TGUID;  
  var  
      I:Integer; 
     FirstIntfClass:TFirstIntfClass;  
  begin  
     FirstIntfClass:=TFirstIntfClass.Create;  
      for  I:=0   to  FirstIntfClass.getInterfaceTable.EntryCount-1   do 
         if  FirstIntfClass.GetInterface(FirstIntfClass.getInterfaceTable.Entries[I].IID,  AIntf)   then  begin  
           Result:=FirstIntfClass.getInterfaceTable.Entries[I].IID; 
            Exit;  
         end;  
     FirstIntfClass.Free;  
  end;  
  procedure  TForm1.btnIntfaceToGUIDClick(Sender:   TObject); 
  var  
     FirstIntfClass:TFirstIntfClass;  
     FirstIntf:IFirstIntf;  
     GUID:TGUID;  
  begin  
     GUID:=FirstIntfClass.GetIntfGUID(FirstIntf); 
      if  GUID.D1>0   then 
        ShowMessage(GUIDToString(GUID));  
  end;  
   
 end.  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值