首页> 中国专利> 利用属性来标识和过滤可插入功能

利用属性来标识和过滤可插入功能

摘要

在用于大规模可扩展应用程序的合成模型中,应用程序是以模块化的方式构造的。各模块通过生产和消费符合一公共定义的功能来相互整合。生产者模块和消费者模块保持相互独立,并且通过一定义模块间接地链接在一起。使用.NET属性来将各种代码人工产物(如类、方法、特性等)标识为功能定义、生产和/或消费。这些属性由模块加载器检验,并且被用于创建单独安装的生产者和消费者模块之间的关系。消费者使用.NET属性来声明对功能的依赖性,并且过滤掉不满足那些属性指定的准则的实现。

著录项

  • 公开/公告号CN101263486A

    专利类型发明专利

  • 公开/公告日2008-09-10

    原文格式PDF

  • 申请/专利权人 微软公司;

    申请/专利号CN200680033359.2

  • 发明设计人 R·S·金伯利;

    申请日2006-08-29

  • 分类号G06F17/00(20060101);G06F15/16(20060101);

  • 代理机构31100 上海专利商标事务所有限公司;

  • 代理人陈斌

  • 地址 美国华盛顿州

  • 入库时间 2023-12-17 20:45:19

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2015-05-20

    专利权的转移 IPC(主分类):G06F17/00 变更前: 变更后: 登记生效日:20150428 申请日:20060829

    专利申请权、专利权的转移

  • 2011-06-08

    授权

    授权

  • 2008-10-29

    实质审查的生效

    实质审查的生效

  • 2008-09-10

    公开

    公开

说明书

版权声明和许可

本专利文献的一部分公开内容可能包含受版权保护的材料。版权所有 人不反对任何人对本专利文献或专利公开内容按照其在(美国)专利和商标 局的专利文献或记录中的形式进行复制,但版权所有人保留其它所有的权 利。以下声明应当应用于本文:Copyright2005,微软公司。

背景

诸如Microsoft.NET(.NET)等连接信息、人、系统和设备的软件提供了 基于可扩展标记语言(XML)的互操作性,并且目前正被结合到客户机、 服务器、服务和工具中。例如,像Microsoft和Microsoft这样的产品将使用.NET来与其他系统和应用程序连接。对于软件开发者而 言,.NET被体现在.NET框架中传送的编程模型中。该框架是 允许构建和运行下一代软件应用程序和万维网(Web)服务的整合的 Microsoft组件。它包括用于Web服务和Web应用程序、数据存 取、智能客户机应用程序和许多其他的技术。

Web服务是在因特网上通过行业标准协议来调用的,这些协议包括简 单对象访问协议(SOAP)、XML、以及通用描述、发现和集成(UDDI)。 它们都是通过诸如万维网联盟(W3C)等公共标准组织来定义的。SOAP 是一种由W3C标准化的基于XML的消息通信技术,它指定了用于定位 Web服务、将其集成到应用程序中、以及在它们之间通信的所有必需的规 则。UDDI是一个免费提供的公共注册中心(public registry),人们可以在 这里发布和查询Web服务。.Net包括对自描述软件模块的使用,这些软件 模块在语义上封装离散功能,并被包装在如XML和SOAP这样的标准的因 特网通信协议中且可通过该协议来访问。

即使模块被载入相同的应用程序进程,并以强类型化的方式来交互, 构建可扩展客户机应用程序程序仍需要相似的模块性,以及在构建时不知 道其起源的情况下检测和利用功能的能力。例如,一开发环境可能有一整 合点,在该点上,对源代码操作的工具(如编译器、浏览器、格式化器/美 化器等)可以被整合到该环境中。这些工具可以由第三方来创作,因此该 环境本身在不知道这些工具来自哪个模块的情况下是不能构建的。所以, 该环境必须公开它用来与这些工具交互的契约(包括它们需要的输入的格 式和它们产生的输出等),然后发现并加载符合该契约的已安装模块。

.NET平台肯定具有动态地将模块载入当前进程并利用模块中的功能 的能力,但其目前没有提供用于宣告整合点或识别对一应用程序中的那些 整合点的有效贡献的框架。

所以,需要的是解决现有技术的缺陷的方法和系统。

概述

提供本概述以便用简化的形式来介绍将在下面的详细描述部分中进一 步描述的一些概念。本概述并不旨在确定所要求保护主题的关键特征或必 要特征,也不旨在用于确定所要求保护的主题的范围。

考虑到上述现有技术的缺陷,提供了使用属性来标识和过滤可插入功 能的方法。对几个实施来说,一种用于使用属性来标识和过滤可插入功能 的系统包括一软件消费者模块、一软件生产者模块和一定义模块,其中, 该生产者和消费者模块通过该定义模块间接地相互链接。使用属性来宣告 安装在软件应用程序配置中的整合点和符合该整合点的代码主体或模块。 具体地,还提供了一种加载器模块,它被配置成在生产者模块和消费者模 块之间建立链接、发现包含功能定义的模块、发现生产符合那些功能定义 的功能的模块、发现消费上述功能的模块、以及加载所发现的模块。

以下描述了本发明的其他优点和特征。

附图简述

结合附图进一步描述使用属性来标识和过滤可插入功能。

图1是表示适于结合使用属性来标识和过滤可插入功能来使用的示例 性计算设备的框图;以及

图2是示出在使用属性来标识和过滤可插入功能时,软件模块如何通 过生产和消费符合一公共定义的功能来相互整合的框图;

图3是示出根据软件模块的生产/消费的实现的第一示例中的执行流程 的图,其中该软件模块通过生产和消费符合一公共定义的功能来相互整合;

图4是示出了根据软件模块的生产/消费的实现的第二示例中的执行流 程的图,其中该软件模块通过生产和消费符合一公共定义的功能来相互整 合;

图5是示出根据软件模块的期望功能的生产者和消费者之间的间接水 平的图,其中该软件模块通过生产和消费符合一公共定义的功能来相互整 合;以及

图6是示出根据软件模块的从消费者到单个生产者的示例情形中的执 行流程的图,其中该软件模块通过生产和消费符合一公共定义的功能来相 互整合。

详细描述

以下描述和附图阐明了一些具体细节以便提供对本发明各实施例的全 面理解。为了避免不必要地淡化本发明的各实施例,通常与计算和软件技 术相关联的某些公知细节在以下公开中没有阐明。此外,本领域的普通技 术人员将理解,其可在没有以下所述的一个或多个细节的情况下实施本发 明的其他实施例。最后,虽然参考以下公开中的步骤和序列来描述各种方 法,但这种描述只是为了提供本发明的实施例的清楚实现,并且这些步骤 和序列不应被认为是实施本发明所必需的。

