下载 第18章对C++组件的进一步讨论 在前一章中,我们学习了用C++创建COM组件的基本方法,用这些概念创建的组件对于 在内存中处理数据是非常有用的。但是,要制作一个功能强大的服务器组件,需要使用微软 平台提供的其他服务。特别是,创建的组件应能提供对数据的访问、与COM+进行接口以及 与ASP交互的功能。本章主要内容有以下几个方面 使用ASP内置接口。 与COM+进行接口。 通过C++使用ADO。 使用 OLE DE消费者模板。 18.1与ASP进行接口 前一章创建的组件没有考虑到在ASP中的使用,如果想创建在任何环境中使用的一般组 件这是有效的。然而,如果ASP页能访问信息,组件也能访问的话,这个组件在Web应用程序 中将会十分有用。如果能够完成像ASP页一样的基于Web的交互功能,则这个组件将更有用 COM的世界十分精彩,可用C++组件做任何事情。就像在ASP中可以有各种各样可用的对 象一样,可从服务器对象访问这些组件。在ASP中所做的工作大部分可通过下列内置对象实现 Request、 Response、 Session、 Application和 Server。指向任一对象的指针可通过 Scripting Context 获得。因此,关键是得到指向 Scripting Context的指针,然后寻找相应的内置对象 与多数编程工作不同,程序的代码是由 Visual c++ AppWizard产生的。我们要使第17章中创 建的组件“启用ASP”,这时将有两个选择:一种是在本章中创建组件,拷贝并粘贴合适的代码 到前面的组件中:另一种从一个新的组件开始,并加入在前一章中编写的代码。我们选择后者。 使用不同的向导选项创建组件的框架,然后通过 Windiff观察附加代码的生成, 这将有助于理解。Wnd是Vsua|C++附带的程序 使用在上一章创建 ASPComponents TL Object ward Ⅴ isual c++项目,插入一个新的ATL对象 创建一个 ActiveX Server组件而不是创建 Simple object,命名为 CTable Storage2 Simple Obect Addn Obect Intenet 图18-1所示。 Simple object向导与 ActiveX Server向 导的不同在于后者包含ASP属性页。在ASP conery MMC Snapin 属性页中,仅选择 Response复选框。在我 们的例子中,仅使用 Response.对象,但是 如果需要再添加其他内置对象也非常容易, 图18-1创建 ActiveX Server组件 如图18-2所示
下载 第18章 对C++组件的进一步讨论 在前一章中,我们学习了用 C + +创建C O M组件的基本方法,用这些概念创建的组件对于 在内存中处理数据是非常有用的。但是,要制作一个功能强大的服务器组件,需要使用微软 平台提供的其他服务。特别是,创建的组件应能提供对数据的访问、与 C O M +进行接口以及 与A S P交互的功能。本章主要内容有以下几个方面: • 使用A S P内置接口。 • 与C O M +进行接口。 • 通过C + +使用A D O。 • 使用OLE DB消费者模板。 18.1 与A S P进行接口 前一章创建的组件没有考虑到在 A S P中的使用,如果想创建在任何环境中使用的一般组 件这是有效的。然而,如果 A S P页能访问信息,组件也能访问的话,这个组件在 We b应用程序 中将会十分有用。如果能够完成像 A S P页一样的基于We b的交互功能,则这个组件将更有用。 C O M的世界十分精彩,可用C + +组件做任何事情。就像在A S P中可以有各种各样可用的对 象一样,可从服务器对象访问这些组件。在A S P中所做的工作大部分可通过下列内置对象实现: R e q u e s t、R e s p o n s e、S e s s i o n、A p p l i c a t i o n和S e r v e r。指向任一对象的指针可通过S c r i p t i n g C o n t e x t 获得。因此,关键是得到指向S c r i p t i n g C o n t e x t的指针,然后寻找相应的内置对象。 与多数编程工作不同,程序的代码是由Visual C++ AppWi z a r d产生的。我们要使第1 7章中创 建的组件“启用A S P”,这时将有两个选择:一种是在本章中创建组件,拷贝并粘贴合适的代码 到前面的组件中;另一种从一个新的组件开始,并加入在前一章中编写的代码。我们选择后者。 使用不同的向导选项创建组件的框架,然后通过 Wi n d i ff观察附加代码的生成, 这将有助于理解。Wi n d i ff是Visual C++附带的程序。 使用在上一章创建 A S P C o m p o n e n t s Visual C++项目,插入一个新的 AT L对象。 创建一个 ActiveX Server 组件而不是创建 Simple Object,命名为C Ta b l e S t o r a g e 2,如 图1 8 - 1所示。 Simple Object向导与ActiveX Server向 导的不同在于后者包含 A S P属性页。在A S P 属性页中,仅选择 R e s p o n s e复选框。在我 们的例子中,仅使用 R e s p o n s e对象,但是 如果需要再添加其他内置对象也非常容易, 如图1 8 - 2所示。 图18-1 创建ActiveX Server组件
dacm,m的539 ATL Object wizard 区 Names Attributes ASP StarTpage/OnEndPage 三 图18-2选择ASP内置对 表现了 Visual c+的灵活性和高效性,仅选择所需要的特性,可减少组件的代码。当 然,与在ASP中不同,特性不仅仅是编程环境的一部分,增加特性就要增加代码 不选择 OnStartPage/OnEndPage时,所有内置对象均无效。必须调用 On StartPage才能得到 内置对象。如果选择内置对象,将会自动产生 OnStartPage和 On EndPage。这种相关性必须引 起开发人员的注意。 我们来看一下选用 ActiveX Server组件后产生的代码,如果已有一个启用ASP的组件,必 须人工插入这段代码。 首先,文件 Table Storage2h中有一个新的头文件,它包含使用 Scripting Context和ASP内置 对象所需的常数和定义 #include mpiResporse //Response object BOOL m bonstartPageCailed; //OnstartPage successful? 另一个成员变量是一个布尔变量,表示调用 On StartPage是否成功,后面你将看到其重要 性。在构造器中这个变量被初始化为 FALSE(在对象首次被创建时,会调用构造器)。在C++中 构造器和析构器起的作用分别与ⅤB中的 Class Initialize和 Class Terminate方法相同 CTableStorage2 m bonstartPagecalled FALSE
图18-2 选择A S P内置对象 这表现了Visual C+ +的灵活性和高效性,仅选择所需要的特性,可减少组件的代码。当 然,与在A S P中不同,特性不仅仅是编程环境的一部分,增加特性就要增加代码。 不选择O n S t a r t P a g e / O n E n d P a g e时,所有内置对象均无效。必须调用 O n S t a r t P a g e才能得到 内置对象。如果选择内置对象,将会自动产生 O n S t a r t P a g e和O n E n d P a g e。这种相关性必须引 起开发人员的注意。 我们来看一下选用 ActiveX Server组件后产生的代码,如果已有一个启用 A S P的组件,必 须人工插入这段代码。 首先,文件Ta b l e S t o r a g e 2 . h中有一个新的头文件,它包含使用 S c r i p t i n g C o n t e x t和A S P内置 对象所需的常数和定义。 注意,这里使用S c r i p t i n g C o n t e x t而不是使用较新的O b j e c t C o n t e x t,AT L向导产生 使用S c r i p t i n g C o n t e x t的代码,一般情况下不必进行修改。 你将看到增加了 O n S t a r t P a g e和O n E n d P a g e方法。有了这两个方法,就可以在 A S P页面创 建这个组件时,或在A S P页面用过它之后做一些工作。这些方法将在以后讨论。 在类里面增加了一些成员变量。其中一个是 R e s p o n s e对象的指针。如果选择其他的 A S P内 置对象,也要为它们声明指针。指向对象的指针声明后,这个指针实际上还没有指向这个对象。 另一个成员变量是一个布尔变量,表示调用 O n S t a r t P a g e是否成功,后面你将看到其重要 性。在构造器中这个变量被初始化为 FA L S E (在对象首次被创建时,会调用构造器 )。在C + +中 构造器和析构器起的作用分别与 V B中的C l a s s _ I n i t i a l i z e和C l a s s _ Te r m i n a t e方法相同。 第1 8章 对C + +组件的进一步讨论计计539 下载
540A5p装程 下载 这是头文件的全部变化。我们再来看一下 App Wizard为 Tablestorage2cpp生成的代码。这 个代码实现了 OnstartPage和 OnEndPage方法。如果转换上一章中的组件,在 ASPComponents. cpp中必须有一行是# include Table Storage2h On Start Page的主要任务是得到 Scripting Context和指向ASP内置对象的指针。在这个例子 中只有得到 Response对象的代码。再强调一次,如果选择了其他的ASP内置对象,就得到指 向它们的指针。一旦成功获取了指向ASP内置对象的指针,m_ bOnStartPage Called将置为 TRUE。可用这个变量对使用ASP内置对象是否安全进行检查: STDMETHODIMP CTablestorage2: OnstartPage(IUnknown* pUnk) it(! pUnk) return E POINTER ComPer spContexti / Get the IScriptingcontext Interface hr. pUnk->QueryInterface(IID_IScriptingContext, (void **)&spContext); if(FAILED(hr)) //Get Response object pointer hr context Response(&m piResponse) if(FAILED(hr)) return hr m bonstartPageCalled= TRUE; return s_OK ASP页处理完后,调用 OnEndPage方法,这时ASP内置对象的指针没有意义,因此释放接 口,并且 m bon StartPage Called置为 FALSE: STDMETHODIMP CTablestorage2: OnEndPage() m bonstartPageCalled FALSE; Release all inter faces nse return soK: 如果在ASP页中对象有效期的开头和结尾处要进行一些处理的话,可在 OnStartPage和 On EndPage内编写程序 简单的组件与 ActiveX server组件不同。 OnStartPage和 On EndPage方法通过 ActiveX自动 化提供,所以在组件的外部可以调用。要这样做必须在接口定义语言(IDL)文件中对此进行说 明。在 ASPComponents. idl中有这两条语句 interface ITablestorage2: IDispatch //Standard Server side Component Methods HRESULT OnstartPage([in] IUnknown* piNk); HRESULT OnEndPage(
这是头文件的全部变化。我们再来看一下 A p p Wi z a r d为Ta b l e S t o r a g e 2 . c p p生成的代码。这 个 代码 实现 了 O n S t a r t P a g e 和 O n E n d P a g e 方 法。 如果 转换 上一 章中 的组 件,在 A S P C o m p o n e n t s . c p p中必须有一行是#include Ta b l e S t o r a g e 2 . h。 O n S t a r t P a g e的主要任务是得到 S c r i p t i n g C o n t e x t和指向A S P内置对象的指针。在这个例子 中只有得到 R e s p o n s e对象的代码。再强调一次,如果选择了其他的 A S P内置对象,就得到指 向它们的指针。一旦成功获取了指向 A S P内置对象的指针, m _ b O n S t a r t P a g e C a l l e d将置为 T R U E。可用这个变量对使用A S P内置对象是否安全进行检查: A S P页处理完后,调用O n E n d P a g e方法,这时A S P内置对象的指针没有意义,因此释放接 口,并且m _ b O n S t a r t P a g e C a l l e d置为FA L S E: 如果在A S P页中对象有效期的开头和结尾处要进行一些处理的话,可在 O n S t a r t P a g e和 O n E n d P a g e内编写程序。 简单的组件与ActiveX Server组件不同。O n S t a r t P a g e和O n E n d P a g e方法通过A c t i v e X自动 化提供,所以在组件的外部可以调用。要这样做必须在接口定义语言 ( I D L )文件中对此进行说 明。在A S P C o m p o n e n t s . i d l中有这两条语句: 540计计ASP 3 高级编程 下载
chinapub. coM ixs Ac Bsmt -t 541 编译组件时,MIDL编译器使用IDL文件创建一个类型库和调度代码 现在已经可以在组件中使用 Response对象了。先添加一个方法来使用它。在前一章中我 们编写了一个ASP程序,它用存储在组件中的数据生成HTML。如果由组件本身产生HTML表 组件会更强大。这一修改使得性能更为优越,并封装了绘制逻辑。 封装具有许多好处。对于生成表,所有绘制代码集中到一个地方,任何ASP页可调用包 含这段代码的组件,并可以运行它。很显然这比在页和页之间拷贝同样的代码或编写新的代 码简单。开发人员可主要关心将像数据存取这样的高层次问题,而不是去寻找遍历数据并在 表中显示的方式。调用一个组件和运行预编译代码比分析一系列复杂的HIML命令快得多 最后需要说明的是即使绘制编码需要有微小的修改,组件也要重新编译。开发组件时应 仔细考虑程序员在生成表时需要设置的参数。用户可修改的特征,如边界尺寸、表格单元的 背景色,可作为参数传给接口方法,而不必进行硬编码。但是如果组件接口改变,使用这个 口的ASP页必须进行修改。 Add Met 还有一点需要说明,必须在 ITableStorage2中增加与 ITableStorage相同的方 法,例如 Parsecs、 GetField和Mww GetColumnName等。详细内容可参阅第17章 在 ITableStorage2中增加一个新方法ars Output Table,按照图18-3所示的对话框进行 配置 OupuT 虽然增加其他表格属性如颜色、单元宽 度等也很简单,但为了说明方便,仅允许改 变边界尺寸。 OutputTable的代码如下: 图18-3增加新方法 STDMETHODIMP CTablestorage2:: OutputTable( short bordersize HRESULT hResult wstring tempstring; tablestring [321 if((m_ bonstartPageCalled = TRUE)&&(mpiResponse ! NULL)) 2r pmte( tablestring, " TABLE border=sd>,bordersize ) mpiResponse->Write( CComvariant( tablestring ) 首先确认 m bOnStart Page Called为TRUE并且,m_ reSponse确实包含一个指针。如果检 查通过,就可以使用 Response对象。 Write方法希望字符串为 variant,在C++中使用 variant.必须指定一种 variant类型。最简单的 方法是将字符串作为字符类型,并用 CCom variant类构造一个 variant。下一步输出表列: the tables headers COLUMN_ INDEX_MAP: iterator mapIter mcolumnIndexMap. begin(); hile mapIter I= m_columnIndexMap. end()) tempstring L": tempString +=(*mapIter) first cstr()i tempstring + L" mpiResponse->Write( CComVariant( tempstring. c_str())):
第1 8章 对C + +组件的进一步讨论计计541 编译组件时,M I D L编译器使用I D L文件创建一个类型库和调度代码。 现在已经可以在组件中使用 R e s p o n s e对象了。先添加一个方法来使用它。在前一章中我 们编写了一个A S P程序,它用存储在组件中的数据生成H T M L。如果由组件本身产生H T M L表, 组件会更强大。这一修改使得性能更为优越,并封装了绘制逻辑。 封装具有许多好处。对于生成表,所有绘制代码集中到一个地方,任何 A S P页可调用包 含这段代码的组件,并可以运行它。很显然这比在页和页之间拷贝同样的代码或编写新的代 码简单。开发人员可主要关心将像数据存取这样的高层次问题,而不是去寻找遍历数据并在 表中显示的方式。调用一个组件和运行预编译代码比分析一系列复杂的 H T M L命令快得多。 最后需要说明的是即使绘制编码需要有微小的修改,组件也要重新编译。开发组件时应 仔细考虑程序员在生成表时需要设置的参数。用户可修改的特征,如边界尺寸、表格单元的 背景色,可作为参数传给接口方法,而不必进行硬编码。但是如果组件接口改变,使用这个 接口的A S P页必须进行修改。 还 有 一 点 需 要 说 明 , 必 须 在 I Ta b l e S t o r a g e 2中增加与I Ta b l e S t o r a g e相同的方 法 , 例 如 P a r s e C S V 、 G e t F i e l d 和 G e t C o l u m n N a m e等。详细内容可参阅第1 7章。 在I Ta b l e S t o r a g e 2中增加一个新方法 O u t p u t Ta b l e,按照图1 8 - 3所示的对话框进行 配置。 虽然增加其他表格属性如颜色、单元宽 度等也很简单,但为了说明方便,仅允许改 变边界尺寸。O u t p u t Ta b l e的代码如下: 首先确认m _ b O n S t a r t P a g e C a l l e d为T R U E并且,m _ p i R e s p o n s e确实包含一个指针。如果检 查通过,就可以使用R e s p o n s e对象。 Wr i t e方法希望字符串为v a r i a n t,在C + +中使用v a r i a n t必须指定一种v a r i a n t类型。最简单的 方法是将字符串作为字符类型,并用 C C o m Va r i a n t类构造一个v a r i a n t。下一步输出表列: 图18-3 增加新方法 下载
542A5p2装程 China pus oM 下载 列的名称作为键存储在列映射中,因此,可以遍历列映射得到列的名称,并显示在表格 的表头中。像前面一样,将字符串转换为 variant,与 Response对象一起送到浏览器中,一旦 列输出完成,接下来处理行: rowIter m rows. begin( INDEX_ FIELD_MAP::iterator fieldIter while( rowIter !s m rows. end( mapIter m-columnIndexMap begin(): while mapIter I= m columnIndexMap end() fieldIter -(*rowIter) find((*mapIter) second )i 每一行是 vector数据结构中的一个元素,因此可遍历mrow。列的数据与列的标题对应 上一章讲过行数据使用映射可使存储空间最小。因此,可遍历列名称以判定特定行是否有值, 如果其值存在,则输出,否则,输出一个空的表格单元 最后关闭HTML标记并递增遍历器: tempstring + L'Write( CComVariant( tempstring. c str()))i Iter. mpiResponse->write( CComVariant( "'))i rowIter++ mpiResponse->Write( CComVariant(".)) return hResult 使用此组件的ASP代码类似于: TableStorage C++ Component Test Driver Dim objTablestorage Dim cstRing csvString =Name, Group, Instrument& vbNewline csvString= csvString &Robert Plant, Led Zeppelin, Vocals& vbNewLine
列的名称作为键存储在列映射中,因此,可以遍历列映射得到列的名称,并显示在表格 的表头中。像前面一样,将字符串转换为 v a r i a n t,与R e s p o n s e对象一起送到浏览器中,一旦 列输出完成,接下来处理行: 每一行是v e c t o r数据结构中的一个元素,因此可遍历 m _ r o w。列的数据与列的标题对应。 上一章讲过行数据使用映射可使存储空间最小。因此,可遍历列名称以判定特定行是否有值, 如果其值存在,则输出,否则,输出一个空的表格单元。 最后关闭H T M L标记并递增遍历器: 使用此组件的A S P代码类似于: 542计计ASP 3 高级编程 下载
(0N0。,的543 cstring The Doors,voca18”& he who, Drums.& vbnewline x,, Guitar Vocals.& vbNewlLine Set objTableStorage2- Server Createobject('ASPComponents Tablestorage2') ob]TableStorage2. Parsecsv csvstring objTablestorage2. Sort ' N Number for Columns: Number for Rows: objTablestorage2. OutputTable 1 这与上一章中的ASP代码非常相似,区别只是没有遍历字段以显示数据,仅须调用 OutputTable。这段代码比较简洁并可得到相似的结果,如图18-4所示。 TableStorage C++ Component Test Driver Number for Columns: 3 Number for Rows: 5 Grop「 Instrument「 The Doors Vocals Jim morrison vocals Jimi hendrix The Who Drum Keith Moon Kraft 图18-4浏览器中显示的表 此表仅是相似,列的顺序不同。这是因为C++程序与ASP代码用不同的方式进行列遍历, C艹+中列按字母顺序存储在map数据结构中。另一方面,ASP代码以列存储的顺序进行遍历, 其存储的顺序是“Name、 Group、 Instrument”,是由上一章的例子生成的输出。可以扩展 OutputTable方法,使用户可指定列的顺序,而不需要改变代码 综上所述,如果可以与其环境交互,C++服务器组件会更有用。在这种情况下,C++组件 可通过COM得到各种ASP内置对象的指针。这样可以让组件利用ASP的固有功能。我们仅分 析了一个ASP内置对象,其余的都以同样的方式工作。下面介绍C++服务器组件如何通过 COM+与其环境交互 18.2与cOM+进行接口 特别应当注意:suaC++向导仍采用术语“MTS”, Visual c++头文件和静态库名 称中仍含有“mt”。因此,本节中我们使用术语“ MTS/COM+”,而不只是“cOM+
这与上一章中的 A S P代码非常相似,区别只是没有遍历字段以显示数据,仅须调用 O u t p u t Ta b l e。这段代码比较简洁并可得到相似的结果,如图 1 8 - 4所示。 图18-4 浏览器中显示的表 此表仅是相似,列的顺序不同。这是因为 C + +程序与A S P代码用不同的方式进行列遍历, C + +中列按字母顺序存储在 m a p数据结构中。另一方面, A S P代码以列存储的顺序进行遍历, 其存储的顺序是“ N a m e、G r o u p、I n s t r u m e n t”,是由上一章的例子生成的输出。可以扩展 O u t p u t Ta b l e方法,使用户可指定列的顺序,而不需要改变代码。 综上所述,如果可以与其环境交互, C + +服务器组件会更有用。在这种情况下, C + +组件 可通过C O M得到各种A S P内置对象的指针。这样可以让组件利用 ASP 的固有功能。我们仅分 析了一个 A S P内置对象,其余的都以同样的方式工作。下面介绍 C + +服务器组件如何通过 C O M +与其环境交互。 18.2 与C O M +进行接口 特别应当注意:Visual C++向导仍采用术语“M T S”,Visual C++头文件和静态库名 称中仍含有“m t x”。因此,本节中我们使用术语“M T S / C O M +”,而不只是“C O M +”。 第1 8章 对C + +组件的进一步讨论计计543 下载
544AsP3高级程 Chinapub.com 下载 Visual c++在两个方面提供 MTS/COM+支持:一是在创建项目时,二是在项目中使用指 定的组件时 首先来看一下 MTS/COM+对于项目的支持。当编译和链接项目时,便转换为DLL或 在项目中使用 MTS/COM+服务时,必须链接指定的库。 Visual c++ App Wizard可帮助完成此 项任务 在你第一次创建项目时,可能已注意到了 Support mTs复选框,如图18-5所示。 ATL COM Appwizard. Step 1 of 1 Th wead Set as C Dynamic Lrk Libary DLLI C Executable EXEI gng of poy/stub code poot MFC R18-5 Visual C++ Appwizard 如果选定此复选框,不会产生附加代码,但向导改变项目设置使其“启用COM+”。特别 是,向链接线增加了mtx.ib、 mtxguid lib和 delaying.lib库。因此,如果没有对上述复选框进 行选定,仍可通过如图18-6所示的方式在链接线中添加这些文件名,使现有的组件“启用 COM+"。 地h以 m produce LB 32b od32 Ib wrspodl 图18-6添加库 另一个选择是创建启用COM+的组件。当在项目上添加一个新的ATL组件时,选择MS ransaction Server Component,如图18-7所示
Visual C++在两个方面提供 M T S / C O M +支持:一是在创建项目时,二是在项目中使用指 定的组件时。 首先来看一下M T S / C O M +对于项目的支持。当编译和链接项目时,便转换为 D L L或E X E。 在项目中使用M T S / C O M +服务时,必须链接指定的库。 Visual C++ AppWi z a r d可帮助完成此 项任务。 在你第一次创建项目时,可能已注意到了 Support MTS复选框,如图1 8 - 5所示。 图18-5 Visual C++ AppWi z a r d 如果选定此复选框,不会产生附加代码,但向导改变项目设置使其“启用 C O M+”。特别 是,向链接线增加了 m t x . l i b、m t x g u i d . l i b和d e l a y i m p . l i b库。因此,如果没有对上述复选框进 行选定,仍可通过如图 1 8 - 6所示的方式在链接线中添加这些文件名,使现有的组件“启用 C O M +”。 图18-6 添加库 另一个选择是创建启用 C O M +的组件。当在项目上添加一个新的 AT L组件时,选择 M S Transaction Server Component,如图1 8 - 7所示。 544计计ASP 3 高级编程 下载
ap60,的545 下载 留区 图18-7在项目中增加新的ATL组件 单击属性页将出现图18-8所示的内容 ATL Object wizard F Names MTS I 图18-8 ATL Object Wizard Properties对话框 创建 MTS/COM+对象时,向导将在项目中添加代码,下面看一下这种配置产生的附加代 在新组件的头文件中,你可看到增加了一个包含文件 #include 和用于ASP内置对象的包含文件类似,此文件包含在C++组件中使用 MTS/COM+组件所 需的常数和定义。组件中头文件还有一处改变 DECLARE NOT_ AGGREGATABLE(CTablestorage2) MTS/COM+对象不能作为其他对象集合体的一部分使用。因此,必须插入代码防止这种 情况发生。 如果不使用 App Wizard创建组件,使组件“启用COM+”是非常容易的。如果选择 TObject Control支持,应该在项目中插入下列附加代码。组件的头文件中也有些改变。 首先,组件继承 OBject Control接口,因此它必须实现该接口定义的方法 class ATL NO VTABLE cTableStorage2: public CComobjectRootEx<CComSingleThreadMode public CComcoclass<CTablestorage2, &CLSID_TableStorage2 public ISupportErrorIn public Iobjectcontrol
图18-7 在项目中增加新的 ATL 组件 单击属性页将出现图1 8 - 8所示的内容。 图18-8 ATL Object Wizard Properties对话框 创建M T S / C O M +对象时,向导将在项目中添加代码,下面看一下这种配置产生的附加代 码。 在新组件的头文件中,你可看到增加了一个包含文件: 和用于A S P内置对象的包含文件类似,此文件包含在 C + +组件中使用 M T S / C O M +组件所 需的常数和定义。组件中头文件还有一处改变: M T S / C O M +对象不能作为其他对象集合体的一部分使用。因此,必须插入代码防止这种 情况发生。 如果不使用 A p p Wi z a r d创建组件,使组件“启用 C O M +”是非常容易的。如果选择 I O b j e c t C o n t r o l支持,应该在项目中插入下列附加代码。组件的头文件中也有些改变。 首先,组件继承I O b j e c t C o n t r o l接口,因此它必须实现该接口定义的方法: 第1 8章 对C + +组件的进一步讨论计计545 下载
546A5p3高程 China-pub.com 下载 public IDispatchImpl 确保向导声明了 OBject Control的方法和 ObjectContext的指 / IObjectcontrol STDMETHOD(Activate)() STDMETHod-(BOOL, CanBepooled)() Deact CComPtr mspobjectcontext 向导在源文件中实现这些方法。当第一次使用对象时调用 Activate方法,并自动生成 ObjectContext的指针 HRESULT CTablestorage2: Activate() HRESULT hr= Getobjectcontext(&mspobjectcontext)i if (SUCCEEDED(hr)) turn s oK 如果选择 oBject Control支持,而没有缓冲对象, Can Bepooled方法将返回 FALSE: BOOL CTablestorage2:: CanBePooled( return FALSE 后面将详细讨论对象缓冲问题。最后,当对象不再使用时,将释放对 lObjectContext的引 用 void CTablestorage2:: Deactivate() m_spobjectcontext Release(); 对于服务器组件,有许多 MTS/COM+接口可用。下面以 lObjectContext接口为例进行讨 182.1 ObjectContext的事务处理 每个 MTS/COM+对象均有相应的环境。环境隐含着与对象相关的状态,包含对象的执行 环境信息和参与的事务的信息 lObjectContext可完成下列功能 声明工作完成 不允许提交暂时的或永久的事务 在当前事务范围内开始新的 MTS/COM+对象 检查调用者的角色 检查安全性 检查事务状态 在前一节中,组件已经有一个对 tObject Context接口的引用。我们将实现 Clear方法,从组 件中删除所有数据。对 ITable Storage2接口添加一个不带任何参数的clea(方法,用下列代码 填写此方法的主体中:
确保向导声明了I O b j e c t C o n t r o l的方法和O b j e c t C o n t e x t的指针。 向导在源文件中实现这些方法。当第一次使用对象时调用 A c t i v a t e方法,并自动生成 O b j e c t C o n t e x t的指针。 如果选择I O b j e c t C o n t r o l支持,而没有缓冲对象,C a n B e P o o l e d方法将返回FA L S E: 后面将详细讨论对象缓冲问题。最后,当对象不再使用时,将释放对 I O b j e c t C o n t e x t的引 用。 对于服务器组件,有许多 M T S / C O M +接口可用。下面以 I O b j e c t C o n t e x t接口为例进行讨 论。 18.2.1 IObjectContext的事务处理 每个M T S / C O M +对象均有相应的环境。环境隐含着与对象相关的状态,包含对象的执行 环境信息和参与的事务的信息。 I O b j e c t C o n t e x t可完成下列功能: • 声明工作完成。 • 不允许提交暂时的或永久的事务。 • 在当前事务范围内开始新的 M T S / C O M +对象。 • 检查调用者的角色。 • 检查安全性。 • 检查事务状态。 在前一节中,组件已经有一个对 I O b j e c t C o n t e x t接口的引用。我们将实现 C l e a r方法,从组 件中删除所有数据。对 I Ta b l e S t o r a g e 2接口添加一个不带任何参数的 C l e a r ( )方法,用下列代码 填写此方法的主体中: 546计计ASP 3 高级编程 下载
Mad0N,.547 STDMETHODIMP CTablestorage2:: Clear() m rows. clear() m_columnIndexMap clear()i mspobjectcontext->Setcomplete()i return s_ OKi 这个方法的目的是删除组件中的所有数据。必须检查 ObjectContexti的引用是否确实存在 如果在COM+以外使用组件,这个指针的值不存在,进行引用会引起组件崩溃。在这个例子 中,调用 SetComplete方法告诉COM+“不再保持状态,可以释放。” 1822 lObjectcontrol的对象缓冲 lObjectControl接口用于对象缓冲,可增强应用程序的性能。当超出对象的使用范围时 被缓冲的对象不会真的破坏,只是处于无效状态。当请求这种类型的对象时,可以重新使用 这个对象,组件被循环使用。性能增强的原因是当一个对象无效时,对象没有完全损坏,因 此就不需执行很多工作。同样,激活一个无效对象也不需执行很多工作 在创建MTS/COM+对象时,对象缓冲可通过 AtL Object Wizard Properties对话框启用, 如图18-9所示 图18-9启用对象缓冲 主意 Can be pooled选项只能在选定 Support lObjectcontro后才能选定。另一种方式是将 e Pooled方法中的返回值改为TURE BOOL cTablestora CanBePooled( return TRUE 使用对象缓冲所需做的工作仅此而已。 上面讲述了组件如何与ASP和COM+相互作用,下面我们讲述组件如何访问永久性数据。 183数据访问 服务器组件一般用于实现三层应用程序的业务规则,因此需要与数据库交互。C++访问数
这个方法的目的是删除组件中的所有数据。必须检查 O b j e c t C o n t e x t的引用是否确实存在。 如果在C O M +以外使用组件,这个指针的值不存在,进行引用会引起组件崩溃。在这个例子 中,调用S e t C o m p l e t e方法告诉C O M +“不再保持状态,可以释放。” 18.2.2 IObjectControl的对象缓冲 I O b j e c t C o n t r o l接口用于对象缓冲,可增强应用程序的性能。当超出对象的使用范围时, 被缓冲的对象不会真的破坏,只是处于无效状态。当请求这种类型的对象时,可以重新使用 这个对象,组件被循环使用。性能增强的原因是当一个对象无效时,对象没有完全损坏,因 此就不需执行很多工作。同样,激活一个无效对象也不需执行很多工作。 在创建M T S / C O M +对象时,对象缓冲可通过 ATL Object Wizard Properties对话框启用, 如图1 8 - 9所示。 图18-9 启用对象缓冲 注意Can be pooled选项只能在选定 Support IObjectControl后才能选定。另一种方式是将 C a n B e P o o l e d方法中的返回值改为T U R E: 使用对象缓冲所需做的工作仅此而已。 上面讲述了组件如何与A S P和C O M +相互作用,下面我们讲述组件如何访问永久性数据。 18.3 数据访问 服务器组件一般用于实现三层应用程序的业务规则,因此需要与数据库交互。 C + +访问数 第1 8章 对C + +组件的进一步讨论计计547 下载