CoCreateInstance是创建组件时使用得最多的一种方法,但由于其灵活性不足以满足所有组件的需求,因此引入了类厂。所有的组件都是类厂创建的。CoCreateInstance实际上也是按照一般发方法通过类厂来创建组件的。当客户直接使用类厂时,将能够获得更高的灵活性。
1. CoCreateInstance函数
此函数需要一个CLSID参数来创建相应组件的一个实例,并返回此实例的某个接口。
HRESULT __stdcall CoCreateInstance(
const CLSID clsid,
IUnkown* pIUnkownOuter,//outer component
DWORD dwClsContext, //server context
const IID& iid,
void** ppv
);
这里,函数的第三个参数dwClsContext可以控制所创建的组件是在与客户相同的进程中运行,还是在不同的进程中运行,或者是在另外一台机器上运行。此参数的值可以是如下所列各值的组合。
CLSCTX_INPROC_SERVER 客户希望创建在同一进程中运行的组件。为实现这一点,组件必须是在DLL中实现的。
CLSCTX_INPROC_HANDLER 客户希望创建进程中处理器。进程中处理器实际上是一个只实现了某个组件一部分的进程中组件,该组件的其他部分将由本地或远程服务器上的某个进程外组件实现。
CLSCTX_LOCAL_SERVER 客户希望创建一个在同一机器上的另外一个进程中运行的组件。本地服务器是由exe实现的。
CLSCTX_REMOTE_SERVER 客户希望创建一个在远程机器上运行的组件。此标志需要分布式COM正常工作。
CoCreateInstance的不灵活性在于,它没有给客户提供一种能够控制组件创建过程的方法,当CoCreateInstance完成之后,组件实际上已经建立起来了,之后要想控制将组件装载到内存中何处或检查客户是否有权限来创建该组件基本上已经是不可能的了。在组件创建好之后,可以通过一个接口来初始化它,但在创建之前却无法获得它的接口,也就无法对组件的创建加上条件限制。为解决组件的创建过程的控制问题,引入了另外一个专门用于创建所需组件的组件——类厂。
2. 类厂
创建其他组件是类厂的唯一功能,而且某个特定的类厂将创建只同某个特定的CLSID相应的组件,而客户则可以通过类厂所支持的接口来对类厂创建组件的过程加以控制。创建组件的标准接口是IClassFactory。
CoGetClassObject函数
此函数和CoCreateInstance函数一样,需要一个CLSID作为参数并返回相应类厂中某个接口指针的函数。其声明如下:
HRESULT __stdcall CoGetClassObject(
const CLSID& clsid,
DWORD dwClsContext,
COSERVERINFO* pServerInfo,//reserved for DCOM
const IID& iid,
void** ppv );
CoGetClassObject和CoCreateInstance的最大区别在于前者返回的是指向所需组件的类厂指针,而后者是指向所需组件的指针。客户可以用前者所返回的指针来创建所需的组件,这个指针通常是一个IClassFactory指针。
IClassFactory接口
其声明如下:
interface IClassFactory:IUnknown
{
HRESULT __stdcall CreateInstance(IUnknown* pUnkownOuter,
const IID& iid,
void** ppv);
HRESULT __stdcall LockServer(BOOL bLock);
};
除了IClassFactory之外,Microsoft还定义了另外一个创建接口IClassFactory2。此接口在IClasFactory的基础上增加了许可或权限功能。此时,客户必须给类厂提供正确的关键字或许可以创建所需的组件。
什么时候用CoGetClassObject?
若想用不同于IClassFactory的某个创建接口来创建组件,则必须用CoGetClassObject。因此,如果想用IClassFactory2来创建组件,就应使用CoGetClassObject;若需创建同一组件的多个实例,使用CoGetClassFactory可获得更高的效力。因为这样只要创建相应的类厂一次,而CoCreateInstance需为每一个实例分别创建并释放相应的类厂。另外CoGetClassFactory使客户可对组件的创建过程进行更多的控制。
类厂的两个特性
首先,类厂的一个实例只能创建同某个CLSID相应的组件。体现在CoGetClassObject借接收一个CLSID,而IClassFactory::CreateInstance却不接收此参数。
其次,在大多数情况下,类厂组件与它所创建的组件包含在相同的DLL中。与某个特定CLSID相应的类厂是由实现组件的开发人员实现的。
DllGetClassObject
CoGetClassObject需要DLL中一个名为DllGetClassObject的函数来完成类厂的创建。此函数定义如下:
STDAPI DllGetClassObject(
Const CLSID& clsid,
Const IID& iid,
Void** ppv
);
DllGetClassObject是的我们可以在同一个DLL中实现多个组件。