有什么方法可以在 DelphiInterface 上实现 dynamic_cast 以获得基础对象 class?
Any way to implement dynamic_cast on a DelphiInterface to obtain underlying objects class?
我正在编写代码来实现跨不同后端系统的一组通用功能。 (例如在不同的订单处理系统中提出销售订单)。我已经抽象了这些功能并为它们定义了 Delphi 风格的接口。为了允许在不同的后端系统中分阶段实施,每个系统都可以支持不同的功能块。 (例如 'raise sales order' 功能)。所以有一个核心的API接口可以让我们找出安装了什么能力(有一个能力接口),并获得一个特定的命名能力(其中每个命名能力都有自己的接口)。
所以我作为一系列对象 classes 来实现,它们同时实现了 IAPICapability 接口和一个特定的函数接口(例如 IAPIRaiseSalesOrder 接口) . IAPICapability 接口有一个 CanInstallTo 方法,它确定是否可以将特定功能加载到核心 API 接口中。
我想要做的是确定我尝试安装的 API 是否是此模块的 API 的正确类型。
我最初指定将 IInterface 传递给 CanInstallTo,但我找不到任何方法将其转换为对象,以便我可以使用 dynamic_cast 来确定它是否是 class 所期望的插入。
查看文档,Delphi接口包括运算符重载以获取底层指针。我希望这在 C++ 术语中实际上是一个带有 vtable 的对象指针 - 因为在 C++ 术语中接口是通过多重继承实现的。
但是我还没有设法找到可以将其转换为对象指针的代码。
我可以在 IAPI 接口中包含一个 'Signature' 并检查它,但这不允许我使用相同的对象 class 来实现多种类型的后端(使用接口应该允许我这样做)。我可以允许 'SupportsSignature' 方法实现多种类型的后端......但是如果我有一个具有 class 继承的对象,我应该能够使用 dynamic_cast.
现在我已经更改了规范以将 TComponent * 传递给 CanInstallTo,但这要求使用 TComponent 作为基础 class 这不是一个问题,但不符合使用的一般概念抽象接口。
这段代码不起作用,但可以让我了解我正在尝试做什么:
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 中实现 - 这应该包含在 中(它可能包含在几乎所有使用 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);
}
}
我还没有达到可以正确测试代码的程度(但它可以编译)。
关于是否投射摘要,评论中有一些有效的观点
对象的接口是好的设计。正如我在 C++ 多重继承方面看到的那样,我希望能够在抽象类型之间 dynamic_cast 。用例的设计目标要求各种后台系统的实现对消费应用程序是隐藏的,但是在多个 类 之间拆分功能需要实现 类 了解另一个 类 在同一个实现中(但不一定是它们的内部工作方式)。
据我所知,Delphi 有一个松散的平行关系,其中 Delphi 类 在同一个单元中能够以其他 [=33= 的方式相互访问] 不能仅仅因为他们在同一个单位。在许多情况下,您希望将抽象接口呈现给消费 类,但在您的实现内部 类 您需要更详细地了解其他 类。
我正在编写代码来实现跨不同后端系统的一组通用功能。 (例如在不同的订单处理系统中提出销售订单)。我已经抽象了这些功能并为它们定义了 Delphi 风格的接口。为了允许在不同的后端系统中分阶段实施,每个系统都可以支持不同的功能块。 (例如 'raise sales order' 功能)。所以有一个核心的API接口可以让我们找出安装了什么能力(有一个能力接口),并获得一个特定的命名能力(其中每个命名能力都有自己的接口)。
所以我作为一系列对象 classes 来实现,它们同时实现了 IAPICapability 接口和一个特定的函数接口(例如 IAPIRaiseSalesOrder 接口) . IAPICapability 接口有一个 CanInstallTo 方法,它确定是否可以将特定功能加载到核心 API 接口中。
我想要做的是确定我尝试安装的 API 是否是此模块的 API 的正确类型。
我最初指定将 IInterface 传递给 CanInstallTo,但我找不到任何方法将其转换为对象,以便我可以使用 dynamic_cast 来确定它是否是 class 所期望的插入。
查看文档,Delphi接口包括运算符重载以获取底层指针。我希望这在 C++ 术语中实际上是一个带有 vtable 的对象指针 - 因为在 C++ 术语中接口是通过多重继承实现的。
但是我还没有设法找到可以将其转换为对象指针的代码。
我可以在 IAPI 接口中包含一个 'Signature' 并检查它,但这不允许我使用相同的对象 class 来实现多种类型的后端(使用接口应该允许我这样做)。我可以允许 'SupportsSignature' 方法实现多种类型的后端......但是如果我有一个具有 class 继承的对象,我应该能够使用 dynamic_cast.
现在我已经更改了规范以将 TComponent * 传递给 CanInstallTo,但这要求使用 TComponent 作为基础 class 这不是一个问题,但不符合使用的一般概念抽象接口。
这段代码不起作用,但可以让我了解我正在尝试做什么:
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 中实现 - 这应该包含在
此文件中的相关代码(正是我要找的,包装对象指针上的 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);
}
}
我还没有达到可以正确测试代码的程度(但它可以编译)。
关于是否投射摘要,评论中有一些有效的观点 对象的接口是好的设计。正如我在 C++ 多重继承方面看到的那样,我希望能够在抽象类型之间 dynamic_cast 。用例的设计目标要求各种后台系统的实现对消费应用程序是隐藏的,但是在多个 类 之间拆分功能需要实现 类 了解另一个 类 在同一个实现中(但不一定是它们的内部工作方式)。
据我所知,Delphi 有一个松散的平行关系,其中 Delphi 类 在同一个单元中能够以其他 [=33= 的方式相互访问] 不能仅仅因为他们在同一个单位。在许多情况下,您希望将抽象接口呈现给消费 类,但在您的实现内部 类 您需要更详细地了解其他 类。