假设我们有两个类Connection和RecordSet.类RecordSet要使用Connecion
类中的某个类型的句柄,如数据库Handle,同时Connection对象的操作要返回
一个RecordSet对象. 那么如何将Connection对象中的这个数据库Handle传递
到RecordSet对象中呢,我们可以采用ATL/COM中的双接口的技术。
我们可以这样声明,RecordSet类
class ATL_NO_VTABLE CRecordSet public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CRecordSet, &CLSID_RecordSet>,
public ISupportErrorInfo,
public IDispatchImpl<IRecordSet, &IID_IRecordSet, &LIBID_DBLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispatchImpl<IParaData, &IID_IParaData, &LIBID_DBLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
BEGIN_COM_MAP(CRecordSet)
COM_INTERFACE_ENTRY(IRecordSet)
COM_INTERFACE_ENTRY(IParaData)
COM_INTERFACE_ENTRY2(IDispatch,IRecordSet)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
成员变量:
DBHandle m_handle;
同时在头文件中声明IParaData的接口,并在实现文件中实现。
如:
STDMETHOD(setDBHandle)( LONGLONG* pHandle);
这里使用LONGLONG* 指针,是因为在IDL文件中,没有数据库
句柄这个数据类型,所以可以用LONGLONG指针,在实现文件中
进行转换。
STDMETHODIMP CRecordSet::SetDBHandle(LONGLONG* pHandle)
{
m_handle = (DBHandle)pHandle;
return S_OK;
}
好了,那么在Connection对象中如何调用这个接口,从而将这个参数传递到
RecordSet 对象中去呢?下面我们来看Connection的实现。
假设Connection对象中也有这个数据库句柄成员
DBHandle m_handle;
同时有这样一个函数,
STDMETHOD(Execute)(IRecordSet** pRecordset);
这个函数的参数在IDL文件中被设置为[out,retval].
我们要在这个函数中传递Connection对象的数据库句柄参数给RecordSet对象
要通过IParaData的接口。我们来看看代码实现片段:
HRESULT hr;
CComPtr<IRecordSet> pRecordset;
if(FAILED(hr = CoCreateInstance(__uuidof(RecordSet),NULL,CLSCTX_INPROC,
__uuidof(RecordSet),(void**)&pRecordset)))
{
return hr;
}
CComPtr<IParaData> pParaData;
hr = pRecordset->QueryInterface(IID_IPARAData,(void**)&pParaData);
if(FAILED(hr))
return hr;
pParaData->SetDBHandle(LONGLONG*)m_handle;
*ppRecordSet = pRecordset;
(*ppRecordSet )->AddRef();
好的,现在大功告成。在RecordSet对象可以成功对数据库句柄进行这种操作。