《COM原理及应用》学习笔记之第六章

第六章 可连接对象

1 COM 的高级特性

       COM 规范中有一些高级特性,如可连接对象、永久存储、一致的数据传输等,使 COM 规范具有更强的生命力,它们也是 OLE 的基础,但它们的应用又不仅仅局限于 OLE ,这些高级特性已经广泛应用于 Windows 操作系统上。

 

2 、入接口、出接口与接收器

       入接口( incoming interface )是组件暴露给客户,被动地监听并为客户请求作出反应的接口。而出接口( outgoing interface )是指组件主动与客户进行通信的接口。

       出接口不是由对象实现的,而是由客户程序来实现,客户实现这些接口,并把接口指针告诉对象,以后对象利用此接口指针与客户进行通信。在客户程序方,实现这些接口的对象被称为接收器( sink )。接收器本身也是一个 COM 对象,但它往往比较简单,只用于监听处理组件对象的通知或请求。

       客户与对象之间的关系是相对的,入接口和出接口也是一个相对概念,它们只用于通信的一个方向。

 

3 、可连接对象

       如果一个 COM 对象支持一个或多个出接口,则称这样的对象为可连接对象( connectable object ),或称为源对象( source )。

       可连接对象的出接口也是 COM 接口,它包含一组成员函数,每个成员函数代表了一个事件( event )、一个通知( notification )或者一个请求( request )。

 

4 、事件、通知与请求

       事件和通知在概念上是完全一致的,只是用在不同的场合,例如在 COM 对象中当某个属性被改变时,它可以给客户发送一个通知;而当特定事情发生时,比如定时消息或用户鼠标操作发生时,对象产生一个事件,客户程序可以处理这些事件。然而,请求的概念则稍有不同,对象给客户发出请求,它希望客户能提供某些信息,期望客户能有应答。

       COM 规范的意义上来讲,不管是事件、通知还是请求,它们都通过出接口的成员函数来实现。

 

5 、客户与可连接对象的关系

       虽然接收器也是一个 COM ,但它有特殊性,它位于客户程序内部,并不需要通过 COM 库来创建,所以接收器并不需要 CLSID 来标识,也不需要类厂,接收器的标识和创建过程完全是客户程序内部的事情。对于客户程序外部而言,接收器也是一个单独的 COM 对象,它有自己的引用计数,有自己的接口查询方法,即 QueryInterface 成员函数。 COM 只要求接收器是一个独立的 COM 对象, COM 规范对接收器的实现没有任何限制。

       一般可连接对象不应该向接收器对象请求其他的接口,即不应该调用接收器的 QueryInterface 成员函数。接收器通常专用于某个出接口指针,接收器对象只实现该出接口,当然出接口是基接口(比如 IUnknown )除外。

       可连接对象和接收器可以形成一对多或者多对一的关系,也即客户与可连接对象之间可以是一对多或者多对一的关系。

 

6 、可连接对象的基本结构

       可连接对象可以支持一个或多个出接口,它通过接口 IConnectionPointContainer 管理所有的出接口。对应于每个出接口,可连接对象又管理了一个称为连接点( connection point )的对象,每一个连接点对象实现了 IConnectionPoint 接口,客户通过连接点对象建立接收器与可连接对象的连接。连接点即可以访问可连接对象的内部信息,也可以访问客户方的接收器,而其它可以直接使用可连接对象的引用计数器。

 

7 、枚举器

       COM 规范中,枚举器( Enumerator )只是一个概念,没有确定的接口用于规定枚举器的各项操作,这是因为枚举器所枚举的数据单元的类型不确定,所以也无法给出确切的定义。客户程序利用枚举器对 COM 对象中的数据单元进行枚举操作,枚举器把客户对数据单元的操作进行了标准化,因此, COM 对象可以按照标准的方法把数据提供给客户,而不必建立二者之间新的协议。

       因为枚举器对象是一个内部对象,它只需暴露枚举接口,不需要 CLSID 和类厂,所以枚举器对象的实现比较简单,只需实现枚举操作并控制好引用计数即可。

客 户的接收器与源对象的连接点建立连接时,源对象使用连接点枚举器管理连接点对象,连接点对象又用连接枚举器管理连接,通过两层结构建立对象与接收器之间的 连接。把源对象与连接点对象分开实现,可以使它们各自保持一定的独立性。源对象与接收器之间的连接具有很好的扩展性,而且连接点对象的独立性也使得 COM 可连接对象机制更具灵活性和广泛性。

 

8 、接收器的实现

       C++ 语言中,用一般的类从接口类派生,然后分别实现接口成员函数即可。客户程序在建立连接之前,要先创建接收器对象,因为接收器是客户程序的内部对象,所以在 C++ 语言中可以用 new 操作符创建接收器对象,然后用此连接器对象建立它与源对象之间的连接。

 

9 、事件的激发和处理

       实现事件和请求是可连接对象机制的主要目标。事件即可由源对象的入接口成员函数激发,也可以由用户的某些操作引起,还可以由其它对象或客户调用而引起。总之,在源对象执行过程中,根据需要都可以激发事件或者向客户发出请求,事件和请求在程序逻辑上完全一致。

       由于事件或请求是在每个连接上进行的,只有建立了连接的接收器对象才会收到事件或请求。

       连 接点对象和接收器对象肯能位于不同的进程中,甚至在不同的机器环境中。因此,事件从激发到处理不一定是直接的函数调用,这是可连接对象机制与一般回调函数 机制的重要不同。只有在单线程模型下,连接点对象才直接调用接收器对象的事件控制函数。从连接点对象到接收器对象之间的通信过程与以前讨论的客户和对象之 间的通信过程一样,也符合 COM 线程模型规范,必要时侯也需要进行列集处理。

 