参考图1,该图示出了适用于实现上述过程的示例性计算设备的框图。 例如,执行使用属性来标识和过滤可插入功能的过程和方法的计算机可执 行指令可以驻留在图1所示的这一计算机环境中,和/或可以在该计算环境 中执行。计算系统环境220只是合适的计算环境的一个例子,并且不旨在 对本发明的使用范围或功能提出任何限制。计算系统环境220也不应被解 释为对在示例性操作环境220中示出的任何一个组件或它们的组合有任何 依赖性或要求。例如,计算机游戏控制台也可以包括诸如以下描述的用于 实现上述过程的那些项。

本发明的各方面可在许多其它通用或者专用计算系统环境或者配置中 操作。可以适用于本发明的众所周知的计算系统、环境、和/或配置的示例 包括但不局限于,个人计算机、服务器计算机、手持式或膝上型设备、多 处理器系统、基于微处理器的系统、机顶盒、可编程消费电子产品、网络 PC、微型计算机、大型计算机、以及包括以上系统或设备中的任一个的分 布式计算环境等等。

本发明可以在诸如程序模块等由计算机执行的计算机可执行指令的一 般上下文中描述。一般而言,程序模块包括执行特定任务或者实现特定抽 象数据类型的例程、程序、对象、组件、数据结构等。本发明还可以在分 布式计算环境中实施,其中任务由通过通信网络链接的远程处理设备来执 行。在分布式计算环境中,程序模块可以位于包括存储器设备的本地和远 程计算机存储介质中。

用于实现本发明各方面的一个示例性系统包括计算机241形式的通用 计算设备。计算机241的组件可包括但不局限于,处理单元259、系统存储 器222、以及将包括系统存储器在内的各个系统组件耦合到处理单元259 的系统总线221。系统总线221可以是几种类型的总线结构中的任何一种, 包括存储器总线或存储控制器、外围总线、以及使用各种总线体系结构中 的任何一种的局部总线。作为例子而非限制,这样的体系结构包括工业标 准结构(ISA)总线、微通道体系结构(MCA)总线、增强型ISA(EISA) 总线、视频电子技术标准协会(VESA)局部总线、也被称为夹层(Mezzanine) 总线的外围部件互连(PCI)总线。

计算机241一般包括各种计算机可读介质。计算机可读介质可以是能 由计算机241访问的任何可用介质,并且包括易失性和非易失性介质、可 移动和不可移动介质。作为例子而非限制,计算机可读介质可以包括计算 机存储介质和通信介质。计算机存储介质包括以任何方法或技术实现的用 于存储如计算机可读指令、数据结构、程序模块或其他数据这样的信息的 易失性和非易失性、可移动和不可移动介质。计算机存储介质包括但不局 限于,RAM、ROM、EEPROM、闪存或者其它存储器技术、CD-ROM、数 字多功能盘(DVD)或者其它光盘存储、磁带盒、磁带、磁盘存储或者其 它磁存储设备、或者能够被用来存储所需信息并且能够由计算机241访问 的任何其他介质。通信介质通常以诸如载波或者其它传输机制等已调制数 据信号来体现计算机可读指令、数据结构、程序模块、或者其它数据,并 且包括任何信息传递介质。术语“已调制数据信号”是指以在该信号中编 码信息的方式来设置或改变其一个或多个特性的信号。作为例子而非限制, 通信介质包括有线介质,诸如有线网络或者直接线连接,以及无线介质, 诸如声学、射频、红外以及其它无线介质。上述任何组合也应当被包括在 计算机可读介质的范围之内。

系统存储器222包括易失性和/或非易失性存储器,诸如只读存储器 (ROM)223和随机存取存储器(RAM)260形式的计算机存储介质。基 本输入/输出系统(BIOS)224一般被存储在ROM 223中,BIOS包含有助 于例如在启动过程中在计算机241内的元件之间传输信息的基本例程。 RAM 260一般包括可由处理单元120立即访问和/或当前正由处理单元259 操作的数据和/或程序模块。作为例子而非限制,图1示出了操作系统225、 应用程序226、其他程序模块227和程序数据228。

计算机241还包括其它可移动/不可移动、易失性/非易失性计算机存储 介质。仅仅作为例子,图1示出了从不可移动、非易失性磁介质中读取或 向其写入的硬盘驱动器238,从可移动、非易失性磁盘239中读取或向其写 入的磁盘驱动器239,以及从诸如CD-ROM、DVD或其它光学介质等可移 动、非易失性光盘253中读取或向其写入的光盘驱动器240。能在示例性操 作环境中使用的其它可移动/不可移动、易失性/非易失性计算机存储介质包 括但不限于,盒式磁带、闪存卡、数字多功能盘、数字录像带、固态RAM、 固态ROM等等。硬盘驱动器238通常通过诸如接口234等不可移动存储器 接口连接到系统总线221,而磁盘驱动器239和光盘驱动器240通常通过诸 如接口235等可移动存储器接口连接到系统总线221。

以上讨论且示于图1中的驱动器及其相关联计算机存储介质为计算机 241提供了对计算机可读指令、数据结构、程序模块及其它数据的存储。例 如,在图1中,硬盘驱动器238被示为存储操作系统258、应用程序257、 其它程序模块256和程序数据255。应当注意,这些组件可以和操作系统 225、应用程序226、其他程序模块227和程序数据228相同或者相异。操 作系统258、应用程序257、其他程序模块256和程序数据255在图1中被 分配有不同的标号以说明至少它们是不同的副本。用户可以经由输入设备, 诸如键盘251和通常称之为鼠标、跟踪球、或者触摸垫的定点设备252,将 命令和信息输入到计算机241中。其它输入设备(未示出)可包括话筒、 操纵杆、游戏手柄、圆盘式卫星天线、扫描仪等。这些及其它输入设备经 常经由耦合到系统总线的用户输入接口236连接到处理单元259,但是也可 以通过其它接口和总线结构,诸如并行端口、串行端口、游戏端口、通用 串行总线(USB)进行连接。监视器242或其他类型的显示设备也通过诸 如视频接口232等接口连接到系统总线221。除了监视器之外,计算机也可 以包括其他外围输出设备,诸如扬声器244和打印机243,它们可以通过输 出外围接口233连接。

计算机241可以利用与诸如远程计算机246等一个或多个远程计算机 的逻辑连接在网络环境中操作。远程计算机246可以是个人计算机、服务 器、路由器、网络PC、对等设备、或者其它常见的网络节点,并通常包括 许多或所有以上相对于计算机241所描述的元件,虽然在图1中只示出了 存储器存储设备247。图1中描述的逻辑连接包括局域网(LAN)245和广 域网(WAN)249,但是还可以包括其它网络。这种网络环境常见于办公 室、企业范围计算机网络、内联网和因特网。

