成长空间

MiLife

常用链接

统计

积分与排名

Automation Testing Development

最新评论

#

单点登陆 single sign-on

    只有注册用户登录后才能阅读该文。阅读全文

posted @ 2007-07-25 18:44 Picasso 阅读(66) | 评论 (0)编辑 收藏

ADO and ADO.net

ADO是什么,它是如何操作数据库的?

  答:ADO的全名是ActiveX Data Object(ActiveX数据对象),是一组优化的访问数据库的专用对象集,它为ASP提供了完整的站点数据库解决方案,它作用在服务器端,提供含有数据库信息的主页内容,通过执行SQL命令,让用户在浏览器画面中输入,更新和删除站点数据库的信息。

  ADO主要包括Connection,Recordset和Command三个对象, 它们的主要功能如下:

  ·Connection对象:负责打开或连接数据库文件;
  ·Recordset对象:存取数据库的内容;
  ·Command对象:对数据库下达行动查询指令,以及执行SQL Server的存储过程。

使用Recordset对象和Command对象来访问数据库的区别在哪里?

  答:Recordset对象会要求数据库传送所有的数据,那么数据量很大的时候就会造成网络的阻塞和数据库服务器的负荷过重,因此整体的执行效率会降低。
利用Command对象直接调用SQL语句,所执行的操作是在数据库服务器中进行的,显然会有很高的执行效率。特别是在服务器端执行创建完成的存储过程,可以降低网络流量,另外,由于事先进行了语法分析,可以提高整体的执行效率。


什么是ADO.NET架构

如今大部分的应用程序都需要后台的数据库来为其提供大量的数据来源,而应用程序与数据库之间的交流称为数据访问。而ASP.NET则使用ADO.NETActive X Data Object)作为数据的访问与操作的协议,从而使得我们可以在Internet上操作这些数据。

ADO.NET的数据访问分为两大部分:数据集(DataSet)与数据提供源(Data Provider,我并不清楚中文该怎么翻译,就叫它数据提供源好了,不要和“数据源”—Data Source搞混)

 

数据集:

数据集是一个非在线,完全由内存表示的一系列数据,可以被看作一份本地磁盘数据库中部分数据的拷贝。数据集完全驻留内存,可以被独立于数据库地访问或者修改。当数据集的修改完成后,更改可以被再次写入数据库,从而保留我们所做过的更改。数据集中的数据可以由任何数据源(Data Source)提供,比如SQL Server或者Oracle

 

数据提供源:

数据提供源用于提供并维护应用程序与数据库之间的连接。

数据提供源是一系列为了提供更有效率的访问而协同工作的组件。如今微软在ADO.NET中提供了两组数据提供源,一组叫做SQL Data ProviderSQL数据提供源),用于提供应用程序与SQL Server 7.0或者更高版本的访问。另一组叫做OleDb DataProviderObject Linking and Embedding DataBase DataProvider),可以允许我们访问例如Oracle 之类的第三方数据源。

每组数据提供源中都包含了如下四个对象:

Connect对象提供了对数据库的连接。

Command对象可以用来执行命令。

DataReader对象提供了只读的数据记录集。

DataAdapter对象提供了对数据集更新或者修改的操作。

 

总体来说,使用ADO.NET访问数据可以被概括为以下步骤:

首先应用程序创建一个Connect对象用来建立与数据库之间的连接。然后Command对象提供了执行命令的接口,可以对数据库执行相应的命令。当命令执行后数据库返回了大于零个数据时,DataReader会被返回从而提供对返回的结果集的数据访问。或者,DataAdapter可以被用来填充数据集,然后数据库可以由Command对象或者DataAdapter对象进行相应的更改。

具体来看数据提供源的四种对象

 

Connect 对象

Connect对象用来提供对数据库的连接,Microsoft Visual Studio .Net中微软提供了两种Connect对象,分别为SqlConnection对象,用来提供对SQL Server 7.0或更高版本的连接,同时还有OleDbConnection对象,用来提供对Access与其他第三方数据库的连接。

 

Command 对象

