| | | 组件对象模型的规则 | | 2001-12-21·
·Charlie Kindel··microsoft
| 上一页 1 2 3 服务器规则
进程内服务器必须输出DllGetClassObject and DllCanUnloadNow。
进程内服务器必须支持COM自注册。
进程内和局部服务器应该在它们的文件版本信息中提供OLESelfReg字符串。
进程内服务器必须输出DllRegisterServer and DllUnRegisterServer。
局部服务器应支持/RegServer and /UnRegServer命令行开关。
生成集合对象
生成可合计的对象是可选的,且操作简单,有诸多益处。以下规则使用于创建可合计的对象(通常称为内部对象)。
由QueryInterface, AddRef, 和 Release对IUnknown接口的内部对象执行单独控制内部接口的引用计数,且不能授权给外部未知指针。这种IUnknown执行称为隐式IUnknown。
内部对象执行接口的QueryInterface, AddRef, 和 Release成员的实行,除了IUnknown自己,都必须授权给外部未知指针。这些实施不能直接影响内部对象的参考计数。
隐式Iunknown只对内部对象实施QueryInterface操作。
集合对象在占用外部未知指针参考时,不能调用AddRef。
如果当对象创建时,需要除Iunknown外的任一接口,创建失败同E_UBKNOWN一起。
以下的代码段阐明了使用嵌套类来实现集合对象接口的范例:
// CSomeObject is an aggregatable object that implements // IUnknown and ISomeInterface class CSomeObject : public IUnknown { private: DWORD m_cRef;// Object reference count IUnknown* m_pUnkOuter; //Outer unknown, no AddRef // Nested class to implement the ISomeInterface interface class CImpSomeInterface: public ISomeInterface { friend class CSomeObject ; private: private:DWORD m_cRef; //Interface ref-count, for debugging private:IUnknown*m_pUnkOuter; // Outerunknown, for delegation private:public: private:CImpSomeInterface() { m_cRef = 0; }; private:~ CImpSomeInterface(void) {}; private:// IUnknown members delegate to the outer unknown private:// IUnknown members do not control lifetime of object private:STDMETHODIMP QueryInterface(REFIID riid, void** ppv) private:{ return m_pUnkOuter->QueryInterface(riid,ppv);}; private:STDMETHODIMP_(DWORD) AddRef(void) private:{ return m_pUnkOuter->AddRef(); }; private:STDMETHODIMP_(DWORD) Release(void) private:{ return m_pUnkOuter->Release();}; private:// ISomeInterface members private:STDMETHODIMP SomeMethod(void) private:{ return S_OK; }; private:} ; private:CImpSomeInterface m_ImpSomeInterface ; private:public: private:CSomeObject(IUnknown * pUnkOuter) { m_cRef=0; // No AddRef necessary if non-NULL as we're aggregated. m_pUnkOuter=pUnkOuter; m_ImpSomeInterface.m_pUnkOuter=pUnkOuter; } ; // Static member function for creating new instances (don't use // new directly).Protects against outer objects asking for interfaces // other than IUnknown static HRESULT Create(IUnknown* pUnkOuter, REFIID riid, void **ppv) { CSomeObject* pObj; if (pUnkOuter != NULL && riid != IID_IUnknown) return CLASS_E_NOAGGREGATION; pObj = new CSomeObject(pUnkOuter); if (pObj == NULL) return E_OUTOFMEMORY; // Set up the right unknown for delegation (the non-aggregation case) if (pUnkOuter == NULL) pObj->m_pUnkOuter = (IUnknown*)pObj ; HRESULT hr; if (FAILED(hr = pObj->QueryInterface(riid, (void**)ppv))) delete pObj ; return hr; } // Implicit IUnknown members, non-delegating // Implicit QueryInterface only controls inner object STDMETHODIMP QueryInterface(REFIID riid, void** ppv) { *ppv=NULL; if (riid == IID_IUnknown) *ppv=this; if (riid == IID_ISomeInterface) *ppv=&m_ImpSomeInterface; if (NULL==*ppv) return ResultFromScode(E_NOINTERFACE); ((IUnknown*)*ppv)->AddRef(); return NOERROR; } ; STDMETHODIMP_(DWORD)AddRef(void) { return++m_cRef; }; STDMETHODIMP_(DWORD)Release(void) { if (--m_cRef != 0) return m_cRef; delete this; return 0; }; }; | 集合对象
当在一个对象上产生另一个集合对象时,必须遵循以下规则:
当创建一个内部对象时,外部对象必须明确的向Iunknown请求。
外部对象必须保护重入时对破坏代码的人工引用的Release实施。
如果外部对象查询任一内部对象接口,它必须调用自己的未知Release。释放此指针时,外部对象紧随内部对象指针调用自己的外部未知AddRef。
// Obtaining inner object interface pointer pUnkInner->QueryInterface(IID_IFoo,&pIFoo); pUnkOuter->Release(); // Releasing inner object interface pointer pUnkOuter->AddRef(); pIFoo->Release(); | 外部对象不能盲目地对内部对象的未被识别接口进行查询,除非操作是为外部对象特定目的。
房间线程化模型
房间模型线程化的细节实际上非常简单,但是必须小心地遵循以下规则:
每个对象存在于单线程中(在单独的房间中)。
所有对一对象的调用必须基于自己的线程(在自己的房间中)。直接从别的线程中调用对象是禁止的。试图用空线程方式使用对象的申请,将在操作系统的未来版本中遇上不能正确运行的问题。这条规则的含义就是在房间之间,必须安排对象的所有指针。
为了处理从不同进程或同一进程的不同房间中的调用,在对象中的每一房间/线程必须有一个消息队列。这就意味着线程的工作函数必须有一个GetMessage/DispatchMessage循环。假如在线程之间有别的同步原语用来通信,那么Microsoft Win32的sgWaitForMultipleObjects将被用来等待消息和线程同步事件。
基于DLL或进程内的对象必须在注册表中标记为"房间识别",通过给注册数据库的InprocServer32关键字增添名为"ThreadingModel=Apartment"的变量实现。
房间识别对象应仔细填写DLL表项。对房间识别对象调用CoCreateInstance的每一个房间将从它的线程调用DllGetClassObject。故DllGetClassObject应能多级类对象或单线程安全对象。从任一线程调用CoFreeUnusedLibraries,都通过主房间线程来调用DllCanUnloadNow.。
上一页 1 2 3 | | | 感谢
访问天极网,如果您觉得该文章涉及版权问题,请看这里!
|
|