在DelphiInterface上实现Dynamic_cast以获取基础对象类的任何方法

Any way to implement dynamic_cast on a DelphiInterface to obtain underlying objects class?

本文关键字:对象 方法 任何 获取 DelphiInterface 实现 Dynamic cast      更新时间:2023-10-16

我正在编写代码,以在不同的后端系统上实现一组通用功能。(例如,在不同的订单处理系统中提高销售订单(。我已经抽象了这些功能,并为这些功能定义了Delphi样式接口。为了允许在不同的后端系统中进行分阶段实现,每个系统都可以支持不同的功能块。(例如,"提高销售订单"功能(。因此,有一个核心API接口,它允许我们找出安装了哪些功能(有功能接口(,并获得一个特定的命名功能(每个命名功能都有其自己的接口(。

因此,我正在作为一系列对象类实现,该对象类同时实现IAPICAILAIBE接口和特定函数接口(例如,Iapiraisesalesorder接口(。IAPICAICAIBALY接口具有方法CanInstallto,该方法确定颗粒功能是否可以加载到核心API接口中。

我想做的是确定我要安装的API是否是此模块的正确类型的API。

我最初指定的是将iinterface传递到caninstallto,但是我找不到将其施放到对象的任何方法,以便我可以使用Dynamic_cast来确定该类是否插入了。

查看文档delphiinterface包括运算符过载以获取基础指针。我希望这应该有效地成为C 术语中可VTable的对象指针 - 因为在C 项中,可以用多个继承实现接口。

但是,我尚未设法找到可以将其投入对象指针的代码。

i可以在IAPIInterface中包含一个"签名"并进行检查,但这不允许我使用相同的对象类实现多种类型的后端(使用接口可以允许我这样做(。我可以允许一种"支持签名"方法实现多种类型的后端...但是,如果我有一个具有类继承的对象,我应该能够使用dynamic_cast。

目前,我已经更改了规格以将TComponent *传递给Caninstallto,但是这要求使用TCOMPONENT作为不是Probem的基类,但不符合使用抽象接口的一般概念。

此代码不起作用,但要了解我要做的事情:

bool TAPICapabilityModule::CanInstallTo(_di_IInterface Target)
{
bool              blRc=false;
TWantedAPIType  * pAPI;
  if((pAPI=dynamic_cast<TWantedAPIType *>(Target))!=NULL)
  { // continue with other checks if needed
    if(pAPI->Capability[MY_CAPABILTY_ID]==NULL)
    {
      blRc=true;
    }
  }
  return(blRc);
}

我目前正在使用tcomponent *作为核心API实现,但是我想知道是否有人知道如何完全通过接口完成此操作?

我发现了一个模板辅助功能,该功能将完全按照我的要求。我正在运行RIO(10.3.1(,并且在系统文件Systobj.h-中实现了这一点 - lt; system.hpp&gt;应该包括在内。(反过来,几乎所有使用RTL的所有内容都可能包括(。

此文件中的相关代码(它确实可以完成我要寻找的内容,包装对象指针上的Dynamic_cast(

  // --------------------------------------------------------------------------
  // Object <-> Interface cast helpers
  // --------------------------------------------------------------------------
  struct __declspec(uuid("{CEDF24DE-80A4-447D-8C75-EB871DC121FD}")) __IObjCastGUIDHolder;
  template <typename DESTOBJ>
  DESTOBJ* _interfaceToObjectCast(IInterface* src)
  {
    if (src)
    {
      TObject *obj = 0;
      src->QueryInterface(__uuidof(__IObjCastGUIDHolder), reinterpret_cast<void**>(&obj));
      return dynamic_cast<DESTOBJ*>(obj);
    }
    return 0;
  }

可以这样使用:

bool TAPICapabilityClass::CanInstallTo(_di_IInterface Target)
{
bool              blRc=false;
TWantedAPIType  * pAPI;
  if((pAPI=dynamic_cast<TWantedAPIType>(Target))!=NULL)
  { // continue with other checks if needed
    if(pAPI->Capability[MY_CAPABILTY_ID]==NULL)
    {
      blRc=true;
    }
  }
  return(blRc);
}

从消费应用程序的角度来看,它仍然是这样的抽象接口:

void TApplicationUnit::InstallCapability(TComponent *pAPI, TObject *pCapability)
{
_di_IAPICore        diAPI;
_di_IAPICapability  diCapability
  if( (System::Sysutils::Supports(pAPI, _uuidof(IAPICore), (void **)(&diAPI))) &&
      (System::Sysutils::Supports(pCapability, _uuidof(IAPICapability), (void **)(&diCapability))) &&
      (diCapability->CanInstallTo(diAPI)) )
  {
    diAPI->InstallCapability(diCapability);
  }
} 

我还没有达到可以正确测试代码(但它编译(的地步。

评论中有一些有效的观点,即是否施放摘要与对象的接口是良好的设计。正如我所看到的那样,我希望能够在抽象类型之间进行动态cast。用例的设计目标要求实施各种后台系统,从消费应用程序中隐藏了,但是在多个类之间拆分功能要求实现类别在同一实现中了解其他类别(但不一定是其内部的(工作(。

从我所知道的delphi的小小的相似之处中,同一单元中的delphi类能够以其他类不能仅仅因为它们在同一单元中而无法相互访问。在许多情况下,您希望将抽象界面呈现给消费类,但是在实施课程的内部,您需要对其他类别进行更详细的知识。