同样,Command对象分为两组,SqlCommandOleDbCommandCommand对象被用来执行针对数据库的命令,比如执行数据库的存储过程(Stored Procedure)SQL命令,或者直接返回一个完整的表。Command对象提供三种方法(Methods)用来执行上述操作。

ExecuteNonQuery用来执行一个不需返回数据的命令,比如表的插入,更新或者删除操作。

ExecuteScalar返回从一个查询得到的单独的值。

ExecuteReader用来返回一个从DataReader来的结果集。

 

DataReader对象

DataReader提供了forward-only, read-only, connected stream的结果集。

这里的forward-only表示数据只能够向前,如果我们访问了一条数据后想要再次访问这条数据就必须重新开始。

Read-only表示只读,不能够对结果集进行操作。

Connected stream表示DataReader对象是面向流连接的。所谓的流可以把它看作是管道,这边放进去东西那边就可以得到,实际上TCP协议就是面向连接的流协议。

不同于其他的三种对象,DataReader不能够被用户直接创建,必须也只能由ExecuteReader返回。

SqlCommand.ExecuteReader返回SqlDataReader

同理,OleDbCommand.ExecuteReader返回OleDbDataReader

需要注意的是,DataReader对应用程序提供行级访问(每次只能访问数据的一行),当你需要多行的时候就需要多次的访问这个对象。这样做的好处就是内存中永远只需要保留一行的数据,缺点就是每次访问都要开启Connect的连接。

 

DataAdapter对象

DataAdapter对象是ADO.NET数据访问的核心。实际上它是数据集与数据库的中间层。DataAdapter可以使用Fill方法来为DataTable或者DataSet填充数据。然后当内存操作完成后DataAdapter可以确认之前的操作从而对真正存于数据库上的数据进行修改。

DataAdapter包含四种属性用来代表不同的数据库命令:

SelectCommand用来查询数据

InsertCommand用来插入数据

DeleteCommand用来删除数据

UpdateCommand用来更新数据Update方法被调用后,数据集中的数据被更改然后拷贝回数据库,紧接着使用InsertCommand, DeleteCommand, UpdateCommand中合适一个来进行数据更新。

posted @ 2007-07-25 16:46 Picasso 阅读(263) | 评论 (0)编辑 收藏

DOM简介

http://book.csdn.net/bookfiles/110/1001107072.shtml

DOM教程(什么是DOM)
                        作为结构的 DOM
      DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中导航仪寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的。
      对于特别大的文档,解析和加载整个文档可能很慢且很耗资源,因此使用其他手段来处理这样的数据会更好。这些基于事件的模型,比如 Simple API for XML(SAX),适用于处理数据流,即随着数据的流动而依次处理数据。基于事件的 API 消除了在内存中构造树的需要,但是却不允许开发人员实际更改原始文档中的数据。
     另一方面,DOM 还提供了一个 API,允许开发人员添加、编辑、移动或删除树中任意位置的节点,从而创建一个引用程序。
     解析器是一个软件应用程序,设计用于分析文档(这里是指 XML 文件),以及做一些特定于该信息的事情。在诸如 SAX 这样基于事件的 API 中,解析器将向某种监听器发送事件。在诸如 DOM 这样基于树的 API 中,解析器将在内存中构造一颗数据树。
作为 API 的 DOM
     从 DOM Level 1 开始,DOM API 包含了一些接口,用于表示可从 XML 文档中找到的所有不同类型的信息。它还包含使用这些对象所必需的方法和属性。