当在LAN网络环境中使用时,计算机241经由网络接口或适配器237 连接到LAN 245。当在WAN网络环境中使用时,计算机241一般包括调 制解调器250,或者用于通过如因特网等WAN 249建立通信的其它装置。 可以为内置或者外置的调制解调器250可经由用户输入接口236或者其它 适当的机制连接到系统总线221。在网络化环境中,相对于个人计算机241 所描述的程序模块或其一部分可被存储在远程存储器存储设备中。作为示 例而非限制,图1将远程应用程序248示为驻留在存储器设备247中。应 当明白,所示的网络连接是示例性的,也可以使用在计算机之间建立通信 链路的其它手段。

应当理解,此处所描述的各种技术可以结合硬件或软件、或在适当时 以两者的组合来实现。由此,本发明的方法和装置或其某些方面或部分可 以采用包含在如软盘、CD-ROM、硬盘驱动器、或任何其他机器可读存储 介质等有形介质中的程序代码(即,指令)的形式,其中,当该程序代码 被载入到如计算机等机器中并由其执行时,该机器成为用于实施本发明的 装置。在可编程计算机上执行程序代码的情况下,计算设备一般包括处理 器、处理器可读的存储介质(包括易失性和非易失性存储器和/或存储元件)、 至少一个输入设备和至少一个输出设备。一个或多个程序可以例如通过使 用API、可重复使用控件等来实现或利用结合本发明所描述的过程。这些 程序较佳地用高级过程语言或面向对象的编程语言来实现,以与计算机系 统通信。然而,如有需要,程序也可以用汇编语言或机器语言来实现。在 任何情况下,语言可以是编译的或解释的语言,且与硬件实现相结合。

尽管各示例性实施例可以涉及在一个或多个单机计算机系统的上下文 中利用本发明的各方面,但是本发明不限于此,而是可以结合诸如网络或 分布式计算环境等任何计算环境来实现。此外,本发明的各方面可在多个 处理芯片或装置中或跨这些芯片或装置来实现,并且类似地可以跨多个装 置实现存储。这些设备可能包括个人计算机、网络服务器、手持式设备、 超级计算机或整合在诸如汽车或飞机等其他系统中的计算机。

鉴于可根据图1中提供的通用框架来构建的各种计算环境,此处所提 供的系统和方法不能被解释为以任何方式限于一特定计算体系结构。相反, 本发明不应限于任何单个实施例,而应在依照所附权利要求书的宽度和范 围中解释。

此处基于使用.NET(.NET)属性来宣告整合点和符合该整合 点的软件代码的主体的概念来提供和描述了框架、系统和过程。然而, Microsoft.NET属性的使用在这里是作为一示例实施例的一部分而提出的, 因此可以用同样的方法利用以类似于Microsoft.NET软件的方式来提供属 性的其他系统、框架和/或平台。

使用.NET属性来表示整合点及其契约的存在,以及符合那些契约的功 能的存在有以下好处:属性允许元数据以静态和可串行化的方式直接与可 执行人工产物(artifact)(类、方法等)相关联。这使得元数据可被读取 或被高速缓存,从而允许系统随后在不载入模块的情况下利用该元数据。 这样做的好处是,带属性功能的开发者可以享受将元数据直接与代码人工 产物相关联的便利,但是运行时性能由系统中将元数据与代码分离并将其 单独载入的能力来增强。由于本身是.NET类型,因此属性对于.NET程序 员是一个熟悉的概念。使用公开整合点和契约的另一种方法将涉及引入一 新的机制、数据格式等,并且向系统添加不必要的和不希望的复杂性。

重要的是,消费者使用同样的.NET属性来声明对功能的依赖性,并过 滤掉那些不满足由那些属性指定的准则的实现。用于该系统所描述的任何 可插入功能的契约包括对功能的编程接口和伴随该功能的静态元数据的描 述两者。该静态元数据是按照.NET属性来表达的。消费者可以使用其自己 的代码中的属性来声明对承载了相同的属性的契约的实施例的依赖性,并 且仅与那些实施例相匹配。

接着参考图2,所示是示出在使用属性来标识和过滤可插入功能时软 件模块如何通过生产和使用符合一公共定义的功能来相互整合的图。这一 概念是用于大规模可扩展应用程序的合成模型的一部分。在该模型中,应 用程序是以模块化的方式构造的。模块262、264、268经由对定义模块262 的直接依赖性272,通过生产和消费符合一公共定义的功能来相互整合。生 产者模块268和消费者模块264保持相互独立,并且通过图2所示的定义 模块262来间接地链接在一起270。

在生产者模块与消费者模块之间建立实际链接的动作是由模块加载器 完成的。加载器负责:发现包含功能定义的模块、发现产生符合这些定义 的功能的模块、发现消费这些功能的模块、以及加载这些模块并建立消费 者264与相应的生产者268之间的连接。

以下描述的是加载器执行这些任务的机制。使用.NET属性来将各种代 码人工产物(如类、方法、特性等)标识为功能定义、生产和/或消费。这 些属性由模块加载器检查,并被用来创建单独安装的生产者268和消费者 264模块之间的关系。以下描述了两个示例实现。

接着参考图3,所示是示出根据各软件模块的生产/消费的实现的第一 示例中的执行流程的图,该软件模块通过生产和消费符合一公共定义的功 能来相互整合。在第一示例中,要生产/消费的功能的定义包括.NET属性声 明(“服务属性”)302,该属性声明源自系统提供的基类,通过一系统提 供的属性标识了一个类或接口类型(“服务对象类型”),并且具有描述 关于服务对象类型的实例的生产者的静态元数据的特性。

服务定义存在于定义模块262中,并且由模块加载器304通过反射 (reflection)来标识,从而检测满足上述准则(特别地以标识服务对象类 型的属性的存在作为关键字)的属性类定义。生产者模块268然后通过从 承载了将其标识为“ServiceProducer(服务生产者)”类308的系统提供的 属性的类静态地展示的特性来提供服务对象类型(“服务对象”)的实现,, 返回服务对象类型的实例,并且承载了提供用于描述这一生产的那个属性 的特性的适当数据的服务属性。

