惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
IT之家
IT之家
Google DeepMind News
Google DeepMind News
罗磊的独立博客
爱范儿
爱范儿
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
U
Unit 42
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
B
Blog
博客园 - 叶小钗
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - 林614

IIS问题:Server Application Error 的解决 实现自己的ProviderBase UML建模的要点总结 软件企业致胜的18种成功模式 自定义协议的注册及程序示例(C#) Remoting事件处理全接触 Marshal、Disconnect与生命周期以及跟踪服务 Net Remoting基础篇 在没有 IIS 的条件下运行 ASMX ASP.NET MVC学习笔记 C#位运算 匹配css 样式的正则表达式 System.Web.Mvc.HtmlHelper学习及应用 正则表达式提取HTML页面的特定部分 - 林614 - 博客园 服务器应用程序不可用的解决方法 - 林614 - 博客园 最窄770px最宽1024px经典布局 调试找不到文件的解决方法 FindControl查找内容页上的某个控件 - 林614 - 博客园 遍历页面所有控件的方式
体验.NET2.0的优雅之Provider应用
林614 · 2009-06-02 · via 博客园 - 林614

在 ASP.net 2.0 的配置文件中,经常看到 Provider的影子,比如说StarterKit 中的XmlSiteMapProvider以及使用Login Controls时隐含的SqlMemberShipProvider。如此众多的Provider,我猜测它们肯定有共同的父亲!查阅了一下资料,果然不出我所料,它们的父亲是 ProviderBase。

体验.NET2.0的优雅之Provider应用

[图中的 三个点 代表直接父类的名称]

  我们以MemberShip为例,来看一下这么多的Provider是怎么被系统所使用的,以及使用它们会给我们带来什么样的好处。

体验.NET2.0的优雅之Provider应用

  LoginControls(包括登录、创建用户、修改密码等控件)是服务器控件,这些服务器控件通过MemberShipAPI 来执行相应的操作。MemberShipAPI是密封类(System.Web.Security.MemberShip类),其中定义了很多静态的方法,包括 CreateUser、DeleteUser等等,但是本身并不提供具体的实现,而是使用MemberShipProvider提供的服务。MemberShipProvider是一个抽象类,其中也定义了CreateUser、DeleteUser 等方法,SqlMemberShipProvider是它的一个实现,可以将MemberShip的数据持久化到Sql Server 2005中。 

  1.  Strategy 

  这里用到了一个非典型的策略模式(strategy)。在典型的策略模式中,Provider应该是通过构造方法注入,而在此处,MemberShip是一个静态类,它的Provider和ProviderCollection都是只读属性,因此我猜测Provider并非是由其他类注入的,而是由Provider自己通过应用上下文获取到的。策略模式的作用是将 MemberShipAPI 对具体的Provider(比如SqlMemberShipProvider)的依赖转化成了 对抽象类 MemberShipProvider 的依赖 + SqlMemberShipProvider对MemberShipProvider的依赖。这样可以保证系统的灵活性和效率。

  2.   IoC 

  这里应用的策略模式的一个附带的好处是实现了 控制反转(IoC)。通常我们设计分层应用的时候,都是自底层向上层设计,上层的组件使用下层提供的服务并直接依赖于下一层的组件。这样做的缺点是 造成底层组件很难修改,因为任意的修改(比如修改方法的功能或者名称)都可能导致上层应用崩溃。使用了策略模式模式以后,我们把MemberShipAPI和MemberShipProvider抽象类置于同一层(上层)中,底层的SqlMemberShipProvider则依赖于上一层(实现MemberShipProvider中的抽象方法)。很明显,我们将上层组件对下层组件的依赖转化成了下层组件对于上层组件的依赖,这就是控制反转。好处是给我们带来了即插即用功能---Provider是可插接的,由于Provider造成的一切系统崩溃都由 Provider 自己负责。 

  3.  Dependency Injection 

  我们可以实现自己的MemberShipProvider,比如说OracleMemberShipProvider---使用Oracle来存储MemberShip和Profile数据---只要我们继承MemberShipProvider类并覆写的部分方法即可。那么我们编写的 OracleMemberShipProvider 或者 系统自带的 SqlMemberShipProvider是如何被 MemberShipAPI 使用的呢?这里有一个重要的概念---依赖注入(Dependency Injection)。依赖注入的意思是将应用程序依赖的组件在运行时注入给应用,依赖注入一般要使用反射技术。

  依赖注入通常分为两种形式:

  构造注入:通过构造方法将组件注入

  设值注入:通过设置属性的值将组件注入

  注入过程一般由某种 IoC 容器(比如Spring)完成。在.net中,MemberShipProvider注入过程应该是由 MemberShipProvider 抽象类最终完成的(我并不知道细节)。我们要做的,仅仅是在Web.Config文件中system.web节中增加下面的节点:

<membership>
      <providers>
        <clear/>
        <add name="OracleMemberShipProvider" type="Oracle.OracleMemberShipProvider"/>
      </providers>
</membership>

  其中 type 中定义的就是 我们自定义的Provider的全名称(包括名字空间)。