Level 1 包括对 XML 1.0 和 HTML 的支持,每个 HTML 元素被表示为一个接口。它包括用于添加、编辑、移动和读取节点中包含的信息的方法,等等。然而,它没有包括对 XML 名称空间(XML Namespace)的支持,XML 名称空间提供分割文档中的信息的能力。
     DOM Level 2 添加了名称空间支持。Level 2 扩展了 Level 1,允许开发人员检测和使用可能适用于某个节点的名称空间信息。Level 2 还增加了几个新的模块,以支持级联样式表、事件和增强的树操作。
     当前正处于定稿阶段的 DOM Level 3 包括对创建 Document 对象(以前的版本将这个任务留给实现,使得创建通用应用程序很困难)的更好支持、增强的名称空间支持,以及用来处理文档加载和保存、验证以及 XPath 的新模块;XPath 是在 XSL 转换(XSL Transformation)以及其他 XML 技术中用来选择节点的手段。
     DOM 的模块化意味着作为开发人员,您必须知道自己希望使用的特性是否受正在使用的 DOM 实现所支持。
                                        确定特性可用性
     DOM 推荐标准的模块性质允许实现者挑选将要包括到产品中的部分,因而在使用某个特定的特性之前,首先确定该特性是否可用可能是必要的。本教程仅使用 DOM Level 2 Core API,不过在着手您自己的项目时,了解如何能够检测特性是有所帮助的。
     DOM 中定义的接口之一就是 DOMImplementation。通过使用 hasFeature() 方法,您可以确定某个特定的特性是否受支持。DOM Level 2 中不存在创建DOMImplementation 的标准方法,不过下面的代码将展示如何使用 hasFeature() 来确定 DOM Level 2 样式表模块在某个 Java 应用程序中是否受支持。
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.DOMImplementation;
public class ShowDomImpl {
   public static void main (String args[]) {
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder docb = dbf.newDocumentBuilder();
         DOMImplementation domImpl = docb.getDOMImplementation();
         if (domImpl.hasFeature("StyleSheets", "2.0")) {
            System.out.println("Style Sheets are supported.");
         } else {
            System.out.println("Style Sheets are not supported.");
         }
      } catch (Exception e) {}      
 }
}
(DOM Level 3 将包括用于创建 DOMImplementation 的标准方法。)
     本教程将使用单个文档来展示 DOM Level 2 Core API 的对象和方法。
                                        基本的 XML 文件
     本教程中的所有例子都是用了一个包含如下节点的 XML 文件,它表示输入某个商业系统的订单。回顾一下,XML 文件的基本组成部分包括:
     XML 声明:基本的声明 <?xml version"1.0"?> 将这个文件定义为 XML 文档。在声明中指定一种字符编码的情况并不鲜见,如下所示。通过这种方式,不管该 XML 文件使用的语言或字符编码是什么,只要解析器理解特定的编码,它就能够正确地读取该 XML 文件。 
     DOCTYPE 声明:XML 是人机之间交换信息的便利手段,但是要使它能够顺利地工作,必须要有一个公共的词汇表。可选的 DOCTYPE 声明可用于指定一个应该用来与此文件做比较的文档(在本例中为 orders.dtd),以确保不会产生任何混淆或丢失信息(例如,丢失一个 userid 或错误拼写某个元素名称)。以这种方式处理过的文档称为有效的文档。成功的有效性检查并不是 XML 所必需的,后面的例子实际上从文档中省略了 DOCTYPE 声明。 
     数据本身:XML 文档中的数据必须包含在单个根元素内,比如下面的 orders 元素。要使 XML 文档得到处理,它必须是格式良好的(well-formed)。 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ORDERS SYSTEM "orders.dtd">
<orders>
   <order>
      <customerid limit="1000">12341</customerid>
      <status>pending</status>
      <item instock="Y" itemid="SA15">
         <name>Silver Show Saddle, 16 inch</name>
         <price>825.00</price>
         <qty>1</qty>
      </item>
      <item instock="N" itemid="C49">
         <name>Premium Cinch</name>
         <price>49.00</price>
         <qty>1</qty>
      </item>
   </order>
   <order>
      <customerid limit="150">251222</customerid>
      <status>pending</status>
      <item instock="Y" itemid="WB78">
         <name>Winter Blanket (78 inch)</name>
         <price>20</price>
         <qty>10</qty>
      </item>
   </order>
</orders>
    在 DOM 中,使用 XML 信息意味着首先将它划分为节点。

posted @ 2007-07-25 16:34 Picasso 阅读(255) | 评论 (0)编辑 收藏

COM与.NET的交互

 
 Advanced COM Interop


.NET framework 是从COM的一种自然地进步,因为这两个模型共享了许多中心的主题,包括组件重用和语言中立。为了支持向后兼容,COM interop提供了不需要修改现有组件而能访问现有COM组件的方法。可以通过使用COM interop工具导入相关的COM类型来合并COM组件到.NET Framework的应用中。一旦导入,COM的类型就可以使用了。