模块加载器304通过反射来发现这些特性,从而检测服务生产者类的 特性上的服务属性的存在。使伴随每个这种特性的服务属性实例对这些服 务对象的消费者可用,并且还由模块加载器304在对消费者声明的依赖性 满意时用于比较目的。消费者模块264通过定义提供对服务对象的访问的 类(“服务工厂”)306来表明其使用服务对象的愿望。这些提供对服务对 象的访问的类306源自一系统提供的基类,该基类由服务属性类型和服务 对象类型参数化,并且可任选地用服务属性来修饰。服务属性声明了对其 服务属性实例与由服务工厂306提供的服务属性实例相匹配的生产者的依 赖性。

消费者264例示服务工厂306,该工厂展示一返回描述生产者268的 服务属性实例的特性,以及调用生产者的服务生产特性的方法。该方法的 实现被内建到该系统提供的基工厂类中,后者使用模块加载器304对已安 装的模块的了解来得知要加载并调用哪一生产者模块268来创建服务对象。 对生产者模块268的选择的是基于由该工厂所提供的服务属性实例的值来 确定的。类似地,消费者可以创建一多生产者工厂(“服务经纪人”), 该多生产者工厂除了表示相同服务对象类型的多个生产外与服务工厂306 的行为完全一样。

参考图4,所示是示出根据软件模块的生产/消费的实现的第二示例中 的执行流程的图,该软件模块通过生产和消费符合一公共定义的功能来相 互整合。要生产/消费的功能在该第二实现中由称为“port(端口)”403的 类来定义。符合端口定义的功能单元被称为“贡献407”。贡献407包括伴 随了元数据412的静态方法。该元数据至少包含定义贡献409的端口类型 的标识。端口403是一个类定义,该类定义:源自一系统提供的基类404, 用将其标识为端口定义411的系统提供的属性以及可用于将元数据与相应 的贡献相关联的零个或多个系统提供的属性408来修饰,并且包含方法(“签 名方法”)413。签名方法通过来自基类的功能来调用一贡献方法,并且为 由端口定义的贡献定义方法签名。贡献407包括匹配端口类403的签名方 法413的方法和与该方法相关联的元数据412,这些元数据是使用端口类 403标识的属性408来声明的。

端口类403的一个实例精确地表示符合该端口403的定义的一个贡献 407。消费者使用存储在有特别属性的字段中的系统提供的分派器对象来从 模块加载304中获得端口类403的实例。在加载时,模块加载器304用匹 配在置于该字段上的属性中声明的依赖性信息的端口实例来填充这些分派 器对象。消费者可在来自分派器的端口实例上迭代、检验来自每个贡献的 元数据、并且调用贡献方法。

图4示出了使用该第二实例实现的典型生产/消费中所涉及的执行流 程。图4示出了“单一分派器”410,其中,基于分派器上提供的元数据, 可能的匹配贡献的数量仅限于一个。特别地,作为一个示例,该分派器410 需要其牌号被指定为“X”412 415的“GizmoCreator(小发明创建器)” 402贡献。带有其他牌号的贡献没有被表示出来,并且如果存在多于一个其 牌号等于“X”的贡献,则这是配置错误。

如上所述,消费者使用同样的.NET属性来声明对功能的依赖性,并且 过滤掉不满足由那些属性指定的准则的实现,这是用于大规模可扩展应用 程序的合成模型的一部分。以下将描述一个这样的合成模型的示例实现, 该模型包括在整个体系结构中用于以模块化和可扩展方式构建系统的静态 合成方法。因此,如上所述的消费者、生产者和定义模块的概念将在以下 用于大规模可扩展应用程序的合成模型的上下文中描述。

用于大规模可扩展应用程序的合成模型的上下文中的实现示例

模块性被认为是大型系统开发的一个重要方面。对可扩展应用程序的 合理设计不仅涉及将功能划分成模块,而且还需要一个被修改成适合提升 普遍的可扩展性的简单、一致、并且开放的交互模式。该合成模型规定并 强制实施这种模块性和交互模式。此处描述的模块性不是关于为类型隔离 创建边界或处理版本化问题。相反,它是创建其中人们否则可能会构建单 块代码的模块化的可扩展代码的一种方法。该模型在经由单个应用程序域 内的方法和特性来交互的CLR类型的级别上。它提供了比类型的抽象级别 更高的抽象级别,并且它是开放的,因此外部开发的模块可以利用核心系 统模块所实行的同样的机制来扩展系统。

此处描述的是关于功能如何被分成模块,以及存在何种允许这些功能 模块相互整合的交互机制的细节。该合成模型的目标是定义用于应用程序 开发的模式和机制,该模式和机制鼓励可扩展性、支持重复利用和可维护 性、并且展示出极佳的运行时性能。

该合成模型的一个核心原则是普通可扩展性。为了从一开始就促进可 扩展性概念,交互机制必须是开放的和可插入的。不管模块是应用程序的 核心部分还是第三方开发者构建的后期部署,所有模块都有同样的利用同 一交互机制来扩展系统的能力。

该合成模型模块可被重复使用,而无需多个应用程序中的修改。这要 求对其他模块提供的功能的间接依赖性,以使功能的定义保持不变,但实 现可在各应用程序之间变化。

可维护系统在其模块之中有可理解的依赖性要求。鉴于此,它们在公 有可消费部分和私有实现细节之间具有清晰的描绘。这两方面一起允许开 发者了解一改变可能对系统的影响。

模块的性能影响极小,特别是在启动的时候。该交互机制的设计允许 廉价的整合,从而将诸如模块加载或其他初始化代码等更昂贵的活动延迟 到功能被实际访问之后。

为了知道软件系统是如何工作的,人们需要识别其逻辑部分,并且了 解它们之间的依赖性和交互。在面向对象的系统中,那些部分通常是对象 (或其类型)。这能起良好的作用,但不能无限制地按比例扩大。一旦该 系统中的类型的数量变为大量,如现今Visual Studio的大小,则开发者在 类型级上理解系统的能力就开始迅速地被破坏。下一代系统甚至会更复杂。

在.NET世界里,下一抽象级别是程序集。程序集包含类型,但它们不 提供那些类型之间的关系或者应如何使用它们的一致声明。通常,本来不 相关的类型被组合到程序集中,这仅仅是为了实现更好的加载性能或分发 便利。虽然理解系统中的各程序之间的相互依赖性当然是有趣的,但这通 常是不够的。

该合成模型中的模块性模式创建了一个新的抽象级别,即落在程序集 和类型之间的模式。功能在可能涉及众多类型的单元中生产和消费,,并 且根据那些单元,模块之间的依赖性是明确的。这使人们可以在无需一路 向下到达类型级别的情况下不仅明白程序集之间的依赖性的存在,而且还 明白其存在的原因。

