COM对象的创建方式疑问

ftkghost 2006-06-08 10:22:28
为什么COM中实体类需要由类厂来创建而不是直接在DLLGetClassObject中创建?后者更简洁直观阿。

望各位高手给点心得和看法,谢谢
...全文
409 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
lxpws 2006-06-14
  • 打赏
  • 举报
回复
CoGetClassObject中指定的iid是申请的COM类的接口而不是类厂的接口。
------------------------------------
我想LZ可能把一个概念理解错了,此处的Class Object,就是通常所说的Class Factory,两者指的都是可以创建其它COM object的某个特殊的COM object,只是翻译方式不同。

这是MSDN2003里关于CoGetClassObject的riid参数的描述,DllGetClassObject的riid也有类似的描述,原因如你所说,是CoGetClassObject调用了DllGetClassObject,并传递了riid:
Reference to the identifier of the interface, which will be supplied in ppv on successful return. This interface will be used to communicate with the class object(这个接口是跟类对象即类厂通信的,而不是欲创建的com对象). Typically this value is IID_IClassFactory, although other values – such as IID_IClassFactory2 which supports a form of licensing – are allowed(通常它是IID_IClassFactory,但其它的值也是接受的,譬如IID_IClassFactory2).

我想这个时候通过IClassFactory2来解释一下为什么要通过类厂而不是直接调用某个导出函数来创建com object应该是比较合适的了。IClassFactory2的功能是可以为com object的创建提供授权机制,也就是说可以通过检查客户提供的授权码是否正确来决定是否创建com object。

因为IClassFactory2不是我们通常使用的IClassFactory,我们暂时把它叫做自定义类厂(虽然它也是COM标准的一部分)。此处我所说的“可以更好的控制COM object的创建过程”的意义就是,我可以通过授权机制来控制对象的创建,而不是不分情况,只要有请求就给创建。
这就需要客户在创建时提供一个license key,这时就不能通过CoCreateInstance来创建对象了,因为它没有提供任何关于license key的参数,这就是我所说的“如果使用了自定义的类厂,就不能通过CoCreateInstance来创建对象了”的一种情况。

正如用户今天提出要通过授权来创建对象一样,明天可能又提出了另一种创建方式,而COM标准是不可能预测到所有的情况的,因此通过一个固定格式的导出函数来完成所有不能被预料的创建方式是不可能的,而通过提供不同的类厂来提供不同的创建方式则可以对未来所有的变化提供扩展性。现在,你的COM服务器只需要导出DllGetClassObject这个固定的函数,其他的事情,就交给相应的类厂去做吧。
ftkghost 2006-06-14
  • 打赏
  • 举报
回复
to lxpws(老烦):
先谢谢你那么热心给我解答~:)
--------------------------------
LZ仔细看一下我那段话,所谓自定义的类厂接口,就是不同于IID_IClassFactory的接口,而CoCreateInstance调用CoGetClassObject创建类厂时查询的则是标准的IID_IClassFactory接口,因此查询将会失败,对象也就创建不了了,此时客户只能自己通过CoGetClassObject指定自定义类厂的IID(如IID_IMyClassFactory)来查询出类厂的接口,而不能通过CoCreateInstance。
--------------------------------
首先,创建类厂是在DllGetClassObject中创建的,而不是在CoGetClassObject中创建,因此作为组件编写者不存在你说的那种问题,而且CoGetClassObject中指定的iid是申请的COM类的接口而不是类厂的接口。
再,你的讨论似乎有点偏题了,我的问题是“为什么COM中实体类需要由类厂来创建而不是直接在DLLGetClassObject中创建?”,和自定义类厂似乎没有太大关系吧~:)
lxpws 2006-06-11
  • 打赏
  • 举报
回复
我只是不知道通过类厂来创建会有什么优势,管理更方便?也不见得吧。
---------------------------------
呵呵,我只是说“可以更好的控制COM object的创建过程”,至于这个“更好”是什么效果,则要看具体的情况了。譬如说可以一次创建多个对象,节省开销,就是一个“更好的效果”。我所举的那个builder模式的例子,也是一种情况。如果LZ对设计模式不熟悉的话,可以参考一下相关的书籍。
总之不管是什么技术,某些实现上的灵感可能来自于发明者或者业界以前遇到的某些问题,如果我们还没有遇到过,自然不好体会。这也没关系,先有这么个印象,以后说不定什么时候就会恍然大悟的:)
lxpws 2006-06-11
  • 打赏
  • 举报