COM interop 同时也提供了向前兼容使得COM的客户可以像访问其他的COM对象一样访问托管的代码,COM interop又一次的提供了所谓的无缝从程序集中导出元数据(metadata)到类型库并且像传统COM组件一样注册托管组件的方法。无论是导出还是导入工具处理的结果都与COM规范一致。在运行时,如果需要的话common language runtime在COM对象和托管代码之间列集(marshals)数据


1. COM Wrappers
COM在以下几个方面与.NET Framework的对象模型有所不同:
• COM对象的客户程序必须管理这些对象的生命期;在.NET Framework 中CLR管理这些对象的生命期
• COM的客户通过请求一个接口并得到接口的指针来查询一个服务是否有效,.NET的客户可以通过反射(reflection)来得到一个对象的功能的描述
• .NET的对象驻留在.NET Framework执行环境管理的内存中,执行环境可以因为性能的原因删除内存中的对象并且更新它删除的对象的所有引用。非托管的客户,得到一个对象的指针,依赖于对象保留在相同的位置。这种客户没有那种处理在内存中不在固定位置的对象的机制。


为了克服这些不同,runtime提供了包装类使得托管代码和非托管代码的客户都认为他们在自己的环境中调用对象的方法。当托管客户调用一个COM对象的方法时,runtime创建一个runtime callable wrapper (RCW)。RCWs抽象了托管代码和非托管代码引用机制的不同。Runtime还创建了一个COM callable wrapper (CCW)来实现其逆过程,使得COM的客户能够无缝的调用.NET对象的方法。如下图所示


COM wrapper overview



在大多数情况下,标准的RCW或者CCW由runtime生成,为跨越COM和.NET Framework的边界调用提供了足够的列集。使用自定义的属性,可以随意的调整runtime表示托管代码和非托管代码的方式

Runtime Callable Wrapper


CLR(common language runtime)通过一个叫做runtime callable wrapper (RCW)的代理(proxy)暴露COM 对象. 虽然RCW对于.NET的客户似乎是一个普通的.NET对象,但是它的主要功能却是在.NET客户和COM对象之间列集调用。


运行时正确的为每个COM对象创建一个RCW,而不管那个对象上存在的引用的个数。如下图所示:任意数量的托管客户可以保持一个暴露INew 和INewer 接口的COM对象的引用。运行时为每个COM对象维护一个单独的RCW。


Accessing COM objects through the runtime callable wrapper



使用来源于类型库(type library)的元数据(metadata),运行库(runtime)创建将被调用COM对象和这个对象的包装(wrapper)。每个RCW维护它所包装的COM对象的接口指针并且在RCW不再需要时释放COM对象。运行库(runtime)在RCW之上作垃圾收集。


在其他的活动中,RCW代表所包装的对象在托管和非托管代码之间列集(marshals)数据。特别的是,RCW在客户和服务有不同的数据表现形式,并需要在他们之间传递数据时,提供方法参数和方法返回值得列集。


标准的wrapper执行内置(built-in)的列集规则。例如:当.NET的客户传递一个String类型作为参数的一部分给托管对象的时候,wrapper把string类型那个转化为BSTR类型。当COM对象返回一个BSTR给托管的调用着的时候,调用着收到一个string。无论是客户还是服务端接受和发送数据都使用自己熟悉的类型。还有一些其他的类型不需要变化,例如:一个标准的wrapper将在托管和非托管代码之间一直传递4-byte integer而不做任何变化。


RCW的主要目标就是隐藏托管代码模型和非托管代码模型之间的差别,实现无缝的传输。RCW使用选择的接口而不把它们暴露给.NET的客户端,如下图所示


COM interfaces and the runtime callable wrapper



当创建一个早期的COM对象的时候,RCW是一个特殊的类型。它实现了COM对象实现的一些接口并且暴露它们的方法,属性和时间。如图所示:RCW暴露了INew接口,但是使用了IUnknown 和IDispatch接口。RCW向.NET客户暴露了INew的所有成员


COM Callable Wrapper