可扩展性在该合成模型的设计中是很流行的。这不仅仅是使应用程序 能够向最终用户提供“可扩展模型”。应用程序本身是在作为所展示的后 期部署的同一可扩展机制上构建的。动机是增强大型团队的生产力,从而 允许它们通过生产和消费以模块化的方式整合的功能而在复杂的系统上够 高效地一起工作。

除了是模块化外,为了实现真正的可扩展,系统从一开始就是开放的 并且是可插入的。该合成模型中的交互机制和模式是为这一目的特别设计 的。在各模块之间共享的功能单元被设计成开放的,从而允许应用程序中 存在任何数量的实现。这为任何模块提供了将功能插入否则可能不灵活的 应用程序中的机会。

在.NET中,有许多可能的方法来实现模块性并描述各模块之间的交 互。此处所描述的模型在整个体系结构中一致地使用的。这一公共机制具 有共享实现,以及在系统的所有开发者之间共享见解的好处。

直接与其他模块绑定限制了重复使用性。与仅包含其实际实现由未知 模块提供的某一功能的公有定义绑定则更好。这样,模块就可在包含该功 能的相同公有定义,但是更适用于该特定应用程序的完全不同的实现的另 一应用程序配置中使用。这种间接性在该模型的设计中得到继承。它不仅 允许重复使用性,而且还是开放和可插入的一个关键方面,从而使任何模 块开发者都能生产符合一公有定义的功能,由此扩展了系统。它还提供了 在公有可消费API和系统中存在的私有实现细节之间建立清晰的描绘的卓 越手段。

系统中的每一共享功能单元都可以附带有描述性元数据。其格式是功 能的公有定义的一部分的该元数据可由消费者使用以在应用程序中安装的 各种实现之间进行区分。系统优化对该元数据的访问,使得它可在不加载 生产模块的情况下获得,从而以极少的运行时成本提供了丰富的整合。

在.NET中,来自不同程序集的类型通过程序集引用相互捆绑在一起。 在运行时,当使用来自另一程序的类型时,定位并加载该程序集。无法这 样做将导致抛出异常,从而防止消费代码必须处理该类型不可用的可能性。

虽然有相互依赖性的间接特性,但是依赖性特征类似地对该模型中的 模块可用。模块作者可以声明对匹配所提供的准则的公有定义的功能的实 现的依赖性。如果对该依赖性不满意,则该模块不会被激活。这避免了必 须在过程上检测并处理该情况。

该合成模型提供了大规模可扩展应用程序的静态的、模块化的合成。 功能可在多个应用程序配置中重复使用,并且可仅有对其它功能的间接依 赖性。

该模型的一个关键方面是对共享功能的定义和实现的清楚分离。这使 得实现代码没有对其他特定实现代码的不想要的依赖性,并且清楚地标识 了公有定义,这是在功能发展时最需要关注的。

在该合成模型平台上构建的应用程序在设计上是模块化的。模块例如 是通过经由一定义良好的机制生产和消费功能来交互的.NET程序集,该机 制根本上基于调用另一模块中的静态方法的简单动作。添加到该简单动作 的主要概念是间接性,从而准许由任何程序集而非一个特定程序集来提供 所需功能。作为这种间接性的结果,可能存在所需功能的多个实现,并且 消费者可以调用所有的所需功能,或基于每个功能所附的元数据来选择一 个子集。

存在该模型在应用程序合成中起作用的三个领域:构建、链接和运行 时。存在在该模型中使用的某些编程模式和实施,并且提供了验证工具以 在构建时检查和强制实施对这些规则的遵从。各模块之间的依赖性是间接 的,但是应用程序的合成在该模型中保持静态。由此,存在连接生产者和 消费者的链接阶段。该阶段在概念上是在紧靠运行时之前出现的。还存在 被称为“内核”的系统的运行时部分,它处理程序集的加载和激活、将来 自消费者的调用传送给适当的功能生产者,并且提供对其相关联元数据的 访问。然而,一旦被构造并被链接在一起,应用程序的执行一般很少涉及 内核。各程序之间的交互点在该模型中静态地描述。在当前的示例中,重 新洗牌(card shuffling)功能被置于另一程序集中(或者,可能被提供给另 一程序集形式的Poker.dll的作者)。poker(纸牌)程序集可仅通过添加对 CardGameUtilities.dll(纸牌游戏实用程序)的引用并直接调用静态方法来 使用该重新洗牌代码。该合成模型中的各程序集之间的交互与调用静态方 法非常相似。关键的区别是,在所需功能的生产者和消费者之间有一间接 级别。可以把这种间接看作是由静态方法以与类实现接口相同的方式“实 现”的“接口”。方法的调用者只知道该方法的形状,但不知道或不介意 该方法是来自哪个程序集。

接着参考图5,所示是示出根据软件模块的所需功能的生产者和消费者 之间的间接程度的图,该软件模块通过生产和消费符合一公共定义的功能 来相互整合。该间接以图5中所设计的C#句法来示出。如图5所示,实际 的洗牌代码存在于Poker.dll不知道的程序集中。它“实现”类Shuffler(洗 牌器)504中定义的调用者未知的方法“接口”。来自Poker(纸牌)类506 的调用被定向到MyCardShuffler(我的洗牌器)类508中的实现。取决于 应用程序配置,调用可被定向到一完全不同的洗牌实现而无需修改作出调 用的程序集。

应当注意,图5所示的所设计的句法不应按字面意思解释为对语言扩 展的建议。将在本文的稍后部分中详细介绍用于实现这一点的实际机制。 虽然为易于理解这些概念而考虑语言扩展是有趣的,但图5所示的“句法” 并不是对这种延伸的建议。

图5所示的一组三个程序集502、504、808表示了一常见的三元组, 被称为诸如以上参考图2至图4所描述的定义、生产者和消费者程序集。 术语生产者程序集和消费者程序集通常仅在单个定义,例如图5所示的 ShuffleDeck(洗一付牌)方法510的上下文中使用。通常,一个交互定义 的生产者程序集也是另一交互定义的消费者程序集。因此,术语实现程序 集用来表示将实现程序集与定义程序集区分开来的这种程序集。

生产者与消费者之间的间接性允许系统的另一重要方面的出现。这个 方面就是所需功能的多个实现对消费者可用的能力。这显然需要一不同的 调用模式,此处未示出。本质上,消费者会需要在一组方法上迭代,并且 或者调用所有方法,或基于随这些方法提供的元数据来挑选其中的一个(或 一些)。后者是一个关键的概念,它提供了系统中的丰富、开端口型的可 扩展能力,以及用于通过延迟加载来获得更大性能的机制。

