软件组件复习内容Word格式.docx
- 文档编号:17629314
- 上传时间:2022-12-07
- 格式:DOCX
- 页数:25
- 大小:1.10MB
软件组件复习内容Word格式.docx
《软件组件复习内容Word格式.docx》由会员分享,可在线阅读,更多相关《软件组件复习内容Word格式.docx(25页珍藏版)》请在冰豆网上搜索。
Aninstanceofaclass.
类的实例
Theinstanceofacoclass
COM类的实例
Marshaling
Movingdata(parameters)betweenclientandserver.
组件和对象技术对比
多态性:
面向对象支持方法多态和对象多态,可以根据参数类型和次序确定方法,还可以根据具体类型决定调用对象;
面向组件支持组件多态,可以根据需要选择实现接口的组件。
绑定:
面向对象以支持编译时绑定为主,只支持純虚类的动态绑定或运行时绑定;
面向组件则以编译后绑定为主。
封装:
面向对象封装后指定了类中内容的访问权限:
public、protected和private,部分情况下可以直接访问数据;
面向组件只能通过接口中方法访问组件,方法中可见的都类似于public部分。
继承:
面向对象实现类之间的继承,是源代码重用;
面向组件是接口重用,重用的是可执行代码的重用。
基于组件的开发方式
组件的开发是一个利用已有软件开发新软件的过程,相比于已有软件开发,增加了对已有软件的确认和检索,其过程如下:
标识过程:
标识一个可重用的组件
验证过程:
判定可重用组件所声明的功能特性和性能特性
分类过程:
根据已有的组件的功能、使用方法、适用范围、接口等内容给出其描述
检索过程:
利用标准的方法根据指定的属性找到所需的组件
定制过程:
对组件进行修改和配置使其满足客户要求
组合过程:
将组件组装成系统
组件的优缺点:
组件作为接口和实现独立,调用方和被调用方分离的软件,可以实现不同语言之间的协作,具有编程语言和开发环境的独立性;
可以实现不同主机之间组件的调用,具有位置透明性;
提供了套间管理进程,具有部分进程透明性;
方便程序的拆卸,具有可扩充性;
支持通过包容和聚合重用组件,具有可扩展性;
提供了检索、启动组件等强有力的基础设施和系统一级的命名、存储、传输等公共服务。
但是也存在不适合使用组件的情况,组件提高了重用性,不适宜用于不需要重用或不能重用的环境下,如:
组件预期软件不大会发生改变,而且不打算把其子模块共享或软件使用率很低,没有组件客户等情况。
二是组件开发需要一些额外的工作,或者说是人力时间成本,不适宜用于公司资金紧缺或者缺乏组件开发人员或人员能力不足以及时间压力大时。
COM(ComponentObjectModel):
组件对象模型,是建立在二进制层次上的标准,是程序与程序之间的通信的基础;
COM规范与平台无关,定义了大量的标准接口,但COM实现是平台相关的,对Windows平台有依赖。
COM原则
第一条原则:
COMisAboutInterfaces。
不同组件之间的交互都通过接口,COM规范很多是关于接口的,包括支持许多对象操作的接口(如IStream、IDataObject等)、一切组件的基本接口IUnknown,不仅如此,还提供了许多接口的缺省实现。
第二条原则是COMisLanguage-Independent。
COM规范可以支持多种语言编写的组件间的协作。
虽然COM作为一种软件,需要语言来实现,但没有限制COM用户的所用的语言,甚至在同一个应用中,不同组件也可以使用不同语言。
第三条原则是COMisBuiltAroundtheConceptofTransparency。
COM分离了客户程序和组件程序,对客户隐藏了组件的实现信息,实现了组件语言、组件位置、进程以及一些服务的透明性。
第四条原则是InterfacesareContractsBetweentheClientandServer。
接口是客户和服务者间的契约,它可能先于组件对象出现,是组件提供者开发组件和客户使用组件的基础或标准。
第五条原则是SoftwareChanges.InterfacesDon'
tChange。
接口一旦发布就不能改变,而且每个接口是唯一的,只能通过创建新接口来增加或改变。
COM模型
COM简化模型
COM细化模型
从简化模型看,COM在架构上主要是拉大了客户程序和COM组件之间的距离,双方以接口为基础,实现自己的功能并确定协作方式。
从细化模型看,COM模型涉及如下部分:
客户程序:
调用COM组件、使用其功能的程序,其步骤包括初始化COM库、查询COM获取组件的接口、执行组件的方法,释放接口、释放COM库等,示例代码如下:
#include"
..\BeepServer\BeepServer.h"
//GUIDSdefinedintheserver
constIIDIID_IBeepObj={0x89547ECD,0x36F1,0x11D2,{0x85,0xDA,0xD7,0x43,0xB2,0x32,0x69,0x28}};
constCLSIDCLSID_BeepObj={0x89547ECE,0x36F1,0x11D2,{0x85,0xDA,0xD7,0x43,0xB2,0x32,0x69,0x28}};
intmain(intargc,char*argv[])
{
HRESULThr;
//COMerrorcode
IBeepObj*IBeep;
//pointertointerface
hr=CoInitialize(0);
//initializeCOM
if(SUCCEEDED(hr))//macrotocheckforsuccess{
hr=CoCreateInstance(
CLSID_BeepObj,//COMclassid
NULL,//outerunknown
CLSCTX_INPROC_SERVER,//serverINFO
IID_IBeepObj,//interfaceid
(void**)&
IBeep);
if(SUCCEEDED(hr)){
hr=IBeep->
Beep(800);
//callthemethod
Release();
//releaseinterface
}
CoUninitialize();
//closeCOM
return0;
}
组件程序:
定义实现COM接口和类的程序.包括进程内组件,以dll为扩展名的程序和进程外组件以及远程组件,以exe为扩展名的程序。
对于进程内组件,客户和组件在同一个进程内,客户可以直接访问组件。
其它组件需要涉及进程之间的通信,远程组件还要借助RPC等通信的支持。
其简要创建过程包括创建COM对象并命名、在COMserver内实现并注册、定义接口并命名、定义接口中的方法或函数并命名和安装COMserver.
COM库:
是客户程序和组件程序之间的桥梁,提供了COM的实现,支持组件对象的创建、对象管理、内存管理和标准化操作等功能,包括所有“Co”开头的API函数,如CoInitialize().由OLE32.DLL程序实现。
SCM(ServiceControlManager):
查找和启动COM组件,包括从注册表中查找COM组件、调用COM库启动组件,在NT中SCM是RPCSS服务的一部分。
注册表:
提供了COM组件的信息,包括所有COM组件的GUIDs和接口,实现了GUID到具体程序和服务的映射。
当前由系统注册表实现,可以由Regedit打开,用regsvr32.exe注册。
类工厂:
指导如何创建COM对象的对象,在COM服务中,和COM组件对应,通常自动使用,对用户透明。
可以通过CreateInstance()和CoGetClassObject()调用,前者是IClassFactory中的标准方法,创建一个调用方法的标准接口,后者可以从COM服务定位、启动并请求COM类。
VTABLES
VirtualFunctionTables虚拟函数表,存放组件中各个方法的指针。
增加了调用组件的间接性,前三个指针指向IUnknown的三个方法。
接口的原则:
所有接口必须按严格的次序实现QueryInterface(第一个),AddRef(第二个)和Release(第三个);
其它方法从第四个开始;
接口发布后不再改变;
接口是强类型的,参数没有二义性;
接口命名为I*,如ICAT,IPeople等
IUnknown接口:
接口查询:
为了获取COM对象的接口,由IUnknown的Querty实现接口查询。
HRESULTQueryInterface([in]REFIIDiid,[out]void**ppv)
Iid为输入参数,表示128位的接口标识符;
ppv为输出参数,是查询结果,如果没有对象没有实现接口,则为NULL,HRESULT为返回值,为S_OK表示找到了接口,接口指针存入ppv中,为E_NOINTERFACE表示对象不支持所找接口,*ppv为空。
为E_UNEXCEPTED表示发生了意外错误,*ppv为空。
实现原则:
-同一个对象的不同接口指针,Iunknown接口完全相同
-接口自反性:
对一个接口查询自身总是成功,如-p->
QueryInterface(IIDp,…)返回S_OK
-接口对称性:
如果从接口A查询接口B成功,则从接口B查询接口A也成功。
如pA->
QueryInterface(IIDpB,…)返回S_OK<
->
pB->
QueryInterface(IIDpA,…)返回S_OK
-接口传递性:
如果从接口A可查询接口B,从接口B可查询接口C,则从接口C查询接口A成功。
QueryInterface(IIDpB,…)返回S_OK&
&
QueryInterface(IIDpC,…)返回S_OK=>
pC->
QueryInterface(IIDpA,…)返回S_OK
-接口查询时间无关性:
如果某一时刻查询接口A成功,则在任一时刻查询接口A也成功
内存管理:
为了COM对象自己管理生命周期,无法自己删除的问题,用IUnknown接口中的AddRef和Release实现引用计数,使用原则为:
-当一个非空的接口从一个内存位置拷到另一个内存位置,应调AddRef增加计数
-对包含非空接口指针的内容位置,重写前要调用Release,以告知对象引用被销毁
-如果两个或多个内存位置之间的关系需要特殊理解,多余的计数可以优化掉(比如堆栈等)
调用AddRef的情况有:
调用Release的情况有:
接口定义语言IDL
为了不同的用户使用组件,描述多个语言编写的软件,解决一般语言中的语义二义性(如不同语言间或者C语言内)的问题,需要一种专门的接口定义语言。
为此微软公司以OSF的DCERPCIDL为基础而开发了MIDL。
文件以IDL为扩展名,句法与C++相似,不生成目标代码code(youcan‘tlinkit).只生成中间文件。
定义的内容包括:
接口、接口方法、参数、COM类、类型库和数据类型等信息。
其中GUID的定义:
typedefstruct_GUID{
DWORDData1;
WORDData2;
WORDData3;
ByteData4[8];
typedefGUIDIID;
typedefGUIDCLSID;
参数属性In(输入,向组件传递数据)、Out(输出,组件产生的数据)和in,out((输入输出,双向传递的数据)
包容和聚合
为了满足客户的请求,尽可能利用已有组件,实现可执行层面的软件重用,需要一种组件重用方法。
包容和聚合是两种重用组件的方法,实现了一个组件对另一个组件的重用。
包容是在接口级别完成的。
外部组件包含指向内部组件接口的指针,它只是内部组件的一个客户,它将使用内部组件来实现它自己的接口。
外部组件不仅可以将调用直接转发给内部组件的方法,还可以在内部组件代码的前后加一些代码以对接口进行改造
聚合是包容的一个特例。
外部组件直接把内部组件的接口指针返回给客户,无需重新实现并转发接口中的所有函数。
但这时无法对接口中的函数进行任何改造。
相关实现内容如下:
委托IUnknown的实现
ULONGCA:
:
AddRef(){
if(m_Out!
=Null)returnm_Out->
AddRef();
elsereturnNondelgationAddRef();
Release(){
Release();
elsereturnNondelgationRelease();
HRESULTCA:
QueryInterface(constIID&
iid,void**ppi){
QueryInterface(iid,ppi);
elsereturnNondelgationQueryInterface(iid,ppi);
回调函数
为了解决客户和组件间的双向通信问题,第一种方法是在客户端开发回调函数,接收组件的消息。
[
object,
uuid(B426A80D-50EA-11D2-85DA-004095424D9A),
helpstring(“ICallBackInterface”),
]
interfaceICallBack:
Iunknown{
HRESULTAwake(longlVal);
//回调方法
};
客户方
服务方
调用InitInstance():
初始化应用对象。
调用InitCOM():
初始化所有COM对象.CoInitialize用于初始化COM
InitCOM用CComObject:
CreateInstance创建CCallBack对象,它存在于客户程序的生命周期
InitCOM()用CoCreateInstance()初始化服务程序的ISimpleCallback接口
服务方启动,创建CSimpleCallback,一直存在到客户释放
InitCOM()传递指针到CCallBack对象与服务方的Advise()方法
Advise复制ICallBack接口,调用AddRef,创建cookie并返回控制给客户
InitCallback()释放CallBack对象
客户程序调用服务程序Now
调用客户的Awake.使用Advise中接受到的接口
调用Awake
Awake返回,Now结束
用户关闭Main,调用ExitInstance.
ExitInstance传递cookie,调用UnAdvise
释放ICallBack接口并返回
CCallBack引用为0,自动释放CCallBack对象
调用ISimpleCallback接口上的Release
CSimpleCallback引用计数为0,服务方关闭
ExitInstance调用CoUninitialize.客户应用关闭
可连接对象:
可连接对象也是为了解决客户和组件间的双向通信问题,而且可以支持组件和客户程序的多对多关系。
可连接对象又称源对象,需要支持IConnectionPoint接口以创建管理连接,还需要支持IConnectionPointContainer接口以支持多个连接点的管理。
IConnectionPointContainer接口:
管理连接点,查找确定的连接点火枚举
classIConnectionPointContainer:
publicIUnknown{
virtualHRESULTEnumConnectionPoints(IEnumConnectionPoints**)=0;
virtualHRESULTFindConnectionPoint(constIID*,IConnectionPoint**)=0;
IConnectionPoint接口:
管理连接,是一个专门管理连接的对象,实现连接点的判断、创建、取消、访问
classIConnectionPoint:
publicIUnknown{
virtualHRESULTGetConnectionInterface(IID*pIID)=0;
virtualHRESULTGetConnectionPointContainer(IConnectionPointContainer**ppCPC)=0;
virtualHRESULTAdvise(IUnknown*pUnk,DWORD*pdwCookie)=0;
virtualHRESULTUnadvise(DWORDdwCookie)=0;
virtualHRESULTEnumConnections(IEnumConnections**ppEnum)=0;
其中,GetConnectionInterface返回对应出接口的IID,GetConnectionPointContainer返回源对象的此接口指针;
Advise建立接收器和源对象之间的连接;
Unadvise取消连接;
EnumConnections访问建立的连接,返回连接枚举器对象
相关概念包括:
入接口:
客户完成对象的创建和释放
出接口:
对拥有出接口的对象称为可连接对象,也称为源对象这些出接口并不是由对象来实现,而是由客户来实现,客户实现这些接口,并把这些接口指针告诉对象。
以后对象利用这些接口指针与客户进行通信。
接收器:
在客户程序方,实现这些接口的对象被称为接收器(sink),它本身就是一个COM对象,只用来监听并处理组件对象的通知或请求
自动化对象:
为了实现COM的语言无关性,支持VB、Java等不支持指针的语言对组件的调用,提供基于属性和方法的调用方式,而实现的一项技术。
它也受VBA发展的驱动。
属性:
自动化对象的数据特征,是一个值,即可以设置(写),也可以获取(读),不需要参数
方法:
自动化对象提供的功能和服务,可以有零个或多个参数,获取或设置属性,完成某一动作
interfaceIDispatch:
IUnknown{
typedef[unique]IDispatch*LPDISPATCH;
HRESULTGetTypeInfoCount([out]UINT*pctinfo);
确定类型库是否可用,可用返回1,否则返回0
HRESULTGetTypeInfo(//调用者通过该函数取得类型库信息
[in]UINTiTInfo,
[in]LCIDlcid,
[out]ITypeInfo**ppTInfo
);
HRESULTGetIDsOfNames(//根据函数名称取得函数序号
[in]REFIIDriid,//保留参数,为IID_NULL
[in,size_is(cNames)]LPOLESTR*rgszNames,
[in]UINTcNames,
[in]LCIDlcid,//指定本地化标识
[out,size_is(cNames)]DISPID*rgDispId//方法的调用ID
HRESULTInvoke(//调用执行函数
[in]DISPIDdispIdMember,//用来确定所需的方法,由GetIDsOfNames确定
[in]REFIIDriid,//保留参数,为IID_NULL
[in]LCIDlcid,//指定本地化标识
[in]WORDwFlags,//指示调用类型
[in,out]DISPPARAMS*pDispParams,//调用参数
[out]VARIANT*pVarResult,//返回结果
[out]EXCEPINFO*pExcepInfo,//保存异常信息
[out]UINT*puArgErr//错误参数的索引值
typedefstructtagDISPPARAMS{
VARIANTARG*rgvarg;
//参数数组,参数的顺序与客户程序中调用的参数左右顺序相反
DISPID*rgdispidNamedArgs;
//参数的分发ID数组
UINTcArgs;
//数组中参数个数
UINTcNamedArgs;
//命名参数个数
}DISPPARAMS;
参数wFlags指示调用类型,其中DISPATCH_METHOD表示方法调用、DISPATCH_PROPERTYGET表示属性调用。
还要了解tagVARIANT的内容
双接口:
即可以支持指针对接口中方法的直接调用又能支持IDispatch接口中通过Invoke方法的调用,为此称为双接口,虽然也要实现IUnknown接口,但它是必须实现的,为此命名时没考虑他
使用方式
因为
所以
脚本语言使用组件
解释器只认识IDispatch接口
可以调用,但执行效率最低
编译型语言使用组件
它认
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件 组件 复习 内容