当COM的客户调用.NET的对象时,CLR创建这个托管的对象和这个托管的对象COM callable wrapper(CCW),COM客户可以使用CCW作为托管对象的一个代理,而不能够直接使用.NET的对象。

 
Runtime正确的创建托管对象的CCW,不管要求这个服务的COM客户的数量。如下图所示,多个COM客户可以保持包含INew 接口的CCW的引用,CCW,反过来包含一个实现了接口和垃圾收集的托管对象的单独的引用。COM和.NET的客户可以同时在相同的托管对象是发起调用。


Accessing .NET objects through COM callable wrapper


COM callable wrappers对于运行在.NET Framework上的其他类是不可见的。它们的主要目的是在托管和非托管代码之间列集(marshal)调用,而且CCWs同时也管理着它所包含对象的identity和对象的生存期(lifetime)


Object Identity
运行时(runtime)在它的能够垃圾回收的堆里(garbage-collected heap)为.NET对象分配内存,这能使runtime需要的时候在内存中移动对象。相反,runtime在不能进行垃圾收集的堆上为CCW分配内存,使COM客户能够直接引用它。


Object Lifetime
与它所包含的.NET 对象不同,CCW是一个基于引用计数的传统的COM。当CCW的引用计数减少到0,wrapper释放自己在托管对象上的引用。没有引用的托管的对象在下一次垃圾收集的周期内将被收集。


Customizing Standard Wrappers
这部分将描述如何自定义标准的runtime callable wrappers(RCW) and COM callable wrappers.(CCW)


Runtime Callable Wrappers
当.NET激活一个COM对象时,运行时(runtime)生成一个包含COM类型的runtime callable wrapper (RCW),如下图所示, 运行时(runtime)使用从导入的类型库而得到的元数据(metadata)来生成RCW。Wrapper根据interop marshaling service定义的规则列集数据。


RCW generation and method calls




有两个方式可以自定义RCW。如果你可以修改Interface Definition Language (IDL)的源文件,你可以给type library file (TLB) 添加属性然后导入TLB。还可以应用interop-specific attributes来导入类型生成新的程序集(assembly)支持自定义的标准RCWs被这些attributes限制


To modify the IDL source

1. Apply TLB attributes to libraries, types, members, and parameters. Use the custom keyword and an attribute value to change metadata. By applying TLB attributes, you can:
• Specify the managed name of an imported COM type, instead of allowing the import utility to select the name according to standard conversion rules.
• Explicitly define a destination namespace for the types in a COM library.
2. Compile the IDL source code.
3. Generate an assembly from the resulting type library file or from a dynamic link library file (DLL) that contains the type you intend to implement.


To modify an imported assembly
1. Import the type library file. Use the Type Library Importer (Tlbimp.exe) to generate an assembly DLL.
2. Create a text file from the imported assembly by using the MSIL Disassembler (Ildasm.exe).
3. Apply interop attributes to the text file.
4. Generate a new assembly from the modified text file by using the MSIL Assembler (Ilasm.exe).


 COM Callable Wrappers
COM callable wrapper (CCW) 向COM导出NET Framework对象. 通过把一个托管的工程编译成一个DLL的程序集, 可以自动的创建需要的元数据来描述程序集中的类型. 当一个COM的客户激活托管对象时,运行时使用元数据来生成CCW.
自定义CCW,你的托管的代码要遵循交互规范属性(interop-specific attributes),并且把编译代码编译成程序集,如下图所示,在这个例子中,Tlbexp.exe把托管类型编译为COM


CCW 的生成和方法调用



通过在代码中添加属性,可以在交互列集服务限定的范围内改变接口和数据的列集行为。例如,可以你可以控制方法参数传递的格式,也可以控制程序集中的什么类型暴露给COM


2 .托管和非托管的线程(Managed and Unmanaged Threading)


COM组件使用套间(apartments)来同步资源的访问。与之对应的是,托管对象使用同步区域(synchronized regions),同步原语例如互斥量(mutexes)锁定和完成异步端口,同步上下文来保证所有的共享资源以线程安全的方式被使用。


