您现在的位置是: 软件 > 开发者网络 > 技术跟踪 > 技术理论 > 正文


-Win xp中的多种网络
-试验试验试验试验
-用Freehand实现位图矢量化
-网络电话面面观

组件对象模型的规则
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  

【责任编辑:  】
【发表评论】【关闭窗口】
■ 相关内容
 Microsoft数据仓库架构
 MS SQL Sever 7.0 存储引擎
 XML 和 Windows CE 3.0
 Win32设备驱动程序的体系结构
感谢 访问天极网,如果您觉得该文章涉及版权问题,请看这里!