ASP.NET提供程序模型

ASP.NET提供程序模型

在ASP.NET提供程序模型的背后有一个著名的设计模式——战略(strategy)模式。根据定义,战略模式指一种可以通过各种可互换的算法(比如Quicksort和Mergesort)实现的预期行为(比如“排序”)。然后,在保持公开的、可观察的行为和编程API不变的同时,每个应用程序选择最适合的算法。

战略模式最突出的特征是,它为对象或整个子系统提供了一种向外提供自己内部构件的方法,使客户可以去掉一个给定特征的默认实现并插入自己的实现。ASP.NET中的许多服务正是这样的,包括成员资格、角色、状态管理、个性化和站点导航。ASP.NET提供程序模型是ASP.NET对战略模式的实现。

1.4.1  提供程序模型的基本原理

提供程序模型不是最终用户能够亲眼所见的应用程序特征。提供程序模型本身并不会使一个应用程序展示出更丰富的内容、运行得更快或者更迅速地做出响应。提供程序模型是一个基础特征,能使开发者和设计师在理解某些系统组件的前提下进行工作,从而改进一个应用程序的构架。同时,它使开发者能够构造新组件,向外提供工具,使客户能够插入和定制行为和设置。实施战略模式并不是指把一个应用转化为一个开源项目,允许任何人修改任何东西。而是指我们有一个简单的、优雅的和有效的模式,使客户可以对应用程序的某些部件进行定制。但是,ASP.NET对战略模式的实现,即提供程序模型,使我们能够通过称为提供程序的特殊的类(可由此派生出自己的类)对ASP.NET运行时环境的某些部件进行定制。

1. 提供程序模型实例

为了观察提供程序模型的实例及其主要好处,让我们来看图1.6。该图概括了用户身份验证的经典模式。该图中的各方框严格遵循ASP.NET 1.1中的操作流。

 

图1.6  ASP.NET 1.1应用的经典成员资格模式

向企图连到一个受保护页面的用户显示一个注册页面,要求他输入身份。接着,姓名和密码被传递给一个函数,该函数最终负责确认该用户。ASP.NET 1.x可以根据Windows账户或web.config文件中的姓名列表自动地核实用户。在实际的Web应用中,这些方法没有一个会行之有效;在大多数情况下,开发者不得不编写一段定制代码,根据一个自制的数据源来确认身份。该数据源的模式和存储介质是固定的,并且由开发者决定。同样,用来确认身份的算法受到设计的限制。

这种解决方案有问题吗?未必。它可以很好地起作用,使你能够控制一切,并且能够适宜在其他应用中工作。问题难就难在不能从这种解决方案获得良好定义的模式。当然,你可以把它从一个应用程序移植到下一个应用程序,但是总的说来,该解决方案与适配器的关系更像是剪切和粘贴与面向对象继承的关系。

让我们简单考虑另一种场景——会话状态管理。在ASP.NET 1.x中,会话状态可以存储在一个与正在运行的应用相分离的进程中——而不管正在运行的应用是SQL Server还是Windows服务(ASP.NET状态服务器)。然而,如果这样存储会话状态,则只能使用ASP.NET为你硬编码的数据模式。进一步设想一下,假设你不是一个SQL Server客户。在这种情况下,要么放弃把会话状态存储到一个数据库中的想法,要么购买一组SQL Server许可。最后,你不能对ASP.NET会话模块的内部行为进行任何处理。即使不喜欢它把数据串行输出到进程外的存储器中,也不能改变它。要么接受它,要么放弃它——没有其他选择。

你能看出ASP.NET的宏伟蓝图吗?ASP.NET中有些模块迫使你采取(或放弃)固定的数据模式、固定的存储介质和固定的内部行为。你能做的最多是(有时)不使用那些模块,而从头开始编写自己的模块,如我们在成员资格模块中所描述的那样。然而,编写自己的替代模块未必就是明智之举。你最后得到的是一个与应用相关的专用系统,不能自动地从一个应用程序移植到另一个应用程序。此外,如果聘请新成员,还必须进行培训,使他们习惯使用你自己编写的API。最后,你不得不投入大量精力使这种专用API具有通用性,以便在各种环境中进行重用和扩展。(否则,你不得不三番五次地重头做起。)

 

从哪些方式能够看出提供程序模型是一种更好的解决方案呢?首先,它提供了一个文档完好的通用编程接口来执行通用任务。此外,你能够完全控制它的每个API的内部事务和数据访问逻辑。

最后,在ASP.NET 1.1中,除了编写自己的API以自己喜欢的方式提供某些功能外,通常别无他选。在ASP.NET 2.0中,提供程序模型提供了一个更好的替代方案。这种方案相当出色,不使用它简直是一种罪过。

