65.9K
CodeProject 正在变化。 阅读更多。
Home

IDispatchImplEx - 用于多接口分派的模板类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (9投票s)

2009年1月24日

CPOL

2分钟阅读

viewsIcon

37624

downloadIcon

386

用于实现 COM 对象的多接口分发的 C++ 模板类,基于 typeinfo 进行驱动,支持双接口和纯接口。

引言

模板类支持实现可脚本化的 COM 对象。可脚本化的对象必须实现 COM 接口 IDispatch,而 ATL 通过模板类 IDispatchImpl 支持此接口。IDispatchImpl 仅支持对单个双接口进行分发。如果您的 COM 对象通过聚合或继承直接实现多个双接口,则 IDispatchImpl 会将分发限制为其中一个接口。此外,如果您的类仅实现非双接口(派生自 IUnknown 的接口),则 IDispatchImpl 将根本不起作用。

提供了两个模板类来实现多接口分发

  • IDispatchImplEx - 替换 ATL::IDispatchImpl,并基于 typeinfo 对多个双接口进行分发。如果继承自此模板的类实现多个双接口,则很有用。该模板支持对聚合 COM 对象进行分发。
  • PureDispatchImpl - 用于实现纯 IDispatch 接口,该接口基于 typeinfo 对一个或多个纯接口(派生自 IUnknown 的接口)进行分发。

背景

ATL 包含模板类 IDispatchImpl,它基于 typeinfo 对单个双接口(派生自 IDispatch 的接口)进行分发。

实现双接口的多接口分发

要实现多个双接口的多接口分发,请使用 IDispatchImplEx 代替 IDispatchImpl

class ATL_NO_VTABLE CMyClass : 
     public IProvideClassInfo2Impl<&CLSID_MyClass,&GUID_NULL, &LIBID_MyModule>,
     public IDispatchImplEx<IMyInterface, &IID_IMyInterface, 
            &CLSID_MyClass, &LIBID_MyModule>,

如果接口定义在导入的类型库中,这仍然有效

class ATL_NO_VTABLE CMyClass : 
     public IProvideClassInfo2Impl<&CLSID_MyClass,&GUID_NULL, &LIBID_MyModule>,
     public IDispatchImplEx<IMyInterface, &IID_IMyInterface, 
            &CLSID_MyClass, &LIBID_ImportedLib>,

如果您的类支持事件,请在 IProvideClassInfo2Impl 模板中将 GUID_NULL 替换为您的事件接口的 IID。

实现对一个或多个纯接口的分发

要实现对一个或多个派生自 IUnknown 的纯接口的多接口分发,请使用 PureDispatchImpl。该实现向类添加单个 IDispatch 实现,并使用 typeinfo 对纯接口进行分发。但是,有一个要求,即接口必须提供 type info。

class ATL_NO_VTABLE CMyClassWithNoDuals : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CMyClassWithNoDuals, &CLSID_MyClassWithNoDuals>,
    public PureDispatchImpl<&CLSID_MyClassWithNoDuals, &LIBID_MyLib>,
    public IPure1,
    public IPure2,

示例代码:

IDL 代码

importlib("ImportedLib.tlb"); // Interface IC is defined here

//Dual interface definitions
interface IA : IDispatch
{
    HRESULT MethodOnIA();
};
interface IB : IDispatch
{
    HRESULT MethodOnIB();
};

// Pure (non-dual) interface definitions


interface IPure1 : IUnknown
{
    HRESULT DispMe();
};
interface IPure2 : IUnknown
{
    HRESULT DispMeAgain();
};
// Class definitions
// MyClass implements three dual interfaces,
// one defined in an imported type library
coclass MyClass
{
    [default] interface IA;
    interface IB;
    interface IC; // Defined in ImportedLib.tlb
};
// MyClassWithNoDuals implements three pure interfaces, 
// one of them defined in an imported type library 
coclass MyClassWithNoDuals
{
    [default] interface IPure1;
    interface IPure2;
    interface ID; // Defined in ImportedLib.tlb
};

C++ 实现

// Implementation of class with multiple dual interfaces
class ATL_NO_VTABLE CMyClass : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public IProvideClassInfo2Impl<&CLSID_MyClass,&GUID_NULL, &LIBID_MyLib>, 
    public IDispatchImplEx<IA, &IID_IA, &CLSID_MyClass, &LIBID_MyLib>,
    public IDispatchImplEx<IB, &IID_IB, &CLSID_MyClass, &LIBID_MyLib>,
    public IDispatchImplEx<IC, &IID_IC, &CLSID_MyClass, &LIBID_ImportedLib>,
    public CComCoClass<CMyClass, &CLSID_MyClass>,
    public ISupportErrorInfo
{
    ..standard ATL implementation
// Implementation of class with multiple pure interfaces
class ATL_NO_VTABLE CMyClassWithNoDuals : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CMyClassWithNoDuals, &CLSID_MyClassWithNoDuals>,
    public PureDispatchImpl<&CLSID_MyClassWithNoDuals, &LIBID_MyLib>,
    public IPure1,
    public IPure2,
    public ID,
    public ISupportErrorInfo,
{
    ..standard ATL implementation
    BEGIN_COM_MAP(CMyClassWithNoDuals)
        COM_INTERFACE_ENTRY(IPure1)
        COM_INTERFACE_ENTRY(IPure2)
        COM_INTERFACE_ENTRY(ID)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(ISupportErrorInfo)
    END_COM_MAP()
    ...standard implementation

脚本示例,VB 脚本客户端

Dim instanceOfMyClass
... got instanceOfMyClass from somewhere
' Regardless of which interface I got hold of, 
' I can script towards all methods on the class:
instanceOfMyClass.MethodOnIA
instanceOfMyClass.MethodOnIB
instanceOfMyClass.MethodOnIC


Dim instanceOfMyClassWithNoDuals
... got instanceOfMyClassWithNoDuals from somewhere
' Regardless of which interface I got hold of, 
' I can script towards all methods on the class:
instanceOfMyClassWithNoDuals.DispMe
instanceOfMyClassWithNoDuals.DispMeAgain
instanceOfMyClassWithNoDuals.MethodOnID

历史

  • 1.0 - 1998-05-07:初始版本。
  • 2.0 - 1998-11-19:转换为 ATL 3.0。
  • 3.0 - 1999-07-10:如果已实现,则使用 IProvideClassInfo
  • 4.0 - 2002-11-14:支持实现纯 IDispatch 实现;添加了 PureDispatchImpl
© . All rights reserved.