com技术内幕--读书笔记(7)

第7章 类厂

相信有了前六章的知识积累,学些以后的章节将会很顺利。本章实现了一个真正的COM组件,并通过client客户端来使用这个组件。学完这章,对COM组件的最基本的东西就已经学完了,可以实现一个真正意义上的组件,后续几章就是在此基础上进行的升华,例如组件的复用,EXE中的组件,多线程等等,也同样重要。


本章将介绍类厂,类厂是能够创建其他组件的组件,并且可以使用同一个类厂来创建不同的CLSID所对应的组件,也就是说,在同一个DLL中,可以包含多个组件(组件是用C++类来实现的),并可以使用同一个类厂来创建它们,我想这就是类厂名字的由来。


CoCreateInstance函数是创建组件并获得IUnknown接口,虽然在使用过程中并没有使用类厂,但是它也是按照一定方法通过类厂来创建组件的。

CoCreateInstance

CoCreateInstance函数是COM库的函数,函数原型如下

HRESULT __stdcall CoCreateInstance(const CLSID &clsid, 
		                   IUnknown *pIUnkownOuter, //Outer Component
	                           DWORD dwClsContext,      //Server Context
                                   const IID &iid,
		                   void **ppv);

其中前四个是输入参数,最后一个是输出参数。第一个参数clsid是所创建组件的CLSID,第二个参数pIUnkownOuter是聚合组件需要用的,将在第8章介绍,第三个参数dwClsContext是限定所创建组件的执行上下文,第四个参数iid是所创建组件的接口的IID,第五个参数ppv将返回该接口的指针。

dwClsContext

dwClsContext可以控制所创建是与客户在相同的进程中运行,还是在不同的进程中运行,或者是在另外一台机器上运行。此参数可以是如下值的组合

CLSCTX_INPROC_SERVER         客户希望创建在同一进程中运行的组件,因此组件必须是在DLL中实现。

CLSCTX_INPROC_HANDLER      客户希望创建进程中处理器。

CLSCTX_LOCAL_SERVER           客户希望创建一个在同一机器上的另外一个进程中运行的组件。组件是由EXE实现的。

CLSCTX_REMOTE_SERVER       客户希望创建一个在远程机器上运行的组件。分布式COM组件。

在OBJBASE.H中定义了一些上述值的组合。


CoCreateInstance的具有一定的不灵活性,解决问题的办法是使用专门用于创建所需组件的组件,这个组件就是类厂。


类厂

某个特定的类厂可以创建某个特定CLSID相对应的组件,客户可以通过类厂提供的接口来对组件的创建过程进行控制。客户使用CoCreateInstance所创建的组件实际上是通过类厂的IClassFactory创建的,使用类厂创建组件的步骤是首先创建类厂,然后使用IClassFactory创建所需的组件。

1.创建类厂

COM库函数CoGetClassObject创建同某个CLSID相应的类厂。函数原型如下

HRESULT __stdcall CoGetClassObject(const CLSID &clsid,
		                   DWORD dwClsContext,
                                   COSERVERINFO *pServerInfo,
                                   const IID &iid,
                                   void **ppv);

同CoCreateInstance非常相似。第一个参数const CLSID&待创建组件的CLSID,第二个参数DWORD dwClsContext是待创建组件的执行上下文,第三个参数COSERVERINFO*用于远程组件的访问,将在第10章讨论,第四个参数const IID&是IClassFactory接口的IID,第五个参数返回IClassFactory接口的指针。

2.类厂组件

IClassFactory

大多数组件是使用IClassFactory来创建的,原型如下

interface IClassFactory:IUnknown
{
	HRESULT __stdcall CreateInstance(IUnkown *pUnknownOuter, const IID &id, void **ppv);
	HRESULT __stdcall LockServer(BOOL bLock);
};

IClassFactory::CreateInstance函数的第一个参数IUnknown*是组件聚合使用的,将在第8章介绍,后两个参数跟CoCreateInstance后两个参数作用相同,将在创建组件的

同时返回此组件的某个接口指针。可以看到IClassFactory::CreateInstance并没有接收一个CLSID参数,这意味着此函数将只能创建同某个CLSID——即传给CoGetClassObject的参数CLSID相应的组件。


IClassFactory::CreateInstance和DllGetClassObject的实现是相同的,这两个函数都将创建一个组件然后向它查询某个接口。


在两种情况下使用创建类厂再创建组件的方法,而不是直接使用CoCreateInstance的方法直接创建组件

(1)想使用IClassFactory2来创建组件。IClassFactory2是Microsoft定义的另外一个接口,此接口在IClassFactory的基础上增加了获取组件接口的许可权限功能。

(2)需要创建一个组件的多个实例。这样只需创建相应的类厂一次,而CoCreateInstance需要为每一个组件实例分别创建并释放相应的类厂。

类厂的特性

(1)类厂将只能给你创建同某个CLSID相应的组件。

(2)与某个特定CLSID相应的类厂是由组件开发人员来实现的。大多数情况下,类厂组件包含在它所创建的组件的同一个的DLL中。

类厂的创建

客户通过CoGetClassObject来创建类厂,这就需要在组件的DLL中实现一个特定的函数,此函数名为DllGetClassObject,由COM库函数CoGetClassObject调用,函数原型如下

STDAPI DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv);
函数的三个参数同CoGetClassObject中传入的参数的意义相同。

通过类厂来创建组件的示意图如下,COM库函数CoGetClassObject将根据传入参数CLSID查询注册表,装载组件所在的DLL库。

首先客户调用CoGetClassObject,COM库实现CoGetClassObject函数,组件所在的DLL输出DllGetClassObject函数由CoGetClassObject函数调用,它返回IClassFactory指针,客户调用IClassFactory来创建相应

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值