COM第三部分(类厂、对象的创建、组件程序装载卸载以及生存期、COM组件与客户程序交互过程的描述)

一、类厂:
作用:

COM库通过类厂来创建对象,每个COM类对应着有一个COM类厂来创建此COM类的对象。
并不是用户直接通过c++的new来实例化
优点:
使用类厂来创建对象,可以将所有客户创建的对象的接口统一(统一的方法创建不同类型的COM对象),实现位置透明
说明:
类厂本身也是一个COM对象,当然,类厂不需要其他的类厂创建了;
类厂有一个特殊的接口IClassFactory,该接口派生自IUnknown接口。

二、数学组件的类厂实现:

//IClassFactory接口必须继承自IUnknown接口
class IClassFactory: public IUnknown
{
public:
	virtual HRESULT _stdcall CreateInstance(IUnknown *pUnkouter,REFIID riid,void **ppv) = 0;
	//pUnkouter用于对象被聚合的情形,一般设置为NULL
	//riid 指的COM创建完成后,客户应该得到的初始接口IID,IID_ISimpleMath等
	//ppv来保存接口的指针
	vitual HRESULT _stdcall LockServer(BOOL fLock)  = 0;
	//用来控制DLL组件的卸载
};


//IClassFactory属于抽象类,要实现什么类型的对象就需要派生什么类型的工厂类
//这里具体实现一个用来生成CMath类型对象的工厂
class CMathFactory:public IClassFactory       //具体类继承自抽象类,多态性
{
public:
	CMathFactory();  ~CMathFactory();  //构造和析构函数
	//IUnknown接口成员函数    查询接口,他对IClassFactory 和IUnknown接口提供支持并返回接口指针
	HRESULT _stdcall QueryInterface(const IID&iid , void **ppv);
	//用来管理创建出对象的引用计数
	ULONG _stdcall AddRef();     ULONG _stdcall Release(); 

	HRESULT _stdcall CreateInstance(IUnknown *,const IID&iid,void **ppv);
	//该函数是这里的重点,
	HRESULT _stdcall LockServer(BOOL fLock);
	//组件生存周期的控制
private:
	ULONG m_Ref;
};
HRESULT CMathFactory::CreateInstance(IUnknown *pUnkouter,const IID&iid,void **ppv)
{
	CMath *obj;    //定义对象类的指针
	HRESULT hr;
	*ppv = NULL;   
	if(pUnkouter != NULL)  return CLASS_E_NOAGGREGATION;

	obj = new CMath();  //创建CMath类型对象
	if(obj == NULL ) return hr;

	hr = obj ->QueryInterface(iid,ppv); //得到COM对象的初始接口
	if(hr != S_OK) delete obj;
	return hr;
}

1.我们客户如何去获取一个工厂类对象呢?
一般普通的COM对象我们可以这样获取:
1.调用CoCreateInstance() 2.或者调用IClassFactory::CreateInstance()
COM规范规定对于工厂对象的总是调用CoGetClassObject创建
优点:
客户代码不需要关系它要创建的是哪种对象,进程内、外的差别由类对象管理
2.CoGetClassObject的工作流程:

1.客户调用CoGetClassObject函数
2.CoGetClassObject从系统的注册表中找到目标组件的路径和名称,然后把组件加载到内存
3.再调用组件程序的引出函数DllGetClassObject,该函数创建类厂接口对象并返回指针

3.通过类厂创建对象:

1.客户通过调用CoGetClassObject获得类厂对象的接口指针
2.用该指针调用类厂中的CreateInstance,创建COM对象并返回对象的接口指针。

三、客户通过COM库与组件程序的交互过程:

1.客户调用CoCreateInstance创建对象;
2.CoCreateInstance调用CoGetClassObject函数,
  该函数通过注册表找到目标组件的路径和名称,加载到内存;
3.CoGetClassObject去调用DllGetClassObject函数创建类厂,并把类厂接口指针返回给CoGetClassObject
4.CoGetClassObject又将接口指针返回给CoCreateInstance
5.CoCreateInstance拿到接口指针去调用类厂的CreateInStance方法,创建COM对象
6.然后类厂将对象的接口指针返回给CoCreateInstance,CoCreateInstance最终将接口指针交付给客户
7.客户最终拿着接口指针来使用操作COM对象。

在这里插入图片描述
四、组件程序的装载和卸载:

前面说过,由于同一个对象可能被多次引用,为了保证对象能被使用后正确的释放,给每个对象加上引用计数的属性,保证对象的正确的声明周期。

那么组件程序的在内存中的生命周期是什么样的呢?
为什么要说这个问题,因为组件程序我们使用前是要将其加载到内存,使用完成后卸载出内存。

为了管理组件程序的生命周期:引入两个计数器
1.锁计数器
2.组件对象个数计数器
当以上两个计数器都 == 0时,组件将被卸载出内存。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值