对于可交互性来说,CLR(common language runtime)在调用COM对象时,创建并初始化一个套间,一个托管的线程可以创建并且进入一个包含一个线程的single-threaded apartment (STA)或者包含多个线程的multi-threaded apartment (MTA)。当COM的套间和线程的套间兼容的时候,COM允许调用的线程直接调用COM对象的方法,如果套间不兼容,COM创建兼容的套间并通过代理列集(marshals)所有的调用。

 
在第一个对非托管代码的调用时,运行时调用CoInitializeEx来初始化MTA或者STA的COM套间。可以使用System.Threading.ApartmentState属性来控制创建的套间的类型是MTA, STA, 或者Unknown.在代理存根或者TLB已经注册后,不一定义定设定要设定这个属性。
下表列出了ApartmentState的枚举值和对应的COM套间初始化调用

ApartmentState enumeration value
COM apartment initialization
MTA
CoInitializeEx(NULL, COINIT_MULTITHREADED)
STA
CoIntializeEx(NULL, COINIT_APARTMENTTHREADED)
Unknown
CoInitializeEx(NULL, COINIT_MULTITHREADED)

COM对象和托管线程在不兼容的套间时,所有的调用都通过COM创建的代理,下面的代码例子显示了怎么在托管代码重创建一个STA套间模型的COM对象AptSimple