回复
为什么不能?
CoCreateInstance调用CoGetClassObject函数,而CoGetClassObject函数调用导出函数DllGetClassObject,DllGetClassObject是自己做COM时需要实现的,自定义的类厂同样可以用来创建对象。
---------------------------------------
LZ仔细看一下我那段话,所谓自定义的类厂接口,就是不同于IID_IClassFactory的接口,而CoCreateInstance调用CoGetClassObject创建类厂时查询的则是标准的IID_IClassFactory接口,因此查询将会失败,对象也就创建不了了,此时客户只能自己通过CoGetClassObject指定自定义类厂的IID(如IID_IMyClassFactory)来查询出类厂的接口,而不能通过CoCreateInstance。

lxpws 2006-06-10
  • 打赏
  • 举报
回复
当然如果使用了自定义的类厂,就不能通过CoCreateInstance来创建对象了。
lxpws 2006-06-10
  • 打赏
  • 举报
回复
据我理解,类厂存在的理由是:可以更好的控制COM object的创建过程。
也就是说COM本身并不规定COM object创建的方式,它通过允许你得到类厂对象来自己控制COM object的产生过程。
看一下CoGetClassObject的声明:
STDAPI CoGetClassObject(
REFCLSID rclsid,
DWORD dwClsContext,
COSERVERINFO * pServerInfo,
REFIID riid,
LPVOID * ppv
);

它的功能只是根据客户要创建的COM object的CLSID来获得一个类厂的指针,注意你可以通过指定riid来指定类厂的接口类型(虽然通常是IID_IClassFactory),然后通过ppv来返回,而ppv也没有被强制为IClassFactory**类型。这一切都说明组件的实现者可以通过提供一个完全不同于IClassFactory的接口来控制COM object的产生过程,比如可以一步步的装配对象,然后再将装配好的对象返回,就像builder模式那样。也就是说,在此处,COM类厂就是创建型模式的一个典型应用。
ftkghost 2006-06-10
  • 打赏
  • 举报
回复
to lxpws(老烦)L
当然如果使用了自定义的类厂,就不能通过CoCreateInstance来创建对象了。

为什么不能?
CoCreateInstance调用CoGetClassObject函数,而CoGetClassObject函数调用导出函数DllGetClassObject,DllGetClassObject是自己做COM时需要实现的,自定义的类厂同样可以用来创建对象。


我的疑问flyleaf0206(寒秋) 解答了一部分,我只是不知道通过类厂来创建会有什么优势,管理更方便?也不见得吧。
seasol 2006-06-09
  • 打赏
  • 举报
回复
用组件类型字符串建立类厂时,需要查找注册表;通过类厂再创建对象,则不再需要查注册表了。显示,如果直接创建对象,则每次都要查找注册表。
ftkghost 2006-06-09
  • 打赏
  • 举报
回复
谢谢
flyleaf0206 2006-06-09
  • 打赏
  • 举报
回复
直接通过CoCreateInstance函数创建类对象,在内部也是通过先创建类厂,然后通过类厂创建类对象。这种方式一次只能创建一个类对象;
通过CoGetClassObject函数先创建类厂,然后通过类厂对象的接口CreateInstance可以多次使用,创建需要的类对象。这样可以别面每次定位COM服务器的查找开销。
COM类对象也不是必须通过类厂才能创建,视需要决定,也可能直接通过newCOM类对象的实例,通过类型转换到类对象接口指针。
handsomerun 2006-06-09
  • 打赏
  • 举报
回复
对,类厂不是必须的
好久不做vc了,com的有些东西都忘记了,nnd

至于为什么好多地方用类厂,哎呀,忘记了

查了一下vckbase上的文章、

类厂 - 创建组件对象的对象。COM为通用化以及在管理上统一和方便,COM规范要求所有标准COM组件都应实现IClassFactory接口(有关IClassFactory的功能各个方法的作用请参阅MSND/Welcome to the msnd library/msnd resource/selected online columns/Dr.GUI online/Dr. GUI on Components, COM, and ATL/part 5)
aspnetwuxueyou 2006-06-09
  • 打赏
  • 举报
回复
可以直接创建对象,没有规定说一定要创建工厂
ftkghost 2006-06-08
  • 打赏
  • 举报
回复
我还有两个贴,希望高手能解答,谢谢
http://community.csdn.net/Expert/topic/4810/4810348.xml?temp=.4504206
http://community.csdn.net/Expert/topic/4810/4810388.xml?temp=.7020685

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