图1.7从提供程序模型的观点再现了图1.6。ASP.NET 2.0在一个全局类(Membership)中提供了大量静态方法。(第15章将详细介绍成员资格API)。在应用级,总是调用相同的方法来执行相同的操作(例如,确认用户身份,创建新用户,修改密码)。然而,在这个通用API下,可以插入自己的提供程序,完全以自己希望的方式执行该作业。编写一个新的提供程序犹如从一个已知的基类派生一个新类并覆盖几个熟悉的方法那么简单。在配置文件中为指定任务选择当前提供程序。

 

图1.7  ASP.NET 2.0中使用提供程序模型的Membership

2. 提供程序模型的好处

在ASP.NET的实现中,战略模式带来了两个主要好处:应用程序的运行时环境的广泛定制和代码重用。提供程序模型影响了ASP.NET中的几个领域。我们可以编写提供程序来处理用户成员资格和角色,永久保存会话状态,通过个性化管理用户配置文件,以及从各种信息源装载站点地图信息。例如,通过编写一个提供程序,我们可以改变用来永久保存身份的数据模式,把该数据存储在一个Oracle或DB2数据库中,并将密码以密文(而不是明文)形式进行存储。系统组件可以随意定制,并且为应用程序开发者开创了全新的世界。与此同时,它也为编写新的提供程序,甚至是为扩展自己的组件模型提供了一个良好的   起点。

 如果从已有的应用程序的角度考虑ASP.NET 2.0,提供程序模型与技术更相关,因为它是代码重用以及随后保护在编程和开发时间方面的投资的关键。正如我们所指出的,ASP.NET 1.1中实际的成员资格管理系统(membership system),在有效性检查和用户管理方面要求运行自己的API。决定升级到ASP.NET 2.0时应该怎么办呢?应该放弃所有自己的代码,而采用ASP.NET 2.0令人眼花缭乱的全新成员资格API?还是坚持使用老式的、专用的成员资格API呢?

提供程序模型特有的在保持总体行为的同时可以切换底层算法的能力,为上述问题提供了答案(的确是一个理想的答案)。然而,光有这种能力是不够的。我们还需要修改已有的代码,使它可以插入新的运行时环境中。另一个流行的模式帮助解决了这个难题——适配器模式。适配器模式的目的是把一个类A转换为客户C理解的一个接口B。我们把现有的代码封装到一个新的提供程序类中,这个新的提供程序类可以无缝地插入现有的ASP.NET 2.0框架中。我们修改成员资格API的底层实现,并在保持最高层级的接口不变的同时使用自己的模式和存储介质。而且更重要的是,我们可以充分重用自己的代码。

1.4.2  ASP.NET实现概述

ASP.NET提供程序模型的实现牵涉到三个不同的元素:提供程序类、配置层和存储层。提供程序类是我们插入到现有的框架中、以我们所需的方式提供期望功能的组件。配置层提供用于标识和实例化实际提供程序的信息。存储层是存储数据的物理介质。依据特征的不同,这可以是Active Directory(活动目录)、一个Oracle或SQL Server表、一个XML文件或者任何其他介质。

1. 提供程序类

提供程序类实现一个可以为其客户理解的接口。这样,它就为客户提供了该接口承诺的功能。客户不必知道有关接口的所有实现细节。这种代码不透明性使代码具有驱动根本不知道的其他代码的魅力。对于战略模式的原始定义,ASP.NET提供程序模型只有一处变动,即用基类代替了接口。

ASP.NET中,提供程序类不能只是实现一个指定接口的类,实际上正好相反。提供程序类必须继承一个众所周知的基类。每一种受支持的提供程序都有一个基类,基类通过一组抽象方法定义了该提供程序的编程接口。

所有提供程序的基类都派生于一个公共类,即ProviderBase。该基类提供了可重写的方法Initialize,运行时环境通过这个方法传递配置文件中所有相关的设置。图1.8概括了成员资格的提供程序类的层次结构。

 

图1.8  提供程序类的层次结构

接口与基类

作为开发者,谁从来没有陷入过周而复始地争论应该使用接口还是基类?这是一场永无休止的争论,不同阵营的人总是坚定地坚持自己的立场。应当使用接口还是基类?回答这个问题应考虑哪些因素?首先,考虑如下事实。

ASP.NET 2.0 beta测试前的构造完全是通过战略模式的定义,即通过接口,实现提供程序模型。在Beta 1时,基类取代了接口,因而发行版也使用基类。ASP.NET团队看起来好像对此问题有了解决方案,不是吗?

接口是逻辑上相关的方法的集合,只包含成员定义而没有代码。接口类型是一种类型的部分描述,可能有多个类支持它。换句话说,一个良好的接口是由许多不同的类型实现的,并且封装了一种有用的、客户希望使用的通用功能。正因为此,很多接口都采用后缀“able”作为结尾,诸如IDisposable、IComparable和IFormattable。如果一个接口只有一个有用的实现类,则该接口可能是设计不当而造成的后果。实践表明,引入新的接口要谨慎,并且应预先计划好。