该合成模型中的程序集交互中涉及的基本模式是一个熟悉的生产者/消 费者模式。在所有情况下,生产者和消费者之间都有一个间接级别,以使 得它们之间不存在直接依赖性。符合定义的功能的多个消费者以及多个生 产者都允许存在于系统中。在该模型中生产和消费的功能在概念上与一静 态方法等价。除了所述方法可能返回一个任何类型的对象以外,系统不规 定任何特定形式的对象交换。

生产者程序集以贡献的形式为系统增值,该贡献是具有某些附带的元 数据的静态方法。方法和元数据的形状由一贡献端口(或端口)来定义。 端口是唯一地标识功能的生产者和消费者之间的联系点的类。端口类的实 例表示由该端口定义的单个贡献,并且提供了对元数据的访问,以及调用 该贡献的方法的方式。消费者从称为分派器的特殊对象中获得端口实例, 该分派器被存储在同样承载了消费者对匹配贡献的依赖性声明的私有字段 中。这些字段以及贡献方法都是称为经纪人的静态类的成员。经纪人“买 进和卖出”(消费和生产)相互关联的贡献,以形成单数的拒绝单元。当 经纪人生产与其它贡献冲突,或依赖于不可用的贡献的贡献时,经纪人就 遭到拒绝。

贡献是具有某些相应的元数据的静态方法。贡献由程序集“生产”和 “使用”。“消费”贡献是要检查其元数据和/或调用其方法,而包含该贡 献的程序集被说成是“生产”它。贡献的生产和消费以可静态描述的、但 间接的方式出现。这意味着一个程序集生产固定数量的贡献,这些贡献都 能通过检查该程序集来唯一地标识,并且由一程序集消费的贡献也可基于 所声明的依赖性信息来发现。然而,在生产贡献和消费贡献的程序集之间 从来都没有直接引用。这些连接由加载器建立。

贡献方法是经纪人类中声明的私有的、静态方法。元数据采用置于贡 献方法上的属性的形式。要求方法匹配端口类中特别指定的方法的签名。 可用于修饰贡献方法的属性的类型也被标识为端口定义的一部分。

贡献端口是定义贡献的形状的类。人们可以将端口看成是贡献所实现 的接口定义。记住,该模型中的生产者和消费者之间从来都没有直接的程 序集引用。端口是直接端口;贡献的生产者和消费者都具有对包含端口定 义的程序集的直接引用。端口定义的一部分是组成贡献的元数据的一组属 性类型的声明。这些类型通过置于端口类定义本身上的属性来标识。同样, 端口定义的一部分是用作消费者用来调用贡献方法的入口点的公有方法。 该方法被称为“签名方法”,因为它也类似于接口定义了贡献方法的签名。

虽然端口类定义了相应的贡献必须看上去是什么,但是端口类的实例 表示单个这样的贡献。有了端口实例,消费者就有了检查贡献的元数据部 分的手段(通过从基类ContributionPort(贡献端口)中展示的功能),以 及调用贡献方法的手段(通过端口的签名方法)。

注意,端口实例有时是指“贡献实例”或者甚至仅仅是指“贡献”。 这种引用的上下文环境通常足以在端口类的实例和贡献的生产(实际上不 是对象)之间进行区分。

实现程序集通常既是生产者又是消费者。“进入”实现程序集和从其 中“出来”的贡献流程集中在一个称为经纪人的静态类中。贡献方法实际 上是经纪人类的成员。还有存储在经纪人类的静态字段中的对象(称为分 派器),它们表示“传入的”贡献--由包含经纪人类的程序集消费的那 些贡献。

经纪人将贡献的相关消费和生产关联起来。例如,由实现程序集生产 的贡献可能由消费来自别处的另一贡献的代码所支持。如果所消费的贡献 不可用,则应拒绝所生产的贡献。

虽然这有点少见,但实现程序集可能包含多于一个经纪人类。在这种 情况下,与一个经纪人相关的程序集中的代码就必须完全独立于与任何其 他经纪人相关的代码。本质上,程序集必须是可分的,以使每个程序集有 一个经纪人,并且它们之间没有程序集引用。如果不满足这个要求,则经 纪人就不能经受得住独立的拒绝。

注意,一般而言,实现程序集的开发将为每个程序集生产单个经纪人。 如果分发便利或加载性能情形要求的话,经纪人成为拒绝单元而非程序集 的能力就允许实现程序集的后构建组合。

端口实例不能仅仅由具有新的表达式的消费者来创建。相反,端口实 例由加载器提供给消费者,因为它们表示源自只为加载器所知的程序集的 贡献。消费者使用被称为分派器的对象来获得端口实例。

分派器是消费者利用新的表达式创建的对象。它们被静态地存储在经 纪人类的字段中,并且那些字段用基于所标识的端口来声明消费者对贡献 的依赖性的性质的属性来修饰。那些属性用于确定哪个(如果有的话)可 用贡献匹配消费者的依赖性。在加载时,加载器用表示匹配贡献的端口实 例来填充分派器。

消费者也可以表明至少一个贡献必须可用的要求。如果没有定位到这 样的贡献,则经纪人就被拒绝。

有两种形式的分派器,其中一个包含单端口实例,另一个包含端口实 例的集合。单分派器是在消费者标识单个贡献时使用(或在只有单个贡献 可用的情况下)。多分派器是在多个贡献可用,且消费者准备好在它们之 中进行选择或利用它们全部时使用。

拒绝防止依赖于遗漏贡献或违反系统约束(如生产冲突贡献)的代码 被加载或执行。这允许消费者能够在不针对遗漏依赖的可能性进行防御性 编码的情况下可信地使用贡献。它还保证系统是由一组不相互冲突的有效 贡献组成。

拒绝在应用程序的开发生命周期的“链接阶段”中出现。该阶段概念 上在应用程序开始运行前,但在候选程序集的集合被部署在系统中之后发 生。拒绝单元是经纪人类,它是贡献的成对的相关消费和生产。通常,每 个实现程序集有单个经纪人类,但是拒绝的粒度是经纪人类以在适当时允 许将实现程序集合并在一起。

如果经纪人类被拒绝,则它就如同从来没有存在过一样。这意味着它 生产的贡献将被加载器忽略,从而保证没有消费者能够访问它们。这保证 了使用由该经纪人类分派的贡献的任何代码永远不会被执行。此外,拒绝 是一个层叠事件。如果经纪人被拒绝,则其生产实际上也不存在。如果另 一个经纪人声明了对这些生产中的任一个的依赖性,则该经纪人也会被拒 绝,依此类推。这个周期持续到满足所有剩余的经纪人的要求。

