|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
由于ASP提供的是一对多的服务,所以用户的一些特殊需求很难得到满足。c++|办事器
C++是尺度化的盘算机言语,不属于任何人,而属于一个尺度委员会。STL是撑持数据布局和算法的C++扩大。ATL是微软具有和保护的模板库,使得COM编程更轻易。综合这些手艺构成了创立COM组件的一种无效办法,这些COM组件用于ASP页面。
上面用一切这些手艺创立一个COM对象,你将看到VC++ 6.0的导游若何供应大批代码,因而,可以把注重力集中在处理成绩上,而不是忧虑详细的编程细节。
17.3.1 成绩
体现数据的最通俗办法是表,列代表字段的类型,每行是一笔记录,具有字段的值。在文本文件中,表凡是由用逗号分隔的值(comma-separated values,CSV)构成。
咱们将要创立的COM组件以CSV数据作为输出,高效地存储它,并供应会见函数去检索它。这些数据在COM组件中以STL数据布局暗示。在今后局部中,咱们会看到如何用STL算法去向理这些数据。别的,鄙人一章,将引见如何在数据库中存贮存这些数据。
为了便于申明,假定数据在一个稀少表中。第一行的字段是列题目,接上去的是一条条数据纪录,纪录的每一个字段对齐于列题目。逗号隔离字段,换行符(/n)隔离行,空的字段用两个逗号暗示,即“,,”。
表17-1是一个睁开的表的例子。导出时,逗号会隔离每个字段。
17.3.2 设计
这个组件的设计目标是使数据的存储空间和会见工夫最小。因为数据有多是稀少的,即很多字段是空的,这就有能够使数据的存储空间最小化。可以经由过程数值(基于零的索引)会见数据的行,可以经由过程字段名会见数据的列。例如,要失掉表17-1中Keith Moon的Instrument,可以挪用GetField (1,"Instrument")。
完成以上任务的东西是STL的vector和map数据布局,这些数据布局是容器,就是说,它们是包括其他对象的一个纠合的对象。为了会见纠合中的对象,利用STL遍历器。
17.3.3 完成
如今你对这个组件的功效已有了概念,咱们将按上面的步调完成它:
? 创立包括组件的DLL。
? 创立组件。
? 增添属性。
? 增添办法。
1. 创立DLL和一个组件
选择ATLCOMAppWizard,创立一个新的VC++项目,然后定名为ASPCOMponents。利用默许的办事器类型(DLL),不选中复选框,如图17-1所示。
当完成后,这个导游会主动发生一个组件的外壳。这时候没有组件存在,只要DLL依据COM标准所请求的函数存在,可以在ASPCOMponents.cpp文件中看到这些函数,但不必关怀文件的细节,也不必改动它。当向DLL中添加组件时,导游会修正该文件。
如今将组件放入DLL。在任务区窗口选择ClassView选项卡,右击ASPComponents Classes,选择New ATL Object。然后再选Simple Object,而且在Short Name框中键入Tablestorage,如图17 - 2所示。
除非你盘算更深切地研讨ATL,不然在Attributes选项卡坚持默许形态,不用改动任何选项。对一切这些选项的意义的具体描写已超越本书的局限。Attributes选项卡如图17-3所示。
点击OK后,就有了一个用来任务的对象。
到今朝为止,VC++导游已完成了一切的任务,假如检查TableStorage.h,你会看到导游发生的ATL代码。在大多半情形下,不用改动这些代码。实践上,可以只依托这些代码,不必懂得ATL,持续停止编程。但是,需求对默许的设置做一点改动,使得生成的代码可以编译。
为了减小组件的巨细,当AppWizard创立一个组件时,主动封闭C++的异常处置。由于假如启用这一功效的话,则需求C运转期库。STL利用异常处置,所以需求启用它。在ProjectSettings对话框的C/C++选项卡中,下拉Category框选择C++ Language,确保Settings for框设置为All Configurations,选择Enable exception handing复选框,如图1 7 - 4所示。
假如用Release形式编译能够会失掉一个链接毛病。当编译一个刊行版本的ATL项目时,假如异常处置没有封闭,会呈现如许的成绩。利用异常处置时,需求C运转期启动代码;然而在默许体例下,Release形式的ATL项目界说了_ ATL _MIN_CRT符号,它回绝启动代码。为懂得决这个成绩,在C/C++预处置器界说中删除_ ATL_MIN_CRT。具体材料请看微软基本常识库中的文章Q165259。
咱们增添的第一段代码用于创立STL数据布局,把以下代码加到TableStorage.h的开首:
这里,声了然两个映照和一个矢量。这个矢量实践是两个映照之一的矢量。利用C++的typedef号令界说映照和矢量次要是为了使得代码更容易读,对数据类型描写得更好。
COLUMN_INDEX_MAP将一个字符串(列的称号)映照到一个索引中。INDEX_FIELD_MAP暗示数据表中的每行的数据。因为他多是一个稀少行,用一个映照完成是高效的,空字段不占用任何空间。INDEX_FIELD_MAP映照COLUMN_INDEX_MAP供应的索引到字段值。最初,ROW_VECTOR包括代表行的每个映照。
如今已申明了外部数据布局,可将它们用于利用属性的内部世界。
2. 增添属性
咱们将增添两个属性:行数属性和列数属性。
在项目任务区选择ClassView选项卡,右击ITableStorage接口。在菜单当选择Add Property,按图1 7 - 5填写对话框。选择Get Function复选框,而不选择Put Function复选框,使得它为只读属性。
发生前往这一属性的get_numRows办法。这就是说可有发生属性值的逻辑。在这类情形下,可经由过程挪用行矢量的size()办法设置属性:
如今有了取得所存储数据的行数和列数的办法,还需让一些数据输出到组件中,这是下一步要做的任务。
3. 增添办法
到今朝为止,还没法把任何数据输出到外部数据布局中,也没法读取它们。上面增添四个办法完成以下义务:
? 在数据布局中拔出数据。
? 从数据布局中获得一个字段。
? 获得列称号。
? 对列停止排序。
(1) 剖析数据
第一个办法将取得一个以逗号隔离的字符串,停止剖析,再将数据输出数据布局中。
在项目任务区当选择ClassView选项卡,右击ITableStorage接口。在菜单当选择AddMethod,按图17 - 6填写对话框。
然后用以下代码填写ParseCSV办法的主体局部:
CSV数据作为一个字符串参数传递,并排除两个STL成员变量,删除之前挪用这个办法时输出的数据。
要出格注重第一行, 由于它包括列的称号,每列的称号作为一个键存储在m_columnIndexMap中,用映照确当前巨细作为索引。当一行处置完后,可以使用列称号映照的索引也就是列的数值索引这一现实。假如被剖析的字段无数据,就将其存储在INDEX_FIELD_MAP中。
一旦一切行都处置完后, COM组件中的CSV数据的存储空间已最小化,而且因为利用映照可以加速会见速度。由于只存储了有实践值的字段,所以存储空间最小。因为映照在外部组织数据,可疾速检索,会见速度很快。
(2) 数据会见
如今数据已能高效存储,下一步是可以会见它。
向ITableStorage接口添加一个称为GetField的新办法,按图17 - 7对对话框停止填写。
给定行数和列称号,这个办法将前往字段值(假如它存在)。改动这个办法的主体,以下所示:
用于取得与映照的键绝对应的值的映照办法是find。关于COLUMN_INDEX_MAP映照,从find中前往pair<wstring, unsigned short>类型的遍历器。假如没有找到键,遍历用具有m_columnIndexMap.end()的值。假如找到键,前往的遍历器的second成员包括对应值:在这类情形下,它是列称号的索引。这个索引作为INDEX_FIELD_MAP映照的键,给定行便可失掉字段值。假如找到这个值,经由过程[out, retval]参数前往,也就是fieldValue。
上面创立一个失掉列称号的办法。在ITableStorage中添加一个称为GetColumnName的新办法,按图17 - 8所示填写对话框。
给定一列的索引,这个办法将前往列的称号,用以下代码改动这个办法的主体:
在这个办法中,必需经由过程映照停止线性查找,由于法式实践是利用键的值而不是键停止检索,遍历m_columnIndexMap映照直到找到索引或搜刮到映照的末尾(即索引未找到)。注重遍历器的second成员用于对照,这是由于查找的是键的值而不是键。假如找到列索引,列称号(实践上是键)经由过程[out, retval]参数前往,也就是columnName。
(3) 数据排序
上面添加一个对数据有实践影响的办法。利用STL sort算法对行停止排序。
然后给I Ta b l e S t o r a g e增添一个新的办法S o r t,按图1 7 - 9对对话框停止填写:
由于CTableStorage数据布局是一种STL数据布局的组合(一种映照矢量),需求供应一种定制的对照函数停止排序。例如,CTableStorage::Sort答应行依据任何列排序,这类排序可以仅利用一个对照函数,或利用一个函数对象。用于排序的列被传递给函数对象doCOMpare的机关器。
在TableStorage.cpp文件某处增添以下函数对象,例如放在includes和TableStorage类的完成局部之间。
这是doCOMpare函数对象的声明和完成局部,在排序顶用于对照。的确,这个函数看起来能够庞杂一点,具体的语法注释可以查C++手册,不外它的目标却十分复杂。对照各行以便按m_direction参数指定的次第排序。以列号作为机关器中的第一个参数,并存储在一个成员变量(m_column)中。如许,当作对照时,函数对象就晓得对照的是哪一列。
注重doCOMpare是由STL binary_function模板衍生的。STL供应binary_function使得创立对照函数十分便利。
17.3.4 测试
这个组件可用于很多中央:好比VB法式中、ASP文件中乃至于C++法式中。上面剖析一下在ASP中的利用体例。
起首创立一个字符串CSVString,它代表数据。用Server.CreateObject创立一个TableStorage对象,用ParseCSV办法对字符串停止剖析。这时候数据在内存中。然后依据名字按升序排序。
注重, COMponentTest.ASP页面的全体代码可以从Worx网站高低载,本章及下一章的Visual C++项目ASPCOMponents是本书源代码的一局部。
别的,为了失掉一个字段的值,必需指定字段名。一个更天真的界面应答应利用索引来失掉字段的值。运转这个页面,阅读器中应当失掉如图1 7 - 1 0所示的显示。
17.3.5 毛病处置
毛病处置的两个次要方面是:
? 确保能捕获一切的毛病。
? 供应毛病情形的准确描写。
在法式开辟过程当中尽可能早地利用适合的毛病处置东西,能分明削减开辟和测试工夫,这是由于能更快地发明和改正毛病。可使用C++的异常处置来捕获毛病,利用Error对象向客户端反应信息。
1. 异常处置
毛病处置才能受法式言语限制。一个典范的毛病处置进程包括以下几个方面:
? 挪用一个函数。
? 反省前往值。
? 假如胜利,法式采取一个代码途径,假如掉败采取另外一个。
这个进程的成绩是招致代码嵌套,很难跟踪。别的,没有举措迫使法式员检测前往值。他们能够懒得反省前往值,或是忘了。
咱们更但愿编程情况能替咱们捕获毛病并引诱代码按事后肯定的毛病处置线路运转。在Visual Basic中可以用On Error Goto <毛病处置函数>做到这点。当毛病发生时,法式将跳到指定的毛病处置函数处。也能够在Visual Basic中挪用Err.Raise来标志一个毛病。
C++和Java具有不异的毛病处置概念,叫作异常处置。异常处置答应把代码的一局部放入try块来回护它。假如毛病发生于try块,那末法式的履行跳到catch块,在那儿有毛病处置代码。当毛病发生于catch法式块时,代码将主动指向try法式块。利用throw关头字收回毛病信息。
上面是异常处置的复杂例子:
在第1 8章中将利用这类异常处置作风。
一旦捕捉了毛病,下一步是将毛病信息前往给用户。假如所利用的COM对象的宿主情况是ASP,最好的办法是经由过程Error对象呈报毛病。
2. Error对象
假如未用On Error Resume Next,当对没有值的字段挪用GetField办法时,将碰到以下毛病:
这个提醒用途不大,在毛病发生时需求组件能供应更多的信息,可以经由过程Error对象来做到这一点。
假如创立一个新的ATL对象,并利用Error对象,可以选择ATL Object Wizard Properties对话框中的Support ISupportErrorInfo复选框,唆使导游发生撑持Error对象的代码。
经由过程这类修正,咱们的类将撑持ISupportErrorInfo COM 接口。但是,需求在源文件TableStorage.cpp拔出上面的代码,才可以完成增添的办法。
咱们的类从C COM CoClass派生,有一个Error办法。也就是说C TableStorage类可以利用C COM Co Class界说的一切公共办法和属性。如今C TableStorage类撑持毛病接口,因此可使用这个办法。C TableStorage类也供应Error对象的一切参数,包含毛病代码、描写和匡助信息。
如今不但失掉了增添的毛病信息,并且失掉了组件的ProgID。当组件撑持ISupportErrorInfo时,ProgID信息将主动地拔出。
别的,我死力保举法式员在组件开辟早期利用毛病撑持。这将有助于法式员调试组件,并可以匡助组件用户的开辟任务。固然,假如不克不及从毛病信息中判别出是甚么出了错,下一步就是调试法式了。
17.3.6 调试
在Visual C++中可以直接调试一个正常的可履行法式。可以设置断点,然后在调试形式下运转法式。假如有DLL,则需求做更多的任务: C++调试器必需附加上撑持调试的历程。
一个DLL不在本人的历程运转,它运转在其他历程中。因而,必需给调试器绑缚上能包容DLL的使用法式历程空间。假如在Visual Basic中测试,就需求绑缚上Visual Basic;假如是在ASP上测试,则需求绑缚上Web办事器历程。别的,在Visual Basic中,可以运转VB6.EXE,翻开一个利用DLL的项目,像正常情形一样设置断点。
还有一个直接设置组件停止调试的办法,只需在组件中需求调试的中央加高低面一行便可:
DebugBreak();
当包容DLL法式的历程运转到这一行时,将停上去弹出一个对话框并告知你已到了断点,并扣问是不是调试使用法式。按Cancel挪用调试器(注重,按OK不进入调试器)。假如组件调试版本而不是刊行版本,当按Cancel时,Visual C++将入手下手运转并停在拔出DebugBreak()的中央。在这可以设置别的的断点、察看变量和做其他的调试任务。
这类体例的次要成绩是其侵入性。为了调试代码必需修正代码,还得非常当心防止遗留DebugBreak()。假如组件产物中有DebugBreak(),运转时将弹出对话框并锁住每个用户使其离开Web办事器,守候用户按下OK或Cancel。这是很糟的。
假如组件在ASP中利用,修正然后从头编译就会呈现以下毛病:
LINK:fatal error LINK1168:connot Debug/aspComponent.dll for writing
Error Executing link.exe
办事器组件在Web办事器的历程空间中运转,假如失掉上述毛病,意味着办事器仍有此组件的援用。更切实地说,办事器正援用组件中的DLL,所以需求消除对DLL的援用。然而,做到这些需求封闭偏重新启动WWW办事。但是,假如对象是在MTS中运转,这个进程就复杂多了。
COM+调试
起首,肯定设定的激活属性(activation property)是公用的办事器历程而不是库历程。这才干确保调试器绑定到所要调试的组件的历程。在Project Settings选项卡上,将Executable fordebug session项设置为dllhost.exe,将Program arguments项设置为ProcessID: <历程的ID >,如图1 7 - 11所示。
历程的I D可以经由过程在Component Services Explorer中右键单击使用法式图标,并选择Properties来取得,如图1 7 - 1 2所示。
封闭组件地点的使用法式的办事器历程,确保组件以后不会驻留在内存中。不然,能够会利用没有绑定调试器的组件实例。确被创立组件的调试版本,在调试版本中设置所需断点并从Build菜单中履行法式。
运转带有法式参数的dllhost.exe,以唆使它载入包括被调试组件的使用法式。由于COM+历程绑定了调试器,不管甚么时分会见组件,调试器都能在断点处中止挪用。
假如对象掉败,有关C++中的组件的其他情形都主动地放在事务日记中。
本章引见了C++的发源和设置与开辟ASP组件相干的情况。读者已进修了一局部C++,如STL和ATL,这些都是创立ASP组件的有效东西。这些东西都能知足办事器组件的设计需求,其目标就是削减存储空间和会见工夫。为了引见它们的利用办法,本章创立了一个能用于任何使用法式的通用组件。
组件的可使用才能的一个主要方面是其毛病处置。C++异常处置供应了在组件中捕捉毛病的无效办法。要想在使用法式挪用以外呈报毛病,组件需求撑持ISupportErrorInfo。
楼上说交互性不好,太牵强了吧。在微软提供的一套框架中,利用asp做网站,开发效率高,使用人数少,减少不必要的开销。交互性是互动方式,是有开发人员决定的。 |
|