[C#]
using System.Threading;
using APTOBJLib;
...
AptSimple obj = new AptSimple ();
obj.Counter = 1;
为了消除代理存根,显著的提高性能,注意创建对象之前的ApartmentState
[C#]
using System.Threading;
using APTOBJLib;
...
Thread.CurrentThread.ApartmentState = ApartmentState.STA;
AptSimple obj = new AptSimple ();
obj.Counter = 1;
设定套间状态之后,可以向下面那样通过程序查询状态
[C#]
Thread.CurrentThread.ApartmentState = ApartmentState.STA;
if (Thread.CurrentThread.ApartmentState == ApartmentState.STA) {
// All is OK.
}
else {
// Incompatible apartment state.
}

3 托管和非托管的事件(Managed and Unmanaged Events)

.NET Framework的事件模型与传统的COM的事件模型不同。托管的事件模型基于委托(delegate),er非托管的事件(在COM中)基于连接点(connection points)。两个模型都是紧耦合的事件系统,因为客户(事件接受者)和服务(事件发送者)必须同时的运行。

这一部分描述了怎样过渡托管和非托管的事件系统,使得对象可以跨域交互边界发送和接收事件。

COM 事件
这部分提供关于连接点的概要介绍以及用来说明COM事件相关的通用术语
连接点在客户和COM的服务器之间确立了一种双向de通信机制。通过这种机制,COM服务器在事件发生时可以回调客户。例如,服务器(像Microsoft Internet Explorer)可以发出一个事件来向客户程序报告一个变化(例如标题变化)。客户创建了一个叫做event sink内部的COM对象来响应通知,当收到通知,客户可以执行事件相关的操作。


event sink提供了向服务器暴露事件相关方法的接口。服务器通过这些事件相关的方法激发事件。客户像实现普通的COM接口一样实现event sink接口。服务器声明这个接口为出接口,COM服务的作者在类型库中队这个接口应用source 属性。服务器使用event sink接口的定义来确定sink并且invoke方法


实现了event sink接口的COM客户通常叫做event sink,或者简单的称为sink。
在下图中,sink实现了ISinkEvents接口,服务器可以激发事件
连接点事件模型(Connection point event model)



event sink的接口确定之后,sink必须与源对象建立连接,连接点的机制使用下面的过程连接sink和source:
1. The sink queries a server object for the IConnectionPointContainer interface. If the object supports connection points, it returns a pointer.
2. Using methods on the container object, the sink locates the IConnectionPoint interface representing a specific connection point. Since a server can support multiple outgoing interfaces, a client must match its sink to the interface identifier (IID) of a particular connection point interface.
3. Having obtained the correct connection point object, the sink calls IConnectionPoint::Advise to register its sink interface pointer. The server (source) holds the connection (and raises events to it) until the client breaks the connection by calling IConnectionPoint::Unadvise.


处理COM源发出的事件(Handling Events Raised by a COM Source)
如果你不熟悉.NET Framework提供的基于委托(delegate-based)的事件模型,参考Handling and Raising Events。

An imported delegate signature comprises the sink event interface, an underscore, the event name, and the word EventHandler: SinkEventInterface_EventNameEventHandler.
.NET的客户(event sink)可以接受现存的COM服务器(event source)的事件。COM interop在你的托管客户的元数据中产生必要的委托。一个导入的委托签名(signature)由sink event接口,一个下划线,事件名称和EventHandler组成


与现存的COM事件源交互(To interoperate with an existing COM event source)
1. Obtain the primary interop assembly for the COM server if the COM types are to be shared by other applications. A primary interop assembly contains metadata representing the converted type library and is signed by the publisher.
Note If the primary interop assembly is not available or if the assembly is to be used privately, you can import the type library by using Tlbimp.exe or an equivalent API.
The conversion process generates a delegate for each event; however, you only have to sink the events that interest you.
2. You can use a metadata browser, such as Ildasm.exe, to identify events delegates.
3. Consume events from the COM event source the same way you consume events from a managed event source.
下面的例子说明了怎样打开一个Internet Explorer窗口,得到Internet Explorer对象发出的事件并在托管的代码中处理。Internet Explorer的类型(包括事件委托)的定义从被SHDocVw.dll导入为元数据,例子激发TitleChange事件
 

[C#]
namespace InternetExplorer
{
    using System;
    using System.Runtime.InteropServices;
    using SHDocVw;
 
    public class Explorer
    {
        public static void Main()
        {
            Explorer explorer = new Explorer();
            explorer.Run();
        }
        public void Run()
        {
            Object o = null;
            String s;
 
            try
            {
                // Starts the browser.
                m_IExplorer = new SHDocVw.InternetExplorer();
            }
            catch(Exception e)
            {
                Console.WriteLine("Exception when creating Internet
                Explorer object {0}", e);
                return;
            }
 
            // Wires your event handlers to m_IExplorer.
            SetAllEvents();
 
            try
            { 
                // Goes to the home page.
                m_WebBrowser = (IWebBrowserApp) m_IExplorer;
                m_WebBrowser.Visible = true;
                m_WebBrowser.GoHome();
 
                // Starts navigating to different URLs.
                Console.Write("Enter URL (or enter to quit): ");
                s = Console.ReadLine();
                while (s != "" && m_IExplorer != null &&
                    m_WebBrowser != null)
                {
                    m_WebBrowser.Navigate(s, ref o, ref o, ref o,
                          ref o);
                    Console.Write("Enter URL (or enter to quit): ");     
                    s = Console.ReadLine();
                }
 
                m_WebBrowser.Quit();
            }
            catch(Exception sE)
            {
                if (m_IExplorer == null && m_WebBrowser == null)
                {
                    Console.WriteLine("Internet Explorer has gone away");
                }
                else
                {
                    Console.WriteLine("Exception happens {0}", sE);
                }
            }
        }
        // Uses the += syntax for adding delegates to events.
        void SetAllEvents()
        {
            if (m_IExplorer != null)
            {
                // Title Change event
                // DWebBrowserEvents2 is the name of the sink event
                //interface.
                // TitleChange is the name of the event.
                // DWebBrowserEvents2_TitleChangeEventHandler is the
                // delegate name assigned by TlbImp.exe.
                DWebBrowserEvents2_TitleChangeEventHandler
     DTitleChangeE = new DWebBrowserEvents2_TitleChangeEventHandler(OnTitleChange);
              m_IExplorer.TitleChange += DTitleChangeE;
            }
        }
///////////////////////////////////////////////////////////////////////
        // Define event handlers.
        // Document title changed
        static void OnTitleChange(String Text)
        {
            Console.WriteLine("Title changes to {0}", Text);
        }
  
//////////////////////////////////////////////////////////////////////////
        // The following are class fields.
        static private SHDocVw.InternetExplorer m_IExplorer = null;
        static private IWebBrowserApp m_WebBrowser = null;
    }
}

posted @ 2007-07-25 11:19 Picasso 阅读(2454) | 评论 (0)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4