端口定义必须出现在来自贡献的单独的程序集中,从而提供生产者和 消费者之间的间接性。这种间接性通过迫使开发者思考其组件的公有表面 并保持其实现细节私有化来得到更好的版本弹性和更清楚的模块化设计。

定义程序集和实现程序集有以下区别。没有其他程序集会有对实现程 序集的依赖性,这会使得实现程序集包含公有类型变得无意义。另一方面, 定义程序集自然地被其它程序集所依赖。定义程序集主要包含公有抽象类 型定义,而实现程序集则包含更复杂的实现代码。只有实现程序集可以包 含贡献。定义程序集中的经纪人类只可以包含分派器。

编程模型

本节讨论了在合成模型中的生产者和消费者之间建立连接时所涉及的 编程模型。虽然不是一个完整的功能说明,但是这些部分将给出对该模型 的编程中所涉及的各种类和属性以及模式和实践的可靠的理解。

各个概念是通过演示在一简单示例情形中定义、生产和消费功能所需 的各步骤来提出的。该示例然后逐渐增强以便示出该编程模型的更多能力。

示例情形

为演示该编程模型,使用以下交互情形。假定存在消费者程序集感兴 趣的接口定义。关于该接口的作用的细节并不重要。该接口被称为例如 IGizmo(小发明接口)。消费者程序集对以开端口的方式创建这些小发明 的实例感兴趣(意味着它希望允许各实例自来任何程序集,可能是作为除 应用程序外的后部署来安装的)。

考虑到这个情形,将该消费者和生产者之间的交互点定义为“小发明 工厂(gizmo factory)”是有意义的。也许有该“小发明工厂”类型的任意 数目的贡献,但是每个贡献都有同样的基本行为,即创建和返回IGizmo的 实例。

该情形将在本文的稍后部分中展开,但现在,假定消费者需要从每个 贡献中创建一个小发明。

定义端口

端口是公有类定义,并且必须置于定义程序集中。对系统提供的所有 端口定义有一基类,称为ContributionPort(贡献端口)。它是泛型的,由 贡献方法的返回类型来参数化。

端口定义除了是源自ContributionPort基类外,还必须带有元数据。端 口定义最少必须用PortDefinition(端口定义)属性来修饰。

端口定义的最后要求是它必须声明一签名方法。该签名方法不仅定义 了相应的贡献方法的签名,并且它还是消费者实际调这些方法的手段。端 口类中的签名方法通过带有SignatureMethod(签名方法)属性来标识。

给定这些要求,本示例情形的端口定义如下所示:

[PortDefinition]

public sealed class GizmoFactory:ContributionPort<IGizmo>

{

     [SignatureMethod]

     public IGizmo CreateGizmo(int size)

     {

      return this.InvokeContribution(size);

   }

}

签名方法的形状是基于什么对该情形有意义--在这一情况下,出于 例示的目的,假定小发明有一个影响其构造的大小(size)参数。签名方法 的返回类型必须匹配提供给ContributionPort基类的类型。注意,这个规则 有一个例外,即签名方法返回空值的情况。在这种情况下,提供给Port(端 口)基类的类型应当是对象。同样应注意签名方法的主体。这是所有签名 方法实现都会有的基本形式。对InvokeContribution(调用贡献)方法 (ContributionPort基类中的受保护方法)的调用使内核调用由该端口实例 表示的贡献方法。

生产贡献

