com 包容类实现多个双重接口
来源:互联网 发布:淘宝介入对卖家的影响 编辑:程序博客网 时间:2024/05/27 01:05
有时项目组件X中,包含类CCMyComClsInner 已经实现了接口 ICMyComClsInner 中的虚方法GetInnerData,但是后期项目的发展可能要新增功能,但是又不能影响之前已经存在的功能。因为原来的功能适用于老客户那边的环境,新客户这边的环境需要新的功能实现,所以在不改变现状的情况下,新增接口ICMyComClsInner2并创建新的虚方法GetInnerData2。此方式很类似于微软对IE内核的访问方式 IWebBrowser2 ->Navigate2 以达到新老接口并存的状况,同时也方便后期的维护和移植。
第一步:修改现存接口描述文件IDL,增加新接口
// 此文件将由 MIDL 工具处理以
// 产生类型库(TestComInner.tlb)和封送处理代码。
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
dual,
helpstring("IComponentRegistrar 接口"),
pointer_default(unique)
]
interface IComponentRegistrar : IDispatch
{
[id(1)] HRESULT Attach([in] BSTR bstrPath);
[id(2)] HRESULT RegisterAll();
[id(3)] HRESULT UnregisterAll();
[id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
[id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID);
[id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
};
[
object,
uuid(2935891B-54B8-4F2B-907E-B4A8E697E360),
dual,
nonextensible,
helpstring("ICMyComClsInner 接口"),
pointer_default(unique)
]
interface ICMyComClsInner : IDispatch{
[id(1), helpstring("方法GetInnerData")] HRESULT GetInnerData([in] LONG value, [out,retval] LONG* retvalue);
};
[
object, ///代表是接口对象
uuid(5DFDCCBF-773B-4900-9B41-42C63B0D4036), ///uuid可以通过GUID生成工具自动生成
dual, ///代表此接口是双重接口
nonextensible,
helpstring("ICMyComClsInner2 接口"),
pointer_default(unique)
]
interface ICMyComClsInner2 : IDispatch{
[id(1), helpstring("方法GetInnerData2")] HRESULT GetInnerData2([in] LONG value, [out,retval] LONG* retvalue);
};
[
uuid(29E12303-85F0-4359-81F6-03A02E68FEBD),
version(1.0),
helpstring("TestComInner 1.0 类型库"),
custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{6638F0BC-D0A9-4032-969B-A5CFFCF6F58A}")
]
library TestComInnerLib
{
importlib("stdole2.tlb");
[
uuid(6638F0BC-D0A9-4032-969B-A5CFFCF6F58A),
helpstring("ComponentRegistrar 类")
]
coclass CompReg
{
[default] interface IComponentRegistrar;
};
[
uuid(2DD8C6C8-CA25-4398-BA39-872FA9B83CB3),
helpstring("CMyComClsInner Class")
]
coclass CMyComClsInner ///coclass 说明是包含类
{
[default] interface ICMyComClsInner;
interface ICMyComClsInner2; ///增加新的接口标示
};
};
Interface definition file 是一个接口文件,它应该由用户利用IDL(interface definition language)语言编辑uuidgen产生的IDL原型文件而成。IDL是一种用来说明操作(过程或函数),操作的参数以及数据类型的语言,它在语法上继承于C语言,但形式上和C语言有很多不同,当然也有一些符合自己特点的适合于分布计算的特殊语法。具体可参看DCE RPC specification中的IDL language specification部分。
第二步:修改CCMyComClsInner的头文件CCMyComClsInner.h,增加接口实现和入口点声明
// CCMyComClsInner
class ATL_NO_VTABLE CCMyComClsInner :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CCMyComClsInner, &CLSID_CMyComClsInner>,
public IDispatchImpl<ICMyComClsInner, &IID_ICMyComClsInner, &LIBID_TestComInnerLib, /*wMajor =*/ 1, /*wMinor =*/ 0> ,
public IDispatchImpl<ICMyComClsInner2, &IID_ICMyComClsInner2, &LIBID_TestComInnerLib, /*wMajor =*/ 1, /*wMinor =*/0>
{
public:
CCMyComClsInner()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_CMYCOMCLSINNER)
BEGIN_COM_MAP(CCMyComClsInner)
COM_INTERFACE_ENTRY(ICMyComClsInner)
COM_INTERFACE_ENTRY(ICMyComClsInner2)
//COM_INTERFACE_ENTRY(IDispatch)
////由于是CCMyComClsInner实现了多个双重接口(ICMyComClsInner 和 ICMyComClsInner2),
///所以必须用 COM_INTERFACE_ENTRY2 替换原来的 COM_INTERFACE_ENTRY 来明确声明到底是通过哪一个接口来实现IDispatch的回调响应
/// 如果不改,会爆出错误: error C2594: “static_cast”: 从“ ::_ComMapClass *”到“IDispatch *
COM_INTERFACE_ENTRY2(IDispatch,ICMyComClsInner)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD(GetInnerData)(LONG value, LONG* retvalue);
virtual HRESULT STDMETHODCALLTYPE GetInnerData2( LONG value, LONG *retvalue );
};
OBJECT_ENTRY_AUTO(__uuidof(CMyComClsInner), CCMyComClsInner)
第三步:在 CCMyComClsInner.cpp文件中完善GetInnerData2方法。
第四步:客户端代码中增加对接口的调用
///直接创建对应组件ICMyComClsInner 接口
ICMyComClsInner * _IMyComClsInner = NULL;
HRESULT hr = CoCreateInstance(CLSID_CMyComClsInner, NULL, CLSCTX_ALL, IID_ICMyComClsInner, (void**)&_IMyComClsInner);
_IMyComClsInner->GetInnerData(123,&_res);
_IMyComClsInner->Release();
///直接创建对应组件ICMyComClsInner2接口
ICMyComClsInner2 * _IMyComClsInner2 = NULL;
HRESULT hr = CoCreateInstance(CLSID_CMyComClsInner, NULL, CLSCTX_ALL, IID_ICMyComClsInner2, (void**)&_IMyComClsInner2);
_IMyComClsInner2->GetInnerData2(123,&_res);
_IMyComClsInner->Release();
///通过跟接口(IUnknown),查询的方式获取目的组件接口
IDispatch * _IDispatch =NULL;
_res = 0;
hr = CoCreateInstance(CLSID_CMyComClsInner, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&_IDispatch);
_IDispatch->QueryInterface(IID_ICMyComClsInner,(void**)&_IMyComClsInner);
_IMyComClsInner->GetInnerData(123,&_res);
_IMyComClsInner->Release();
ICMyComClsInner2 * _IMyComClsInner2 = NULL;
_IDispatch->QueryInterface(IID_ICMyComClsInner2,(void**)&_IMyComClsInner2);
_IMyComClsInner2->GetInnerData2(123,&_res);
_IMyComClsInner2->QueryInterface(IID_ICMyComClsInner,(void**)&_IMyComClsInner);
_IMyComClsInner->GetInnerData(123,&_res);
_IMyComClsInner2->Release();
- com 包容类实现多个双重接口
- 用MFC写的COM如何实现包容或聚合?
- 聚合 包容 COM
- COM对象包容
- COM连接点 - 一个COM接口实现多个连接点(3)
- COM连接点 - Part III - 一个COM接口实现多个连接点
- COM 的聚合和包容
- COM笔记-包容与聚合
- COM特性 包容和聚合
- COM笔记-包容与聚合
- COM笔记-包容与聚合
- COM特性 包容和聚合
- COM学习笔记(九):包容
- 一个接口,多个实现类
- COM复用的中Containment(包容)和Aggregation(聚合)的实现
- COM复用的中Containment(包容)和Aggregation(聚合)的实现
- COM复习(一) : COM复用的中Containment(包容)和Aggregation(聚合)的实现
- com学习笔记(7)包容与聚合
- java多线程之路之Callable与Future—Core Java学习
- 关于CentOS设置系统时间命令介绍
- Windows系统不关机故障的解决方法
- spring 特性介绍
- js 二维码
- com 包容类实现多个双重接口
- 为何PB应用程序运行时弹出过滤条件的设置窗口?(PB开发小技巧)
- [STL]next_permutation全排列
- 笔记本电脑开机报错故障的原因及解决办法
- MYSQL管理之主从同步管理
- 一步一步了解Cocos2dx 3.0 正式版本开发环境搭建(Win32/Android)
- linux kernel阅读(一) 进程的生命周期
- 一个难题: 怎样写一个输出自己源代码的程序?
- google打不开解决办法