基类定义子类树的公共行为和公共编程接口。类比接口更灵活,并且支持版本编号。如果添加一个新方法到一个2.0版本的类,则只要该新方法不是抽象的,已有的任何派生类仍然能够毫无变化地起作用。对接口则不一样。

根据这些考虑因素,最新规则是:只要有可能,尽量使用基类而不使用接口(但不是“总是使用基类”)。对我而言,在考虑提供程序模型的情况下,基类似乎是一种出色的选择。

2. 配置层

在配置文件中,每种受支持的提供程序类型都被分配一个小节。这里设置特征的默认提供程序,并列出所有可用的提供程序。如果提供程序具有公有特征,则这些特征的默认值可以通过属性加以规定。一节内容作为一个参数传递给ProviderBase类的Initialize方   法——只有这个方法是所有提供程序都有的。在这个方法中,每个提供程序使用传递的信息初始化自己的状态。下面给出了成员资格提供程序的配置节的简短描述。

<membership defaultProvider="AspNetSqlProvider">

    <providers>

        <add name="AspNetSqlProvider"

            type="System.Web.Security.SqlMembershipProvider, System.Web"

            connectionStringName="LocalSqlServer"

            enablePasswordRetrieval="false"

            enablePasswordReset="true"

            requiresQuestionAndAnswer="true"

            

            passwordFormat="Hashed" />

        

    </providers>

</membership>

3. 存储层

所有提供程序都要从一个持久性存储介质读写信息,在很多情况下,两个相同类型的提供程序只存在它们所用存储器的不同这一点差异。在<provider>小节中,存储介质的详情封装在提供程序的属性中,如前面的范例代码所示。例如,前面的AspNetSqlProvider提供程序是预定义的成员资格提供程序,负责读写一个SQL Server表。该提供程序的连接字符串通过connectionStringName属性加以规定,而该属性又引用另一个集中了配置文件的小节,这里列出了所有可用的连接字符串。

为了使提供程序起作用,必须存在所有必需的基础结构(即数据库、表、关系)。工作环境设置通常是在部署时完成的。由于有网站管理控制台(如图1.9所示),ASP.NET使这项任务变得很容易。

 

图1.9  从Visual Studio .NET 2005中激活的ASP.NET 网站管理控制台

4. 可用的提供程序类型

提供程序模型用于实现几个任务,最重要的几个任务如下:

  • 永久保存用户配置文件的读/写机制的实现。
  • 创建一个用户定义的用户身份存储库,用于支持大多数通用操作,诸如核实一个用户的存在、添加和删除用户以及改变密码。
  • 创建用户定义的用户角色存储库。
  • 定义站点地图。
  • 为会话状态引入更新的数据存储类型。

表1.1列出了ASP.NET中可用的提供程序类。

表1.1  现有的ASP.NET提供程序基类

描    述

MembershipProvider

成员资格提供程序的基类,用来管理用户帐户信息

ProfileProvider

个性化提供程序的基类,用来永久存储和检索用户的配置信息

RoleProvider

角色提供程序的基类,用来管理用户角色信息

SessionStateStoreProviderBase

会话状态存储器提供程序的基类,这些提供程序用来把会话状态信息保存在持久性存储介质中,或从中检索会话状态信息

SiteMapProvider

管理站点地图信息的基类

表1.1中列出的类为它们所代表的特征中每个可定制的方面定义了一个抽象方法。例如,关于成员资格管理,MembershipProvider类提供了诸如ValidateUser、CreateUser、DeleteUser、ChangePassword等方法。注意,仅仅因为MembershipProvider是一个抽象类,所以绝不能在代码中使用它。但可以在代码中使用它的派生类,诸如SqlMembershipProvider或者ActiveDirectoryMembershipProvider。这一点同样适用于其他的提供程序类型。

最后,如果打算编写一个自定义的成员资格提供程序,用它封装现有的代码,可以从MembershipProvider类或相似的类继承,创建一个新的类(如果还要包含其他基于提供程序的特征的话)。

  注意 

提供程序构架是ASP.NET 2.0的最重要的新特征之一,也是与应用相关的最难掌握的特征之一。为了防止开发者开发出拙劣的提供程序类,ASP.NET团队提供了一个量身定做(made-to-measure)的提供程序工具箱,详细论述了一个提供程序能干什么和不能干什么,同时提供了大量范例代码加以指导说明。至少有两个原因使自定义提供程序的编写比较棘手。首先,ASP.NET提供程序必须是线程安全的。其次,初始化步骤会引导你直接进入一个致命的重入。在突然转向一个新的提供程序项目之前,一定要从ASP.NET开发者中心(ASP.NET Developer Center)下载ASP.NET提供程序工具箱。

posted @ 2012-05-07 21:46  SunShineTian  阅读(241)  评论(0编辑  收藏  举报