现在已经定义了端口,检验生产者程序集是如何提供小发明工厂贡献 的。贡献是带有元数据的静态方法,并且这些方法是经纪人类的成员。Broker (经纪人)类属于实现程序集,所以它是非公有的。Broker类通常被定义 为静态方法(如果是用C#语言编写的话),因为它们从来都没有被实例化 过,并且只包含静态成员。Broker类还必须用将其标识为经纪人类的Broker 属性来声明。

以下代码示出了生产小发明工厂贡献的经纪人类:

[Broker]

static class Broker

{

     [Production(typeof(GizmoFactory))]

     private static IGizmo CreateTurboGizmo(int size)

     {

          return new TurboGizmo(size);

     }

}

围绕所实例化的实际小发明对象的细节被省略了。该示例代码的重要 方面是生产属性将CreateTurboGizmo(创建Turbo小发明)标识为用于 GizmoFactory端口的贡献方法,并且该方法是私有且静态的,且有一不同 的名称,但却匹配端口的签名方法。这是与贡献方法的匹配规则相一致的。

消费贡献

消费者通过获得定义贡献的端口的实例来消费贡献。因为只有内核知 道关于贡献的来源的细节,因此内核是端口实例唯一的发源地。它们通过 称为分派器的对象被提供给消费者,这些分派器是由消费者静态地创建和 存储在其经纪人类的私有字段中的。这些字段必须带有将它们标识为消费 的属性(称为Comsumption(使用))。

有两种形式的分派器,一种被称为SingleDispenser(单分派器),另 一种被称为MultiDispenser(多分派器)。正如它们的名字所示的那样,它 们分派单个端口实例,或一组端口实例。端口的类型作为类型参数来提供。

在当前情形的情况下,需要MultiDispenser,因为期望从每个可用的贡 献中创建一个小发明,而可用的贡献的数量可为任意数目。以下经纪人类 包含用于小发明工厂的分派器:

[Broker]

static class Broker

{

     [Consumption]

     private static MultiDispenser<GizmoFactory>d=new MultiDispenser<GizmoFactory>();

     public static IList<GizmoFactory>GizmoFactories

     {

          get

          {

            return d;

        }

    }

}

此处的关键是MultiDispenser<GizmoFactory>类型的字段d。该字段在 该经纪人被加载时由内核识别(通过Consumption(消费)属性)并且被自 动填充。GizmoFactory类型的所有贡献的每个贡献都各自由GizmoFactory 的一个实例在分派器中表示。作为惯例,字段被标记为私有的,并且存在 将端口实例的集合展示给程序集中剩余的代码的相应的公有访问特性。该 特性的类型为Ilist<>(列表接口)而非MultiDispenser<>,这仅仅是因为该 特性的消费者不需要或不想知道它们正在处理的是分派器;它们满足于知 道它们有一端口实例列表。实际上,MultiDispenser<>不会展示除了实现 IList<>接口所需的之外的任何其它成员。

写好了该经纪人类后,消费者程序集只需要编写以下代码来完成该示 例情形:

foreach(Broker.GizmoFactories中的GizmoFactory f)

f.CreateGizmo(42);

执行流程

接着参考图6,所示是示出了从消费者经由到个单个生产者的通过当前 情形的执行流程的图。所示是消费者程序集602、定义程序集604、内核606 以及生产者程序集608之间的流程。

添加元数据

到目前为止,该示例情形已经演示了贡献方法如何被消费者调用。然 而,以下将提供涉及可以伴随这些贡献的元数据的应用。为了阐明这一点, 略微改变该示例。给予小发明工厂一商标名称(brand name),从而所有的 小发明工厂就可以被相互区分。并且消费者的功能变成将其创建的每一小 发明置入以工厂的商标名称为关键字的表中。

可用于将元数据添加给贡献方法的属性的类型必须识别为端口定义的 一部分。这通过使用ContributionMetadataType(贡献元数据类型)属性来 完成,该属性被直接置于端口类定义上。

在该新的示例情形中,定义了一个元数据,它与小发明工厂贡献:商 标名称相关联。第一步是定义表示该商标名称的属性,这是直截了当的, 因此这里被省略。假定该属性的名称为Brand(商标),它被声明为 AllowMultiple=false(允许多个=假),并且它有称作Name(名称)的单个 串特性。为将该属性与端口相关联,使用以下ContributionMetadataType属 性:

[PortDefinition]

[ContributionMetadataType(typeof(BrandAttribute),IsRequired=true, MustBeUnique=true)]

 public sealed class GizmoFactory:ContributionPort<IGizmo>

 {

      [SignatureMethod]

      public IGizmo CreateGizmo(int size)

      {

           return this.InvokeContribution(size);

      }

}

该属性允许GizmoFactory类型的贡献以Brand属性为属性。实际上, 这要求贡献用Brand属性来修饰,并且该属性的值在所有GizmoFactory贡 献中必须是唯一的。

注意,虽然每个属性类型只被指定一次,但任意数量的属性都能以这 种方式与一端口定义相关联。

向元数据提供贡献

现在已经改变了端口的定义,贡献需要做以下改变:

[Broker]

static class Broker

{

     [Production(typeof(GizmoFactory))]

     [Brand(Name=“Acme”)]

     private static IGizmo CreateTurboGizmo(int size)

     {

          return new TurboGizmo(size);

     }

}

注意,由于编写本实例的渐进式公开风格,所以对端口定义作出了中 断的、不可后向兼容的改变。在实践中,如果IsRequired(是否必需)被设 为假,则向端口定义添加元数据类型才被认为是可后向兼容的。

消费元数据

对为贡献提供的元数据的访问是由ContributionPort基类以一般的方式 来提供的,即通过类型为ContributionMetadata(贡献元数据)的称作 Metadata(元数据)的特性来提供。这基本上是是一属性集合,其具有找出 并返回指定属性类型的实例的称为FindAttribute<>和FindAttributes<>(找 出属性)的泛型的、便利的方法。

以下示出了来自上一个示例的消费者代码可被修改成将所创建的小发 明桶装(bucket)成以工厂的商标名称作为关键字的词典中:

Dictionary<string,IGizmo>dict=new Dictionary<string,IGizmo>();

foreach(GizmoFactory fin Broker.GizmoFactories)

{

       string brandName=f.Metadata.FindAttribute<BrandAttribute> ().Name;

       dict.Add(brandName,f.CreateGizmo(42));

}

注意,假定FindAttribute调用会成功被认为是“安全的”,因为端口 定义声明Brand属性必须伴随所有贡献。

声明依赖性

为了演示声明对贡献的依赖性的概念,再次略微改变该示例情形。此 次,增加了对消费者给予至少一个GizmoFactory类型的贡献的要求。然后, 对该要求进一步细化,规定消费者必须找到具有匹配一组三个所提供的商 标名称中的一个的商标名称的至少一个贡献。最后,它被限制为给予一个 有一特定商标名称的贡献的要求。

要求至少一个贡献

如上所述,消费者代码不声明对GizmoFactory类型的贡献的任何依赖 性。依赖性声明的最简单形式是规定对至少一个贡献的需求。这通过将 Consumption属性上的Required(必需)参数设置为真来完成,如下所示:

[Broker]

static class Broker

{

      [Consumption(Required=true)]

      private static MultiDispenser<GizmoFactory>d=new MultiDispenser<GizmoFactory>();

      public static IList<GizmoFactory>GizmoFactories

      {

           get

       {

            return d;

        }

    }

}

这规定,作为对该要加载或执行的经纪人(以及任何相关联的代码) 的先决条件,必须有至少一个贡献被置于分派器中。如果安装不包含这一 贡献,则该经纪人就被拒绝。

此处所描述的各种系统、方法和技术可以用硬件或软件,或在适当时 以两者的组合来实现。因此,本发明的各个方法和装置,或其某些方面或 部分可以采用包含在诸如软盘、CD-ROM、硬盘驱动器、或任何其他机器 可读存储介质等有形介质中的程序代码(即指令)的形式,其中,当该程 序代码被载入到诸如计算机等机器中并由其执行时,该机器成为用于实施 本发明的装置。在可编程计算机上的程序模块执行的情况下,计算机一般 包括处理器、处理器可读的存储介质(包括易失性和非易失存储器和/或存 储元件)、至少一个输入设备、以及至少一个输出设备。一个或多个程序 较佳地用高级过程语言或面向对象的编程语言来实现,以与计算机系统进 行通信。然而,如有所需,程序也可以用汇编语言或机器语言来实现。在 任何情况下,语言可以是编译或解释语言,并且可以与硬件实现相结合。

本发明的方法和装置也可以用通过某一传输介质,诸如通过电线或电 缆、通过光纤、或通过任何其他形式的传输传输的程序代码的形式来实施, 其中,当该程序代码被诸如EPROM、门阵列、可编程逻辑器件(PLD)、 如以下图中所示的客户机计算机、录像机等机器接收并载入到该机器中且 由其执行时,该机器成为用于实施本发明的装置。当在通用处理器上实现 时,该程序代码与处理器相结合以提供一用于执行本发明的索引功能的独 特装置。

虽然已经结合各图中的较佳实施例描述了本发明,但是应当理解,在 不背离本发明的情况下,可以使用其他类似的实施例或可对所描述的实施 例进行修改和添加来执行本发明的相同功能。此外,应当强调,此处构想 了各种计算机平台,包括手持式设备操作系统和其他应用专用硬件/软件接 口系统,尤其是当无线联网设备的数量持续增加的时候。因此,本发明不 应限于任何单个实施例,而是相反,应在根据所附权利要求书的宽度和范 围内解释。

最后,此处所描述的所公开的实施例可以适用于其他处理器架构、基 于计算机的系统、或系统虚拟化,并且这些实施例为此处所做出的公开清 楚地预想,因此,本发明不应限于此处所描述的具体实施例,而是相反, 应从最宽泛的意义上来解释。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号