在COM中对象要通过class factory的接口(通常是IClassFactory)来创建。在ATL中,class factory也是从CComObjectRootEx派生的COM类,它跟普通的COM类一样,也通过CComObject或其同伴类将逻辑功能跟生存期管理分离。
在ATL中,class factory类和普通类对象的创建都可以通过被称为“创建者”的模板类来创建。
template <class T1>
class CComCreator
{
public:
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
{
HRESULT hRes = E_OUTOFMEMORY;
T1* p = NULL;
p = new T1(pv);
if (p != NULL)
{
p->SetVoid(pv);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalFinalConstructRelease();
if (hRes == S_OK)
hRes = p->QueryInterface(riid, ppv);
if (hRes != S_OK)
delete p;
}
return hRes;
}
};
“创建者”通过提供一个静态函数CreateInstance来创建指定类的实例,并且查询指定的接口。第一个参数在实例化普通对象和class factory对象时会有不同:对于普通对象,通常会传递聚合外部对象的IUnknown指针,如果是非聚合创建,可以传递NULL(详见ATL对COM实体身份的支持四);稍后会介绍在class factory创建时第一个参数的用处。
在ATL中,一个class factory对象只能创建一种类型的COM类实例。在class factory的CreateInstance函数中,它不是硬编码被创建的对象类型,而是通过一个
函数指针成员变量来创建它所管理的对象,而这个函数指针指向的通常就是某个COM类的“创建者”类的CreateInstance静态函数的地址,此地址是在class factory对象被它自身的“创建者”的CreateInstance函数创建时通过第一个参数传进来的,class factory重新定义了SetVoid函数,并且保存这个地址:
class CComClassFactory :
public IClassFactory,
public CComObjectRootEx<CComGlobalsThreadModel>
{
public:
// IClassFactory
STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
{
HRESULT hRes = E_POINTER;
if (ppvObj != NULL)
{
*ppvObj = NULL;
if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
{
hRes = CLASS_E_NOAGGREGATION;
}
else
hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
}
return hRes;
}
STDMETHOD(LockServer)(BOOL fLock)
{
if (fLock)
_pAtlModule->Lock();
else
_pAtlModule->Unlock();
return S_OK;
}
void SetVoid(void* pv)
{
m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
}
_ATL_CREATORFUNC* m_pfnCreateInstance;
};
根据上面的讨论,一个COM类的创建者会像这个样子:
CComCreator< CComObject<CMyClass> >
而一个class factory的创建者会像这个样子:
CComCreator< CComCachedObject<CComClassFactory> >。
ATL在客户请求创建CMyClass对象时执行的伪代码如下:
typedef CComCreator< CComCachedObject<CComClassFactory> > CClassFactoryCreator;
typedef CComCreator< CComObject<CMyClass> > CMyClassCreator;
IClassFactory* pcf=NULL;
CClassFactoryCreator::CreateInstance(&CMyClassCreator::CreateInstance,__uuidof(IClassFactory),&pcf);
pcf->CreateInstance(pOuter,__uuidof(IMyInterface),ppvObj);
posted on 2007-04-10 17:36
michael 阅读(1499)
评论(0) 编辑 收藏 引用 所属分类:
心得