10 、出接口通信连接的建立

       首先客户方通过源对象的 IConnectionPointContainer 接口得到源对象的出接口 IID ,并进一步向源对象请求 IProvideClassInfo 接口,调用 IProvideClassInfo::GetClassInfo 成员函数得到 ITypeInfo 结构,再进一步得到出接口的 ITypeInfo 结构而获取接口的所有类型信息,包括成员函数、函数参数的个数和参数类型等。类型信息是客户和源对象双方的通信协议标准。

       根据出接口的类型信息在程序运行过程中实现动态接收器对象很不容易。虽然可连接对象提供了完善的双向通信机制,但客户要在运行过程中根据源对象的类型信息响应事件或请求并不容易。为此, OLE 发展了 COM 的可连接对象的机制,它使用 IDispatch 接口作为出接口,利用 IDispatch 接口中方法( method )的分发功能实现事件控制函数。 IDispatch 接口的主要特点是,它可在运行时刻而不是在编译时刻把成员函数与特定的分发 ID 进行绑定操作,这种特性称为迟绑定( late binging )。 IDispatch 接口是 Microsoft 实现自动化技术的基础,现在已经得到了广泛的应用。

 

11 、用 IDispatch 接口作为出接口

       IDispatch 接口是自动化对象的基本接口,在高级语言或者脚本语言中,可以直接用符号化的名字即字符串访问自动化对象的属性( property )和方法( method )。使用 IDispatch 接口有三方面的显著有点:第一,用名字访问属性和方法非常简单易用;第二,自动化对象的 IDispatch 接口的 vtable 是固定的,在有些高级语言或脚本语言中没有指针数据类型,所以在这些语言中描述自定义接口比较困难;第三, IDispatch 接口支持迟绑定特性,可以在运行过程中根据名字访问属性或方法。

       COM 已经提供了 IDispatch 接口的代理对象( proxy )和存根对象( stub ),所以,使用 IDispatch 接口作为出接口可直接用于进程外源对象的出接口。

       IDispatch 接口把所有的调用都通过其成员函数 Invoke 来实现,并且它提供了管理属性和方法的分发 ID 机制,以及一套描述参数和返回值的方法,所以使得运行时刻动态绑定属性和方法并进行参数类型检查成为可能。可以说 Invoke 函数是自动化对象的命令翻译器。

       根据不同的开发环境和运行环境,实现 Invoke 函数可以采用不同的方法。如果在编译时刻可以决定客户应该响应那些事件或请求,则可以在程序中建立一张表,把每个事件或请求的分发 ID 和对应的控制函数作为表项放到表中,把这张表称为事件映射表。 MFC COleControl 类使用这种方法处理 ActiveX 控制的事件和请求。

       利用 IDispatch 接口作为出接口可以很好地解决接收器的动态创建过程。利用 IDispatch 接口作为源对象的出接口,由源对象提供出接口的类型信息,即事件控制函数的所有信息,客户程序根据这些类型信息,在 Invoke 函数中调用相应的事件控制函数。

 

12 MFC 对连接和事件的支持

       1 MFC 实现了连接点类 CConnectionPoint CConnectionPoint 实现了 IConnectionPoint 接口,它用一个数组枚举器管理连接;

       2 CCmdTarget 也提供了一组宏支持连接点对象;

       3 CCmdTarget 类有一个内嵌的结构成员 m_xConnPtContainer 专门用于存放接口 IConnectionPointContainer vtable 和偏移量;

       4 )连接点是可连接对象的核心,但连接点的主要目的是激发事件或发送请求,因此,我们应该对每个事件或请求编写一个激发函数。

       MFC 提供了类 COleDispatchDriver ,他主要用于 IDispatch 接口的客户方调用操作,利用 COleDispatchDriver 的成员函数,客户可以创建自动化对象,也可以把 COleDispatchDriver 对象与某个自动化对象联系起来,更有意义的是, COleDispatchDriver 使得 IDispatch::Invoke 调用的参数处理更为简单。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我是C知道,很高兴回答您关于mxGraph学习的问题。mxGraph是一款基于JavaScript的开源图形库,可用于在Web应用程序中创建交互式图表和图形。以下是一些学习mxGraph的笔记: 1. 官方文档:您可以从mxGraph的官方网站获取最新的文档和示例。官方文档提供了详细的API参考,示例代码和教程,可以帮助您快速入门和理解mxGraph的各种功能和用法。 2. 基本概念:了解mxGraph的基本概念是学习的第一步。这包括了解图形模型、元素、连接、样式、布局和事件处理等。 3. 示例代码:通过查看和运行示例代码,您可以学习如何使用mxGraph创建各种类型的图表和图形。官方文档中提供了丰富的示例代码,您可以直接使用或修改它们来满足自己的需求。 4. 自定义样式:mxGraph允许您通过自定义样式来美化图表和图形。您可以使用CSS样式表或直接在代码中设置样式属性来实现。掌握如何使用样式可以使您的图表更加美观和可定制。 5. 交互和事件处理:mxGraph提供了丰富的交互和事件处理功能,如拖放、缩放、选中和编辑等。学习如何处理这些事件可以增强用户体验并实现更复杂的交互操作。 6. 布局算法:mxGraph提供了多种布局算法,可帮助您自动排列图表中的元素。了解这些布局算法的原理和使用方法可以提高图表的自动化程度。 7. 扩展和定制:mxGraph是一个开源库,您可以通过扩展和定制来满足特定的需求。了解如何编写自定义的图形元素、连接线和布局算法可以使您的应用程序更加个性化。 这些只是mxGraph学习的一些基本笔记,希望对您有所帮助。如果您有任何具体的问题,欢迎继续提问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值