随笔-6  评论-0  文章-16  trackbacks-0
         在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 阅读(1527) 评论(0)  编辑 收藏 引用 所属分类: 心得

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理