如何在Delphi 7中将一个接口转换为另一个接口?

How to cast one interface to another in Delphi 7?

我陷于以下问题:

我有一个类,该类是使用Delphi 7 XML数据绑定向导(新建->其他-> XML Databindng)从xsd文件生成的。

我需要找到一种方法来将方法添加到生成的代码中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
IXMLGlobeSettingsType = interface(IXMLNode)
    ['{9A8F5C55-F593-4C70-85D2-68FB97ABA467}']
    { Property Accessors }
    function Get_General: IXMLGeneralSettingsType;
    function Get_Projector: IXMLProjectorSettingsType;
    function Get_LineMode: IXMLLineDrawingSettingsType;

    { Methods & Properties }
    property General: IXMLGeneralSettingsType read Get_General;
    property Projector: IXMLProjectorSettingsType read Get_Projector;
    property LineMode: IXMLLineDrawingSettingsType read Get_LineMode;

    //procedure SetDefault;   {To be added}
  end;

该接口由相应的类实现,该类也由向导生成:

1
2
3
4
5
6
7
8
9
TXMLGlobeSettingsType = class(TXMLNode, IXMLGlobeSettingsType)
  protected
    { IXMLGlobeSettingsType }
    function Get_General: IXMLGeneralSettingsType;
    function Get_Projector: IXMLProjectorSettingsType;
    function Get_LineMode: IXMLLineDrawingSettingsType;
  public
    procedure AfterConstruction; override;
  end;

并且为了定义我自己的对生成代码的扩展,我定义了以下接口:

1
2
3
IDefaultable = interface
   procedure SetDefault;
end;

具有以下实现类:

1
2
3
4
DefaultableXMLGlobeSettingsType = class(TXMLGlobeSettingsType, IDefaultable)
  public
    procedure SetDefault;
  end;

但是,我刚刚意识到Delphi 7不允许我将一个接口转换为另一个接口(甚至从一个接口转换为一个对象)。因此,以下代码将引发错误:

1
2
3
4
5
6
defaultSettings : IDefaultable;    
FGlobeSettingsIntf: IXMLGlobeSettingsType; // FGlobeSettingsIntf is in fact a DefaultableXMLGlobeSettingsType

// some code

defaultSettings := FGlobeSettingsIntf as IDefaultable; // error: operator not applicable to this operand type

我几乎被困在这里。如何解决这个错误? Delphi 7中是否有一种方法(甚至是丑陋的方法)可以将接口强制转换为对象,然后又转换为另一个接口。


1
2
defaultSettings := FGlobeSettingsIntf as IDefaultable;
// error: operator not applicable to this operand type

此错误表明IDefaultable的定义不包括GUID。没有GUID,就不可能查询接口,这是as运算符在此上下文中的作用。

as运算符与右侧的接口一起使用时,是通过调用IInterface.QueryInterface来实现的。这要求将GUID与接口关联。

通过声明IDefaultable时添加GUID解决此问题。


这是Supports的用途:

1
2
3
if Supports(FGlobeSettingsIntf, IDefaultable, defaultSettings) then begin
  defaultSettings.SetDefault;
end;