﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-KiMoGiGi 技术文集-文章分类-英文文章翻译</title><link>http://www.cnitblog.com/seeyeah/category/6547.html</link><description>不在乎选择什么，而在乎坚持多久……</description><language>zh-cn</language><lastBuildDate>Tue, 27 Sep 2011 03:55:29 GMT</lastBuildDate><pubDate>Tue, 27 Sep 2011 03:55:29 GMT</pubDate><ttl>60</ttl><item><title>Silverlight 2 简介</title><link>http://www.cnitblog.com/seeyeah/articles/47670.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 05 Aug 2008 15:53:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/47670.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/47670.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/47670.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/47670.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/47670.html</trackback:ping><description><![CDATA[<p>原文<br>标题：Introducing Silverlight 2<br>作者：Christian Wenz<br>链接：<font color=#000000><a href="http://www.cnitblog.com/seeyeah/archive/2008/08/05/47669.html">http://www.cnitblog.com/seeyeah/archive/2008/08/05/47669.html</a><br></font>翻译开始时间：2008-8-5<br><br>
<hr>
<p>&nbsp;</p>
<p><strong>第一章：Silverlight 2 简介</strong></p>
<p>Silverlight 是微软一个新的基于浏览器插件，它可以为用户在web的平台上提供丰富交互应用程式的。Silverlight 2 是微软发布的第二个Silverlight 平台版本。Silverlight 2 与Silverlight 1 最大的改变来源于Silverlight 2包含了一个小型版本的.NET Framework，具备完整的.NET Framework 3.0公共语言运行时。随着为Silverlight添加了.NET，微软让.NET的开发人员更容易地重用他们现有的编程技巧，与设计师很好地合作，并快速开发&#8220;富客户端&#8221;的Web程式。<br></p>
<p align=left><br>虽然Silverlight 2把.NET Framework带到客户端去了，但它同时也可以很容易地与许多现有的网站以及终端Web平台进行整合。这说明，Silverlight将可以整合你现有的架构和程式，无论是IIS和.NET、Apache和PHP、Javascript和XHTML。Silverlight 并不是一个工具，意味着它可以独立于ASP.NET使用，应该把Silverlight划分为一项新的应用技术。<br><br>Silverlight 最吸引人的有点就是它能执行.NET语言，包括C#和VB.NET。不像一般的CLR存在于&#8220;正常&#8221;的.NET Framework模式，多个Silverlight CLR实例可以运行在一个进程中。因为如此，使用XAML文件创建的布局可以使用code-behind的代码的业务逻辑，而这些逻辑可以用任何.NET的语言来编写。<br><br>Silverlight 2 包含了一个轻量级版本的完整的.NET Framework，框架内包括常用类，扩展空间，XML WebService，网路组件以及LINQ的API。这个类库是.NET Framework 的基类库的一个子集，它使Sliverlight插件的体积会更小，便于快速下载。基于安全理由，全部Silverlight程式都运行于一个沙盒的环境中，防止执行其他平台的API，避免恶意代码的浸入。Silverlight 2同时也添加了DRM流媒体文件，这个对于某些人来说是好消息，对某些人来说是坏消息。<br><br>另外，Silverlight 2 发布了一部分WPF UI编程模型，包括支持图形、文件、多媒体以及WPF动画。Silverlight 2 December CTP版本中，并没有发布很多WPF 的UI空间，一些&#8220;盒外&#8221;控件直到beta 1仍受到限制。Silverlight 2 beta 1 release 承诺会发布更多的控件用于绑定数据。微软宣称，数据绑定仍然暂时受到一定地限制，但在未来的版本会解决这些问题。未来的Silverlight正式版，我们可以看到更多的UI控件，支持数据绑定，以及一个急切需要的布局管理器（如图1-1）。<br><br>Silverlight 1.0的架构是非常复杂，但它可以分为几个大的部分。表现层部分主管所有的用户界面，包括动画、文本呈现、以及媒体播放。整合到浏览器的插件会把这些内容呈现出来，同时可以使用Javascript DOM访问。最后，使用一些Javascript代码（推荐ASP.NET AJAX 框架），Silverlight程式可以拥有更丰富的访问服务器API，如访问WebServices。浏览器的插件可以解析标记文件和执行代码，即使在客户端没有安装.NET Framework。Silverlight 2 以后会再扩展此部分功能以及提供更多一部分 .NET Framework 的功能到Silverlight。这样你就可以用如C#的语言编写Silverlight，这些代码都会在发布前编译。<br><br></p>
<p align=center>图&nbsp;1-1. Silverlight&nbsp;框架模型<br>&nbsp;</p>
<p align=center><img height=658 alt="" src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/silverlightArt.JPG" width=500 border=0></p>
<p><br><br><br><strong>1.1 富网络应用程式</strong><br><br>什么叫做RIA网页应用程式呢？为什么我要我在网页开发中采取RIA模型？<br><br>富网络应用程式（Rich Internet Applications），简称RIA，是一个拥有传统桌面应用程式的特性以及功能的网页应用程式。一般RIA为网页客户端传输必要的用户界面，但保持大数据处理（如维护程式的状态，数据等等）留在服务器上执行。<br><br>传统的网页应用程式实现了C/S架构，一个瘦客户（浏览器）连接一个强大的服务器。一般，所有流程处理都在服务器，客户端只是简单的现实静态的HTML内容。瘦客户端最大的缺陷在于，所有的程式交互都需要通过服务器。这意味着，数据必须有服务器发出，服务器必须响应，以及页面必须在服务器响应之后在客户端进行重载。向客户端分配更多的一些处理，在客户端也能够执行一些指令，RIA能避免这种缓慢，同步处理多用户的交互。<br><br><strong>1.1.1 RIA的优点</strong><br><br>RIA一个最主要的有点就是，它可以提供一些不只是HTML的一些UI。在RIA平台上，网页应用程式不再受浏览器的限制，他们可以实现任何RIA平台可以实现的用户界面。如&#8220;拖拽行为&#8221;，平滑的哦规划，以及客户端计算。同时，这些交互有一部分是可以不需要特定的RIA平台就可以实现（如使用Ajax），但RIA可以统一跨平台。<br><br></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/47670.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-08-05 23:53 <a href="http://www.cnitblog.com/seeyeah/articles/47670.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET 3.5 Extension 文档翻译</title><link>http://www.cnitblog.com/seeyeah/articles/37812.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 17 Dec 2007 16:47:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/37812.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37812.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/37812.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37812.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37812.html</trackback:ping><description><![CDATA[<p>1、【2007-12-11】<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/37563.html">ASP.NET MVC 概述</a>&nbsp;&nbsp;&nbsp;<br><a class=ctl00_NavBar_TocTree_0 id=ctl00_NavBar_TocTreet14 href="http://quickstarts.asp.net/3-5-extensions/mvc/MVCOverview.aspx"><font color=#0000ff>ASP.NET MVC Overview</font></a><br><br>2、【2007-12-12】<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/37604.html">了解URL导航</a><br><a class=ctl00_NavBar_TocTree_0 id=ctl00_NavBar_TocTreet2 href="http://quickstarts.asp.net/3-5-extensions/mvc/mvcurlrouting.aspx"><font color=#0000ff>Understanding URL Routing</font></a><br><br>3、【2007-12-18】<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/37811.html">控制器和控制器操作</a><br><a class="ctl00_NavBar_TocTree_0 ctl00_NavBar_TocTree_1" id=ctl00_NavBar_TocTreet3 href="http://quickstarts.asp.net/3-5-extensions/mvc/MVCControllerActions.aspx">Controllers and Controller Actions</a></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-12-18 00:47 <a href="http://www.cnitblog.com/seeyeah/articles/37812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>控制器和控制器操作</title><link>http://www.cnitblog.com/seeyeah/articles/37811.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 17 Dec 2007 16:42:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/37811.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37811.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/37811.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37811.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37811.html</trackback:ping><description><![CDATA[<p>原文：<a href="http://quickstarts.asp.net/3-5-extensions/mvc/MVCControllerActions.aspx">http://quickstarts.asp.net/3-5-extensions/mvc/MVCControllerActions.aspx</a><br>
<hr>
<p>&#160;</p>
<p><strong>介绍</strong></p>
<p>ASP.NET MVC 框架直接映射URL到他们所引用的控制器类中。控制器处理引入的请求，用户的输入和交互，以及执行相应的应用程式和数据逻辑。一个典型的控制器，会呼叫一个分离开的视图为请求生成HTML标记。</p>
<p style="COLOR: red">注意：<br><span style="COLOR: red">要运行以下代码，你需要ASP.NET 3.5 Extensions预览版。你可以从 ASP.NET Web site中下载。</span></p>
<p>ASP.NET为了MVC开发提供了以下类型</p>
<ol>
    <li>&nbsp;IController - 控制器的协议接口</li>
    <li>&nbsp;Controller - 提供一般MVC处理的控制器基类</li>
</ol>
<p>控制器基类有以下职责：</p>
<p>&nbsp;1、指向对应的方法，以及验证是否有权呼叫<br>&nbsp;2、获取操作方法所需要的参数<br>&nbsp;3、执行操作方法期间，处理所有异常。<br>&nbsp;4、为呈现ASP.NET页面（视图）提供默认的WebFormViewFactory。</p>
<p><span style="COLOR: red">注意：<br>为了安全访问各种各样的控制器和控制器的操作，你可以使用PrincipalPermissionAttribute。</span></p>
<p>以下是一个控制器类的例子。控制器类包含操作方法，操作方法的参数和呈现视图的方法。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;HelloWorld.Controllers&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;SampleController&nbsp;:&nbsp;Controller&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ControllerAction]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ShowProducts(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;category)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ViewData[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">category</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;category;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RenderView(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Products</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ControllerAction]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Index()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RenderView(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">HelloWorld</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></span></div>
<p>&nbsp;</p>
<p><strong>操作方法（Action Methods）</strong></p>
<p>控制器定义许多操作方法。默认情况下，操作方法与用户的交互拥有一对一的关系。用户的交互距离包括使用URL进入浏览器，点击链接，以及提交表单。这些每个用户交互会产生出一个请求，发送到服务器。在每个情况中，请求的URL都包含MVC框架需要调用操作方法的信息。</p>
<p>举例，当用户输入URL到浏览器，MVC应用程式中定义在Global.asax的用户导航规则会分析URL，决定通往哪个控制器。然后，控制器就会定位适当的方法去处理请求。控制器包裹很多所需要的操作方法。</p>
<p>在没有使用MVC框架的ASP.NET应用程式中，用户的交互都集中在页面，以及触发、处理来自页面的事件。相反，在ASP.NET MVC应用程式中，用户交互集中在控制器和他们的操作方法。</p>
<p>默认情况下，一个请求的URL被解释的字路径包括操作名字的控制器的名称。举例，如果用户输入URL&#8220;http://contoso.com/MyWebSite/Products/Categories&#8221;，子路径为&#8220;/Products/Categories&#8221;。默认的导航规则认为&#8220;Categories&#8221;为操作的名称，以及Products控制器将会调用Categories方法处理请求。如果URL以&#8220;/Products/Detail/5&#8221;结尾，默认的导航规则认为&#8220;Detail&#8221;为操作的名称，以及Products控制器将会调用Detail方法处理请求。在URL中的5将会当Detail 方法参数传入。</p>
<p>以下例子展示控制器和控制方法：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CatalogController&nbsp;:&nbsp;Controller<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;[ControllerAction]<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Hello()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RenderView(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">HelloWorld</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<p>&nbsp;</p>
<p>所有的控制器类命名必须以Controller结尾，以及控制器的类必须继承于Controller基类。</p>
<p><strong>操作方法参数</strong></p>
<p>默认情况下，操作方法的参数是来自Request的数据集合。数据集合包括&#8220;键-值&#8221;数据，包括表单数据，查询字符串、cookie值等。</p>
<p>基于RouteData实例和表单数据，控制器基类定位所要操作的方法，如果方法包括参数，控制器基类会为方法决定相关的参数值。如果参数没有被解析出来，并且同时参数的类型是引用类型或者空的允许空的值类型，null就会被当参数传入。否则，抛出异常。TypeConverter通常用于从URL或表单数据参数中，转换正确的参数类型。</p>
<p>在控制器类的操作类中，有几种方法可以访问URL的参数。控制器的基类有一套可在操作方法方法的公开属性对象&#8220;Request&#8221;和&#8220;Response&#8221;。这些对象模拟在ASP.NET已有的 HttpRequest 和 HttpResponse 。然而，一个重要的不同点在于，控制器类的Request和Response对象是继承System.Web.IHttpRequest 和 System.Web.IHttpResponse ，代替以往的封闭类。这个接口可以更方便的创建mock对象，更方便对控制器做单元测试。</p>
<p>以下的例子展示如何在Detail方法内，使用Request对象获取查询字符串名为&#8220;id&#8221;的值。</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">[ControllerAction]<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Detail()<br>{<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Convert.ToInt32(Request[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">id</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">]);<br>}</span></div>
<p>&nbsp;</p>
<p><strong>自动映射操作方法参数</strong></p>
<p>ASP.NET MVC 框架可以为操作方法自动映射URL参数到方法的参数值。默认情况下，如果一个操作方法需要参数，MVC框架会检查请求的数据和决定HTTP请求值中是否有相同参数名称值。如果有，请求值自动会传入到操作方法。</p>
<p>下面的示例是上面例子的变体。在这个变体中，id参数被认为映射到请求的URL也名为id的数据。由于自动的映射，方法中无需拥有任何从Request获取参数的代码，因此代码更简洁。</p>
<p>你也可以使用内嵌参数值到URL中，代替以往的查询字符串用法。举例，以往使用查询字符串链接的URL如&#8220;/Products/Detail?id=3&#8221;，你可以使用类似以下的URL&#8220; /Products/Detail/3&#8221;代替。</p>
<p>默认的导航映射规则格式为/[controller]/[action]/[id]。如果URL的子路径后面接着控制器和操作方法的名称，那么参数的名称就被认为id，它会自动传入操作方法做参数。</p>
<p>MVC框架对方法参数允许可选的参数。在MVC内的可选参数，被处理为可空类型，示例，如果你有一个方法需要一个日期的查询字符串，但你想如果参数为空的时候默认为今天的日期，你可以使用以下的代码：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">[ControllerAction]<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ShowArticles(DateTime&nbsp;date)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">date.HasValue)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;&#8230;&nbsp;additional&nbsp;processing</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">}</span></div>
<p>&nbsp;</p>
<p>如果请求中包含date的参数，那么就会传递到ShowArticles 方法内。如果请求中没有包括参数值，参数将会为null，控制器无论如何也需要处理这个缺省值。</p>
<p><strong>处理未知方法</strong></p>
<p>控制器基类调用HandleUnknownAction处理了一般情况下的未知方法。默认，方法会返回HTTP 404 状态。</p>
<p>你可以为配置默认的一个方法，处理任何不予实际动作方法通讯的URL。以下例子说明一种方法，重写HandleUnknownError方法，重定向到搜索页。</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">[ControllerAction]<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000">&nbsp;HandleUnknownError(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;action)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Redirect&nbsp;to&nbsp;a&nbsp;search&nbsp;page&nbsp;where&nbsp;the&nbsp;unknown&nbsp;action&nbsp;is&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;the&nbsp;search&nbsp;query.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(ShouldShowSearch(action)&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RedirectToAction(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">search</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;{&nbsp;query&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;action&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">.HandleUnknownError(action);<br>}<br><br></span></div>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-12-18 00:42 <a href="http://www.cnitblog.com/seeyeah/articles/37811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>了解URL导航</title><link>http://www.cnitblog.com/seeyeah/articles/37604.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 11 Dec 2007 16:00:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/37604.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37604.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/37604.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37604.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37604.html</trackback:ping><description><![CDATA[<p>原文：<a href="http://quickstarts.asp.net/3-5-extensions/mvc/mvcurlrouting.aspx">http://quickstarts.asp.net/3-5-extensions/mvc/mvcurlrouting.aspx</a><br>
<hr>
<br><strong>简介</strong>
<p>&#160;</p>
<p>在ASP.NET应用程式，引入的URL请求一般都会直接映射到.aspx文件。一个不使用URL重写的标准ASP.NET应用程式，一个&#8220; /InterestingNews.aspx&#8221;的请求将会映射到物理文件&#8220;InterestingNews.aspx&#8221;，其包含的代码和标记就会输出浏览器相应的响应。</p>
<p>ASP.NET MVC框架包括一个URL导航引擎，它可以映射引入的请求到控制器的类和动作（动作部分通常是需要的，但并不是必要，它协作于控制器类的方法）。URL导航引擎可以分析你在URL所定义的变量，自动以方法参数的形式传入控制器的动作。</p>
<p>ASP.NET MVC 模板在Global.asax文件的Application类包含了一个预先配置好的URL导航规则。这默认的配置能让你无需为你的程序显示配置导航规则就可以开始编写ASP.NET MVC 应用程式。换句话说，你可以使用默认的命名URL映射协定。</p>
<p><strong>默认的命名URL映射协定</strong></p>
<p>默认的命名协定映射引入的HTTP请求的URL路径的一部分到对应的控制器。映射是基于URL对应的控制器名为&#8220;UrlPathController&#8221;。举例，一个URL包含路径&#8220;/Products/&#8221;映射的控制器名为&#8220;ProductsController&#8221;。</p>
<p>控制器类必须实现System.Web.MVC.IController接口，且名称必须以&#8220;Controller&#8221;结尾。最简单实现控制器的方法就是创建一个继承于System.Web.MVC.Controller的类。你可以向控制器添加方法，方法要标记上ControllerAction特性，让默认的URL导航处理器能调用到对应的方法。如果你遵循这些规则，你就能让MVC框架运行URL导航，以及选择公开你标记了特性的行为方法。</p>
<p>当控制器和导航规则被定义后，ASP.NET MVC框架执行控制器的类，去处理全部以控制器类名称开头的URL请求。如&#8220;/Products/&#8221;URL。默认的，一个向服务器的请求大致类似以下这种形式：</p>
<p><a href="http://site/application/controller/action[parameters]note"><strong>http://site/application/controller/action[parameters]note</strong></a><strong> </strong><br><br>这里所描述的URL导航是为新的ASP.NET MVC应用程式提供的一种默认的模式。当然，你也可以使用不同的模式，创建自定义的URL导航。</p>
<p>如果需要的话，控制器可以调用基于控制器URL的其他部分，如/Products/Categories, /Products/List/Beverages, 和/Products/Detail/3。</p>
<p>请求导航是通过UrlRoutingModule和MvcHandler的HTTP处理实现的。MvcHandler决定哪个控制器被调用。URL的行为部分表示控制器哪个方法被呼叫。行为与业务逻辑合并执行模型的交互。这些行为的结果会被指定的视图所呈现。<br><br><strong>URL到控制器的映射<br></strong><br>ASP.NET MVC框架使用的默认规则映射控制器和URL，规则包括、行为的名称以及任何行为的参数。以下例子演示URL的语法：</p>
<p><a href="http://domain/site/controller-name/action-method-name?parameters">http://domain/site/controller-name/action-method-name?parameters</a> </p>
<p><a href="http://domain/site/controller-name.mvc/action-method-name?parameters">http://domain/site/controller-name.mvc/action-method-name?parameters</a> </p>
<p><strong style="COLOR: red">注意：<br>在IIS6.0中，.mvc扩展名是必需的。</strong></p>
<p>下面的例子展示一个具体的URL到控制器的映射：</p>
<p><a href="http://www.contoso.com/Shopping/Store/ShowCategory?id=5">http://www.contoso.com/Shopping/Store/ShowCategory?id=5</a> </p>
<p>一些开发者喜欢更加易读的URL语法，如下所示：<br><a href="http://www.contoso.com/Shopping/Store/beverages/">http://www.contoso.com/Shopping/Store/beverages/</a></p>
<p>ASP.NET MVC 框架允许你定义不同的映射设计和自定义URL语法。你可以为你的程式做一个映射设计，定义更有意义的URL，令他支持不同的搜索引擎模型。</p>
<p>举例，在默认的URL映射的情况，下面的URL应该执行ShowCategory方法且附带的参数为5，然后获取Northwind数据库显示Beverages目录。</p>
<p><a href="http://www.contoso.com/Shopping/Store/ShowCategory?id=5">http://www.contoso.com/Shopping/Store/ShowCategory?id=5</a> </p>
<p>一个自定义的架构可以使用以下URL定制语法，提供相同的数据呈现：<br><a href="http://www.contoso.com/Shopping/Store/products/beverages">http://www.contoso.com/Shopping/Store/products/beverages</a> </p>
<p><strong>定义RouteTable, Routes, 和 RouteData</strong></p>
<p>你可以在Global.asax文件的Application_Start时间内定义URL导航的映射。下面的例子演示了一般Global.asax文件包括添加到RouteTable对象的Route对象实例。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Global&nbsp;:&nbsp;System.Web.HttpApplication&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Application_Start(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;EventArgs&nbsp;e)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RouteTable.Routes.Add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Route&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Url&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">[controller]/[action]/[id]</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Defaults&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;{&nbsp;action&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Index</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RouteHandler&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(MvcRouteHandler)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></span></div>
<p>RouteTable公开Routes collection，包含Route对象集合。每次MvcModule的请求都会执行RouteTable。MvcModule 对象查询每一个在集合中的Route对象，查看URL是否有符合Route对象的映射。</p>
<p><strong style="COLOR: red">注意<br>映射的逻辑定义在MvcModule，并且不可自定义。</strong></p>
<p>当URL找到相应的Route映射时，Route就会产生一个IRouteHandler实例。IRouteHandler 实例定义了Route的HTTP Handler。这个Route 处理为请求创建了IHttpHandler 。IRouteHandler 的执行方法被呼叫，并设置到当前的上下文。</p>
<p>如果没有导航相对应，RouteTable 中没有定义相应的Route 。相应处理就直接指向ASP.NET page, Web service, 或其他ASP.NET 终端。</p>
<p>Route 在Routes 集合中的排序是有意义的。Route 对应搜索是从第一个到最后一个的顺序查询。当对应的Route 找到之后，搜索就会停止。默认的route一般放在最后面。</p>
<p>对于IIS7.0,不需要后缀名。下面的代码例子展示创建一个没有后缀名的URL控制器映射的RouteTable 集合。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">RouteTable.Add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Route(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/[controller]/[action]/[id]</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;{&nbsp;action&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Index</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;},&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(MvcRouteHandler));</span></div>
<p>对于IIS 6.0，URL的名称必须包含mvc的后缀名。下面的代码例子展示创建有后缀名的URL控制器映射的RouteTable 集合。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">RouteTable.Add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Route(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/[controller].mvc/[action]/[id]</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;{&nbsp;action&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Index</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;},&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(MvcRouteHandler));</span></div>
<p>&nbsp;</p>
<p>基于前文所提的URL，以下与其对应RouteData所通讯的值。<br>
<table class=authoredTable cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td>
            <p>URL</p>
            </td>
            <td>
            <p>RouteData object values</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>/domain/site/blog</p>
            </td>
            <td>
            <p>Controller="blog", action="Index", id=null</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>/domain/site/blog/ShowPosts</p>
            </td>
            <td>
            <p>Controller="blog", action="ShowPosts", id=null</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>/domain/site/blog/ShowPosts/123&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
            </td>
            <td>
            <p>Controller="blog", action="ShowPosts", id="123"</p>
            </td>
        </tr>
    </tbody>
</table>
<br>当route找到对应时，UrlRoutingModule产生以&#8220;键-值&#8221;成对地产生以上数据RouteData实例。。</p>
<p>如果引入的URL没有route对应，相应处理就直接指向ASP.NET page, Web service, 或其他ASP.NET 终端。</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37604.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-12-12 00:00 <a href="http://www.cnitblog.com/seeyeah/articles/37604.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET MVC 概述</title><link>http://www.cnitblog.com/seeyeah/articles/37563.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 10 Dec 2007 17:06:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/37563.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37563.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/37563.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37563.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37563.html</trackback:ping><description><![CDATA[<p><strong>介绍</strong></p>
<p>模型-视图-控制器架构模式把一个应用程式分离成三个主要组件：模型、视图和控制器。ASP.NET MVC框架为ASP.NET使用Web-Forms模式开发基于MVC的网页应用程序提供了一个选择。ASP.NET MVC 框架是一个轻量级；表现层框架提供高度可测试；以及（像现在的基于Web-Froms的应用程式）整合了ASP.NET的现有特性，如Master Pages和基于Membership的验证。MVC 框架被定义在System.Web.Mvc命名空间，他的基础部分建立在System.Web 命名空间中。</p>
<p>MVC是一个许多开发者都非常熟悉的标准设计模式。某些类型的网页应用程式将会从MVC框架获取好处。其他的可以继续使用传统的基于WebForms和postback的ASP.NET应用程式模式。也有结合两种框架的Web程式，当然也有两者都不使用的。</p>
<p>MVC框架不使用ViewState和Forms。对于页面重视控件展现多于行为的应用程式，提供了一个理想的方案。</p>
<p>另一方面，基于表单的应用程式支持事件模型，在HTTP协议上可以保持状态，对于开发网页应用程式是非常有好处的。基于网页表单的应用程式提供了许多时间来支持许许多多的服务器控件。MVC使用Front Controller模式，使你在设计应用程式的时候可以完全分离表现层、业务逻辑以及数据访问，使控件按流程支持丰富的架构。网页表单程式使用 page-controller 模式，为个别页面分别添加功能。这两种可以按需混合使用。</p>
<p>MVC组件如下：</p>
<p>&nbsp;1、Models - Model对象是应用程式负责实现领域逻辑的部分。通常，Model对象可以在数据库获取或存储Model状态。举例，Product 对象从数据库获取信息，操作后，写入更新后的信息到SQL数据库的Products表。</p>
<p><span style="COLOR: red">&nbsp;注意：在一些更小型的程式来说，model通常是是概念上分离多于物理上的分离。举例，如果程式只是读取DataSet，并把它传送到view，程式并没有物理上的Model层和所关联的类。这种情况下，DataSet就担当着Model的角色。</span></p>
<p><br>&nbsp;2、Views - 视图是专职表现程式用户界面(UI)的组建。典型地说，UI从Model数据创建出来的。举例，现在有一个修改Products表的页面，它是根据当前Product对象的状态显示对应的文本框(textbox)、下拉框(dropdowlist)和勾选框(checkbox)。</p>
<p>&nbsp;3、Controllers - 控制器是负责用户交互，维护Model以及最终选择哪一个view去呈现数据UI的组件。在MVC应用程式中，视图只显示信息，控制器负责处理和回应用户的输入和交互。举例，控制器处理查询字符串(query-string )的值，传递这些值给model，然后就可以使用这些值实现轮流查询数据库。</p>
<p>MVC框架助你创建各个分离层的应用程式（输入逻辑、业务逻辑和UI逻辑），同时为各个元素提供了解耦。这种模式具体指定每一类的逻辑应该存在程式的哪里。UI逻辑是属于视图的。输入逻辑属于控制器。业务逻辑属于模型的。这样的分离有助于你管理建立复杂的应用程式，因为可以让你在一个时间内只关注程式的某一部分的实现。举例，你完全可以只关注视图而无需依靠业务层。</p>
<p>在管理复杂程式方面，MVC模式比传统的ASP.NET网页应用程式提供了更容易测试的程式。举例，在传统的ASP.NET网页应用程式，一个类就负责输出和输入两部分。编写传统ASP.NET网页应用程式的自动化测试是非常复杂的，因为要测试一个页面，你必须实例化一个页面的类和它的全部子控件，以及应用程式中所依赖的所有类。因为运行一个页面都需要许多类初始化，编写程式其中一部分的单独测试代码是非常困难的。而且，测试传统ASP.NET网页应用程式需要Web服务器。MVC 框架为组件和沉重的UI解耦，这样就有可能从框架其他部分分别为各组件进行测试。</p>
<p>解耦了MVC三个主要组件也促进了平行开发。举例，一个开发人员在view开发，第二个可同时在控制器业务层开发，第三个就关注业务逻辑模型。</p>
<p><strong>ASP.NET MVC框架特性</strong></p>
<p>ASP.NET MVC 框架提供以下特性：</p>
<p>1、分离程式的任务（输入逻辑、业务逻辑以及UI逻辑），可测试，以及默认测试驱动开发模式。在MVC框架内，所有核心协议都基于接口，便于使用mock数据进行测试。 你可以在ASP.NET进程中不运行控制器的情况下，进行快速和灵活的单元测试。你可以使用任何一个兼容.NET框架的单元测试框架。</p>
<p>2、框架具有扩展性和可插拔性。ASP.NET MVC 组件非常容易被替代或自定义。你可以组装你自定义的视图引擎，URL转向规则，action方法参数序列化，以及其它组件。ASP.NET MVC 框架提供了现成的依赖注入和IOC容器模型。</p>
<p>3、强大的URL映射，为你的应用程式提供通熟易懂、可搜索的链接。链接不必一定要文件扩展名，MVC框架支持URL&#8220;命名模式&#8221;，在SEO（search engine optimization ）和REST（representational state transfer ）定位中也工作得很好。举例，你可以映射&#8220;/products/edit/4&#8221;到你项目中的ProductsController类修改动作；或者映射&#8220;/Blogs/YourSite/10-10-2007/SomeTopic/&#8221;链接到BlogEngineController 类的DisplayPost 动作。URLs 无需与文件名称有关联。</p>
<p>4、在现有的ASP.NET页面（.aspx文件）、用户控件（.ascx文件）支持标记语言以及支持Master页面(.master文件)作为视图模板。你可以在使用ASP.NET MVC框架的同时使用现有的ASP.NET特性，如内嵌Master Page，嵌入表达式（&lt;%=%&gt;），声明式服务器控件，模板，数据绑定，本地化，等等。</p>
<p>5、支持现有的ASP.NET特性。ASP.NET MVC 可以使用特性如Forms和Windows的验证，URL验证，membership和roles，输出和数据缓存，Session和状态描述管理，监控健康状态，配置系统，provider的扩展架构，以及ASP.NET的其它领域。</p>
<p><strong>后台</strong></p>
<p>在ASP.NET网页，URL可以映射存在硬盘上的文件（如.aspx文件）。这些.aspx文件包括代码和标记，用于回应请求。</p>
<p>ASP.NET MVC框架用不同的方法映射链接到服务器代码。框架直接映射URL到控制器的类，代替映射URL到ASP.NET页面或使用handlers。控制器类处理引入的请求，如用户输入和用户交互，基于用户的输入以及执行相应的程式和数据逻辑。一般来说每一个控制器类调用一个视图组件，从而视图组件产生HTML输出。</p>
<p>ASP.NET MVC框架分离了Model，视图和控制器组件。模型组间一般使用在数据库的持久数据维护状态。控制器选择相应的视图组件，呈现适当的UI。大部分情况，ASP.NET MVC框架使用ASP.NET页面（.aspx）、用户控件（.ascx）、Master页面(.master)呈现页面到浏览器。控制器组件在控制器中定位适当的动作，使用动作方法的参数获得相应值，处理执行动作期间的所有异常，以及呈现所请求的视图。每一套的组件分别存在于MVC网页应用程式项目子目录。</p>
<p><strong>URL映射</strong></p>
<p>ASP.NET MVC框架包括一个URL映射的引擎，它提供了灵活的映射URL到控制器的类中。你可以使用映射引擎定义页面链接导航规则，ASP.NET MVC 框架会估计引进的URL和选择对应的控制器执行。你也可以让导航引擎自动添加变量定义到URL，ASP.NET MVC框架就会传递这些参数到控制器。</p>
<p><strong>MVC 框架和Postbacks</strong></p>
<p>ASP.NET MVC框架不会使用传统的ASP.NET postback模型来与服务器做交互。替代的是，所有的终端用户交互都由控制器控制。这样可分开维护UI逻辑和业务逻辑部分，有助于测试。这样导致的结果就是，ASP.NET 的视图状态、页面的生存周期事件都没有整个到基于MVC的视图当中。</p>
<p><strong>创建ASP.NET MVC应用程式</strong></p>
<p>ASP.NET MVC框架包括VS项目模板，让你创建支持MVC模式的网页应用程式。MVC Web Application 模板创建一个由子目录、模板、配置文件配置的网页应用程式，它们去全部都是ASP.NET MVC 程式所需要的部分。</p>
<p>默认情况下，当你使用模板创建新的网页应用程式的时候，Visual Studio 会创建一个解决方案和添加两个项目到解决方案。第一个项目就是实现你程式的网站项目，另外一个就是提供给你编写你的MVC组件单元测试的测试项目。</p>
<p>你可以使用任何兼容.NET框架的单元测试框架来测试ASP.NET MVC应用程式。Visual Studio 2008 Professional 包含了内置支持MSTest的测试项目。</p>
<p><strong>了解MVC网页程式结构</strong></p>
<p>当你创建ASP.NET MVC应用程式项目时，MVC组件基于以下的项目文件夹做分割：</p>
<p>1、视图文件夹。推荐视图文件夹内只存放视图。视图使用 .aspx, .ascx, 和 .master文件，当然其他任何文件也可以关联呈现视图。视图文件夹根据每一个控制器类的前缀而命名（如有Controller为&#8220;ProductsController&#8221;，View就有对应文件夹&#8220;Products&#8221;）。当加载视图时，默认地，ASP.NET MVC 框架会在Views\controllerName文件夹内寻找所请求的aspx文件视图名称。有一个叫&#8220;Common&#8221;的文件夹跟任何控制器没有关系。这个文件夹可用于定位存放master page、脚本、CSS文件以及呈现视图时要使用的其他文件。</p>
<p>2、控制器文件夹。推荐控制器文件夹内只存放控制器。</p>
<p>3、模型文件夹。推荐模型文件夹内只存放模型。一般来说，这里包含的代码就是定义与交互数据库的逻辑。</p>
<p>4、App_Data。数据的物理存储。这个文件夹与基于表单的ASP.NET网页应用程式作用相同。</p>
<p>在以上的文件夹之外，MVC还是用了以下的元素：</p>
<p>1、Global.asax 和 Global.asax.cs (在Visual Basic为 Global.asax.vb)。导航是在Application_Start 方法初始化的。以下示例展示Global.asax文件包含了默认的导航逻辑。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Global&nbsp;:&nbsp;System.Web.HttpApplication&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Application_Start(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;EventArgs&nbsp;e)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RouteTable.Routes.Add(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Route&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Url&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">[controller]/[action]/[id]</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Defaults&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;{&nbsp;action&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Index</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RouteHandler&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(MvcRouteHandler)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<p>2、配置。MVC要在Web.Config注册HTTP handlers 和 HTTP modules。httpHandlers段注册MvcHandler类，用来导航请求到对应的控制器。以下示例显示httpHandlers段在ASP.NET MVC 的配置。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">httpHandlers</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">add&nbsp;</span><span style="COLOR: #ff0000">verb</span><span style="COLOR: #0000ff">="*"</span><span style="COLOR: #ff0000">&nbsp;path</span><span style="COLOR: #0000ff">="*.mvc"</span><span style="COLOR: #ff0000">&nbsp;type</span><span style="COLOR: #0000ff">="System.Web.Mvc.MvcHandler,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;System.Web.Extensions,&nbsp;Version=3.6.0.0,&nbsp;Culture=neutral,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;PublicKeyToken=31BF3856AD364E35"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">httpHandlers</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span></div>
<p><br>httpModules 段要注册UrlRoutingModule 类，强制URL导航到相应的处理者。这个入口允许程式在同一个项目是否使用MVC Handlers。以下示例显示httpModules段在ASP.NET MVC 的配置。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">httpModules</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">add&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="UrlRoutingModule"</span><span style="COLOR: #ff0000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;type</span><span style="COLOR: #0000ff">="System.Web.Mvc.UrlRoutingModule,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;System.Web.Extensions,&nbsp;Version=3.6.0.0,&nbsp;Culture=neutral,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;PublicKeyToken=31BF3856AD364E35"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">httpModules</span><span style="COLOR: #0000ff">&gt;</span></div>
<p>当你创建MVC程式的时候，方案已包含了测试项目。你可以使用MVC模板创建测试和创建mock来实现内置的接口。</p>
<p><strong>了解MVC项目执行进程</strong></p>
<p>使用MVC框架建立对网页的请求，通过 ASP.NET HTTP module 和 an HTTP handler进行导航。</p>
<p><span style="COLOR: red">注意<br>当MVC项目在IIS7运行的时候，无需注册任何文件后缀名。然而，在IIS6，处理器需要你映射.mvc文件后缀名到ASP.NET ISAPI DLL。</span></p>
<p>The module 和 handler 是指向 ASP.NET MVC框架的入口，会做以下动作：</p>
<p>1、在MVC项目中选择适当的控制器。<br>2、包含具体制定的控制器实例<br>3、呼叫控制器的方法</p>
<p>以下表格列出MVC项目执行场景：</p>
<p><br>
<table class=authoredTable cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td>
            <p><strong>Stage</strong></p>
            </td>
            <td>
            <p><strong>Details</strong></p>
            </td>
        </tr>
        <tr>
            <td>
            <p>初次请求</p>
            </td>
            <td>
            <p>在Gloabal.asax文件内，导向添加的<span class=keyword>RouteTable</span> 对象。</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>导向</p>
            </td>
            <td>
            <p><span class=keyword>UrlRoutingModule</span> 模块从在<span class=keyword>RouteTable实例中</span>对应的<span class=keyword>Route</span> 对象创建<span class=keyword>RouteData。<br></span>Route data 决定哪个控制器被请求，并且哪个方法被调用。</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>映射到控制器</p>
            </td>
            <td>
            <p><span class=keyword>MvcRouteHandler</span> handler&nbsp;根据<span class=keyword>RouteData实例中的数据，尝试创建控制器的类型。</span></p>
            </td>
        </tr>
        <tr>
            <td>
            <p>调用控制器创建者</p>
            </td>
            <td>
            <p>处理器调用<span class=keyword>ControllerBuilder</span> 类的静态方法<span class=keyword>CreateController</span> ，包含在<span class=keyword>IController</span> 实例。<br><br>如果没有返回<span class=keyword>IController</span> 实例，handler 会指定服务器返回HTTP500的错误。 </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>创建控制器</p>
            </td>
            <td>
            <p><span class=keyword>ControllerBuilder</span> 实例世界创建新的控制器实例，或者使用<span class=keyword>IControllerFactory</span> 对象创建控制器。</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>执行控制器</p>
            </td>
            <td>
            <p><span class=keyword>MvcHandler</span> 实例被添加到上下文，然后调用控制器的方法。</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-12-11 01:06 <a href="http://www.cnitblog.com/seeyeah/articles/37563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[2007-12-1]异步调用方法 </title><link>http://www.cnitblog.com/seeyeah/articles/36862.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sun, 25 Nov 2007 13:32:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36862.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36862.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36862.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36862.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36862.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文标题：Asynchronous Method Invocation作者：mikeperetz链接：http://www.codeproject.com/csharp/AsyncMethodInvocation.asp 翻译开始时间：2007-11-27&nbsp;简介在此篇文章，我将要解释异步方法的调用以及如何使用它们。在玩过委托、线程和异步调用一段时间后，如果我不分享一下我在这些...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/articles/36862.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/36862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-25 21:32 <a href="http://www.cnitblog.com/seeyeah/articles/36862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[2007-11-26]使用依赖注入解耦</title><link>http://www.cnitblog.com/seeyeah/articles/36861.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sun, 25 Nov 2007 13:30:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36861.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36861.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36861.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36861.html</trackback:ping><description><![CDATA[<p>原文<br>标题：Dependency Injection for Loose Coupling<br>作者：<a href="http://www.codeproject.com/script/Articles/list_articles.asp?userid=2797038"><strong><u><font color=#0000ff>Billy McCafferty</font></u></strong></a>. <br>链接：<a href="http://www.codeproject.com/cs/design/DependencyInjection.asp">http://www.codeproject.com/cs/design/DependencyInjection.asp</a><br>翻译开始时间：2007-11-25<br>
<hr>
<br>
<p><span style="COLOR: #993300"><strong style="FONT-SIZE: 18pt">简介</strong></span></p>
<p>在面向对象的设计中，有一个重要的原则 -- &#8220;解耦&#8221;。简单说（loosely），不是一语双关（这里使用loosely和loose coupling没有任何关系，只是语法相似），&#8220;解耦&#8221;的意思就是说，一个对象工作时需要依赖一些对象，而这些依赖应该越少越好。此外，当可能的时候，对象依赖的应该是接口，而不是具体具体化的类。(具体得累就是用关键字&#8220;new&#8221;常见的实例。）&#8220;解耦&#8221;能促进更好的重用、增加可维护性，并且允许你能很容易地提供&#8220;模仿&#8221;(Mock)对象替代昂贵的服务，例如端口交流器（socket-communicator）。</p>
<p>&#8220;依赖注入&#8221;（"Dependency Injection"，简称DI），和更神秘的概念&#8220;控制反转&#8221;（Inversion of Control" ，简称IoC），是一项提供解耦方式的技术。主要有两个实现DI的的方式：构造函数注入（constructor injection）和设置方法注入（setter injection）。显然，在某些点上，必须要&#8220;某个东西&#8221;有创建具体的类的职责，以提供对象，可供注入到另一个对象。这个注入者（injector）可以为一个父类，我们称为&#8220;依赖注入控制端&#8221;（DI controller）；或者能被一个&#8220;依赖注入容器&#8221;（DI container）在外部处理实现。以上就是几个主要的使用依赖注入的概观。</p>
<p><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>构造函数注入（Constructor Injection）</strong></span></p>
<p>使用构造函数参数传递对象依赖的DI（依赖注入以下都简称为DI）技术，就是构造函数注入。以下的这个例子，包括一个类，Customer,它暴露了一个方法去获得每份销售订单所属客户的详细日期信息。因此，Customer类需要一个数据访问类与数据库关联。假设，现在有一个类orderDao （全名"order data-access object"），实现接口IOrderDao.有一种方法，Customer类可以执行以下代码获得依赖：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">IOrderDao&nbsp;orderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;OrderDao();</span></div>
<p>这样做，有2个主要的缺点。</p>
<p>1、在本地实例化OrderDao,就抵消了在一开始使用接口的好处；并且<br>2、OrderDao不能轻易地被用来测试的Mock对象替换。（Mock对象会稍后讨论）</p>
<p>上述的例子应该如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Customer&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Customer(IOrderDao&nbsp;orderDao)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(orderDao&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArgumentNullException(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">orderDao&nbsp;may&nbsp;not&nbsp;be&nbsp;null</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.orderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;orderDao;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;IList&nbsp;GetOrdersPlacedOn(DateTime&nbsp;date)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cnitblog.com/Images/dot.gif">&nbsp;code&nbsp;that&nbsp;uses&nbsp;the&nbsp;orderDao&nbsp;member<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get&nbsp;orders&nbsp;from&nbsp;the&nbsp;datasource&nbsp;<img src="http://www.cnitblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;IOrderDao&nbsp;orderDao;<br>}<br><br></span></div>
<p>在以上例子中，注意构造函数接受的是一个接口；不是接受一个具体的类。同时，注意如果orderDao参数为null的时候，抛出了异常。这样强调了获取依赖对象的合法性。以我的观点，构造函数注入，它最好的机制在于提供了对象必须的依赖。让开发这清楚地知道，调用Customer，在它能正常执行之前，需要提供哪些它所依赖的对象。然而，考虑以下状况&#8230;&#8230;假设你的类有十个方法都不需要依赖，但你加一个方法需要依赖于IOrderDao。你的确可以改动构造函数，使用构造函数注入，但这会强迫你在所有地方改变原有的构造函数调用。当然，你也可以选择新加一个构造函数老获取依赖，但怎么样能让开发简单地知道使用哪个构造函数呢？最后，如果这个依赖的创建是很昂贵的，为什么要创建它并传入构造函数类，然而却很少使用它？设置方法注入（setter injection）可以在这种情况下使用。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>设置方法注入（Setter Injection）</strong></span></p>
<p>设置方法注入不会强迫传递依赖对象到构造函数中。取而代之，是通过对象暴露出来的公有方法设置依赖。这样做法的动机主要包括以下几点：</p>
<p>&nbsp;1、在继承的类中，无需修改构造函数，就可实现依赖注入，而且；<br>&nbsp;2、允许尽可能晚的，而且在需要的情况下，才创建某些昂贵的资源或服务。</p>
<p>以下代码使用设置方法注入替代刚才的构造函数注入：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Customer&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Customer()&nbsp;{}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;IOrderDao&nbsp;OrderDao&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;{&nbsp;orderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(orderDao&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;MemberAccessException(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">orderDao</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;has&nbsp;not&nbsp;been&nbsp;initialized</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;orderDao;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;IList&nbsp;GetOrdersPlacedOn(DateTime&nbsp;date)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cnitblog.com/Images/dot.gif">&nbsp;code&nbsp;that&nbsp;uses&nbsp;the&nbsp;OrderDao&nbsp;public<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cnitblog.com/Images/dot.gif">&nbsp;property&nbsp;to&nbsp;get&nbsp;orders&nbsp;from&nbsp;the&nbsp;datasource&nbsp;<img src="http://www.cnitblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Should&nbsp;not&nbsp;be&nbsp;called&nbsp;directly;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;use&nbsp;the&nbsp;public&nbsp;property&nbsp;instead</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;IOrderDao&nbsp;orderDao;<br>}</span></div>
<p><br>在以上的例子中，构造函数没有参数。替代的是，在调用对象时，执行GetOrdersPlacedOn方法之前需要先设置IOrderDao依赖。构造函数注入而言，当依赖一开始没有注入时，程式立刻会抛出异常。例如，创建对象之前。对于设置方法注入而言，异常要到某个方法要使用依赖时才会抛出。还有注意的是，GetOrdersPlacedOn方法使用的是OrderDao属性，而不是直接使用私有的orderDao变量。这样，属性的getter方法才有机会验证依赖对象是否初始化。</p>
<p>使用设置方法注入替换构造函数注入时要谨慎，因为：</p>
<p>1、至少到&#8220;has not been initialized&#8221;抛出异常的时候，开发人员要清楚哪些依赖是需要的；<br>2、加大了一点难度去跟踪异常的来源和原因。</p>
<p>虽然如此，设置方法注入能提供新方法的同时尽量少改动原有的代码；如果所依赖的对象创建时非常昂贵或很困难的，此注入方法能提供性能上的加速。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>注入器（The Injectors）</strong></span><br><br>紧接着，下一个问题就是，什么东西能创建出依赖对象，注入到&#8220;被注入者&#8221;？有2个试点那个的地方以供创建这些逻辑：控制器和容器。<br><br><strong>DI 控制器（DI Controllers）<br><br></strong>DI控制器的创建步骤是容易理解和实现的。在一个适当分层的架构中，一个应用程式拥有不同的层处理逻辑。最简单的分层通常包括与数据库通讯的数据层，负责显示UI的表现层，履行业务逻辑的区域逻辑层。即使没有很好地定义,&#8220;控制器&#8221;层总是存在，为了定位UI事件到区域和数据层，反之亦然。举个例子，在ASP.NET中，code-behind页面扮演基础控制层。还有更多形式化的控制层存在：Java中的Struts和Spring;.NET的Front Controller 和 Spring .NET 。全部这些实现都遵守着MVC（Model-View-Controller ）模式形态。不管你用什么作为你的控制器，这个控制器就是实现依赖注入配件的适合所在；这里是实例化、注入依赖对象的地方。接着两个例子演示使用控制器实现DI。第一个例子是一个示例性的例子 &#8220;生成注入代码&#8221;-- 你要自我完成配置。第二个是&#8220;测试代码&#8221;示例 -- 用来测试应用程式的，但没有完整，并不一定需要一个真实的数据库。<br><br>控制器代码实现依赖注入（如，ASP.NET code-behind页面）：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cnitblog.com/Images/dot.gif">&nbsp;code&nbsp;performed&nbsp;when&nbsp;the&nbsp;controller&nbsp;is&nbsp;loaded&nbsp;<img src="http://www.cnitblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>IOrderDao&nbsp;orderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;OrderDao();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Using&nbsp;Setter&nbsp;Injection&nbsp;on&nbsp;a&nbsp;pre-existing&nbsp;customer</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">someCustomer.OrderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;orderDao;<br>IList&nbsp;ordersPlacedToday&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;someCustomer.GetOrdersPlacedOn(DateTime.Now);<br><br><img src="http://www.cnitblog.com/Images/dot.gif"></span></div>
<br>单元测试的依赖注入：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">IOrderDao&nbsp;orderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;MockOrderDao();<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Using&nbsp;Setter&nbsp;Injection&nbsp;on&nbsp;a&nbsp;pre-existing&nbsp;customer</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">someCustomer.OrderDao&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;orderDao;<br>IList&nbsp;ordersPlacedToday&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;someCustomer.GetOrdersPlacedOn(DateTime.Now);</span></div>
<p><br>使用DI控制器注入以来的一个主要好处就是它非常直接、容易地指出创建在何处发生。缺点就是仍然在某处存在依赖的硬编码；即使硬编码处于经常需要变动的位置。另一个缺点在于，现在DI控制器无法轻易地使用mock对象进行单元测试。（但我承认，某些强大的工具如<a href="http://www.typemock.com/">TypeMock</a>，可以在任何情况下生成注入mock对象。但是，类似TypeMock的工具应该只是用在绝对必要的情况下，因为他们引导你不使用&#8220;面对接口编程&#8221;的习惯。事实上，我推荐在非常困难得测试才使用。）<br><br>在ASP.NET，我更喜欢使用Model-View-Presenter (MVP)模式，ASP.NET code-behind 页面创建依赖，通过构造函数注入到presenter。另外，我使用用户控件作为模式的View部分，因此ASP.NET code-behind在用户控件（View视图）和他们的Presenter之间，纯粹扮演着MVP&#8220;依赖初始化&#8221;的角色。</p>
<p>另一个实现注入的方式，就是使用应用程式容器&#8230;&#8230;<br><br><strong>DI容器（DI Containers）<br></strong></p>
<p>控制反转（Inversion-of-Control）/依赖注入（Dependency-Injection）容器，无论哪一部分细节的事件触发，都可以监测应用程式、注入依赖。举例，当Customer实例创建时，他可以自动被注入所需要的依赖。首先，这个是非常奇怪的一个概念，但这对于管理大型应用程式多个服务依赖非常有效。不同的容器拥有它们各自的机制，提供管理依赖注入的设置。</p>
<p>Spring .NET允许你使用XML文件定义依赖注入。以下例子，Spring.NET XML使用设置方法注入，为ASPX code-behind page提供数据访问对象的依赖：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">spring</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">context&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="Spring.Context.Support.WebApplicationContext,&nbsp;Spring.Web"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">resource&nbsp;</span><span style="COLOR: #ff0000">uri</span><span style="COLOR: #0000ff">="config://spring/objects"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">context</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">objects&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="http://www.springframework.net"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;Data&nbsp;Access&nbsp;Object&nbsp;that&nbsp;will&nbsp;be&nbsp;injected&nbsp;into&nbsp;ASPX&nbsp;page&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">object&nbsp;</span><span style="COLOR: #ff0000">id</span><span style="COLOR: #0000ff">="daoFactory"</span><span style="COLOR: #ff0000">&nbsp;type</span><span style="COLOR: #0000ff">="MyApp.Data.DaoFactory,&nbsp;MyApp.Data"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">object&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="ViewDetails.aspx"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="DaoFactory"</span><span style="COLOR: #ff0000">&nbsp;&nbsp;ref</span><span style="COLOR: #0000ff">="daoFactory"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">object</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">objects</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">spring</span><span style="COLOR: #0000ff">&gt;</span></div>
<p><br>ASPX code-behind 简单地公开一个名为DaoFactory的属性，当页面被呼叫时，来获取所需要的依赖。到Spring .NET's website 可以获取更详细信息和示例。对于Java开发者，肯定参观过Spring's website。</p>
<p>有许多其他的容器，有些根本并不需要很多的XML管理（你有时会看到令你畏惧的500行壮观XML文件）。对于Java开发者，看看<a href="http://www.picocontainer.org/4.1+Container+Comparison">Container Comparison</a>，有很好的对比观点。对于.net开发者，现在的选择比较少（可能是个好事？）。看看一些开源的建议<a href="http://csharp-source.net/open-source/containers">Open Source Inversion of Control Containers in C# </a>。</p>
<p><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>使用注入Mock对象做单元测试（Unit Testing with Injected Mock Objects）</strong></span><br><br>据经验所得，使用DI最大的好处就是更干净的单元测试和非常好的可插拔性。由于接口，依赖带来了可插拔性。我们来看看DI怎么有利于单元测试。这是一个经常的用例，开发者应对真实数据库编写单元测试。避免让单元测试成为累赘，这需要摒弃以前的慢速单元测试 -- 测试业务逻辑层的时候所依赖的数据访问代码，要不断地访问数据库。Mock对象是实现这个的完美选择。Mock对象模仿真实对象的反应，扮演假设使用真正资源的角色。他们可以很好地模仿访问数据库，模仿访问IO，模仿访问Web Service等等。</p>
<p>下面的代码展示了一个Mock的数据访问，实现了一个贯穿全文的IOrderDao接口。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MockOrderDao&nbsp;:&nbsp;IOrderDao&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Order&nbsp;GetOrderById(</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;orderId)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Order&nbsp;foundOrder&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Order();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foundOrder.SaleDate&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1/1/06</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foundOrder.ID&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;orderId;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;foundOrder;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<br>一个简单的，Mock数据访问对象实现了IOrderDao，因此它能通过构造函数或设置方法注入的方法，传递到各个需要依赖IOrderDao 的对象。现在我们的逻辑层可以脱离访问数据库做测试。在我自己的测试包中，我通常有一段包含真正数据库的测试，然后传入Mock数据库对象以提供业务逻辑对象的单元测试。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>引用文章</strong></span><br><br>
<li><a href="http://www.martinfowler.com/articles/injection.html" target=_blank><u><font color=#0000ff>Inversion of Control Containers and the Dependency Injection Pattern</font></u></a>
<li><a href="http://www-128.ibm.com/developerworks/library/j-mocktest.html" target=_blank><u><font color=#0000ff>Unit testing with mock objects</font></u></a> </li><img src ="http://www.cnitblog.com/seeyeah/aggbug/36861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-25 21:30 <a href="http://www.cnitblog.com/seeyeah/articles/36861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[2007-11-23]高性能ASP.NET应用程式的最佳实践(Point 11~15)</title><link>http://www.cnitblog.com/seeyeah/articles/36761.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 22 Nov 2007 17:17:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36761.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36761.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36761.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36761.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36761.html</trackback:ping><description><![CDATA[<p style="COLOR: #993300"><span style="COLOR: #000000">原文<br>标题：ASP.NET Best Practices for High Performance Applications<br>作者：Ali Khan (OKC)<br>链接：<a href="http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp">http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp</a><br>翻译时间：2007-11-23<br></span><strong style="COLOR: #993300"><br>
<hr>
<br>11. 注意分页的效率【Use paging efficiently】</strong>&nbsp;<br>&nbsp;
<p>允许用户请求获得太多的数据，以至于消耗程式过多的资源，造成服务器不必要的紧张。这种不必要的压力导致增加CPU的使用率，增加内存使用量以及降低了反应次数。客户自然而然地，链接速度就会变慢。从可用性角度来说，大部分用户不会想在一个页面看到成千上万笔数据的呈现。。执行一个分页方案，从数据库中获取只想看到的一部分数据，减少后台数据库的工作量。你应该优化从数据库服务器到中间网站服务器获取数据的效率。要获取更多的信息，可以读这篇文章(<a href="http://weblogs.asp.net/scottgu/archive/2006/01/01/434314.aspx">http://weblogs.asp.net/scottgu/archive/2006/01/01/434314.aspx</a>)，在数据库层面实现分页。如果你是使用SQL Server2000，也看看这篇文章（<a href="http://www.codeproject.com/aspnet/PagingLarge.asp">http://www.codeproject.com/aspnet/PagingLarge.asp</a>）。</p>
<p><strong style="COLOR: #993300">12. 显示关闭所有资源【Explicitly Dispose or Close all the resources】</strong></p>
<p>当出现异常时，使用try/finally模块，保证资源被清除。在finally模块关闭资源。使用try/finally模块可以确保即使出现异常状况，资源也被关闭。在你需要打开连接的时候才打开它，并且在你完成任务后，尽快地关闭掉。你应该永远记住这句话：&#8220;进来，处理完数据，立刻走&#8221;。如果你使用了多个不同的对象，你要确认已经调用了各个对象所提供的Dispose 或Close。如果调用Close或Dispose失败的话，在客户端停止使用它们后，对象在内存还会延长它的生命周期。延迟清除资源会增加内存的压力。数据库连接和文件IO读写，就是应该显示关闭的例子。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br>_con.Open()<br></span><span style="COLOR: #0000ff">Catch</span><span style="COLOR: #000000">&nbsp;ex&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Exception<br></span><span style="COLOR: #0000ff">Throw</span><span style="COLOR: #000000">&nbsp;ex<br></span><span style="COLOR: #0000ff">Finally</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Not</span><span style="COLOR: #000000">&nbsp;_con&nbsp;</span><span style="COLOR: #0000ff">Is</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Nothing</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000"><br>_con.Close()<br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Try</span></div>
<p>&nbsp;</p>
<p><strong style="COLOR: #993300">13. 禁用跟踪和除错【Disable tracing and debugging】</strong></p>
<p>在你发布配置你的应用程式时，应该禁用跟踪和除错。跟踪和除错功能会导致一些性能的问题。当你的程式在正式环境运行时，并不推荐开启跟踪和除错功能。你可以使用以下的语法，在Machine.config和Web.config文件中禁用它们。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">configuration</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">system</span><span style="COLOR: #ff0000">.web</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">trace&nbsp;</span><span style="COLOR: #ff0000">enabled</span><span style="COLOR: #0000ff">="false"</span><span style="COLOR: #ff0000">&nbsp;pageOutput</span><span style="COLOR: #0000ff">="false"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">compilation&nbsp;</span><span style="COLOR: #ff0000">debug</span><span style="COLOR: #0000ff">="false"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">system.web</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">configuration</span><span style="COLOR: #0000ff">&gt;</span></div>
<p>&nbsp;</p>
<p><strong style="COLOR: #993300">14. 预编译页面，禁用自动匹配属性【Precompile pages and disable AutoEventWireup】</strong></p>
<p>尽量使用预编译页面，不要让用户有机会访问批量即时编译的ASP.NET文件；因为这将会增加用户消耗的性能。</p>
<p>另外，在Machine.config设置AutoEventWireup属性为false，你的页面将不会根据一些匹配的方法名称而自动调用它们（如，Page_Load）。如果开发人员想使用这些事件，它们可以重写基类的方法（如，他们可以重写页面的Page.OnLoad，替换使用Page_Load的方法）。如果你禁用了AutoEventWireup，你使用事件绑定替代原来的自动呈现方法，页面性能会得到轻微的提升。<br></p>
<p><strong style="COLOR: #993300">15. 使用存储过程和索引【Use stored procedures and indexes】</strong></p>
<p>在大部分的情况下，使用已编译后的存储过程代替特别的查询会获取更多的性能改善。</p>
<p>确认你的表都正确地添加了索引。尝试使用&#8220;索引优化向导&#8221;（Index Tuning Wizard ），你可以获得他的一些关于最好的索引建议，可供选择。你无需遵守所有以下的建议，但它可能会提示出关于你的结构和数据的一些信息，这些都对你选择更适合索引有所帮助。</p>
<p>&nbsp;1）在SQL Server Management Studio (SQL Server 2005), 选中你的Sql语句。在菜单选择&#8220;查询&#8221;=》&#8220;显示估计执行计划&#8221;，查看查询开销和索引使用详细信息（快捷键Ctrl +L）。<br>&nbsp;2）在Sql2000也有类似的&#8220;索引调整向导&#8221;。在查询分析其中，选中你的Sql，选择在菜单选择&#8220;查询&#8221;=》&#8220;Index Tuning Wizard&#8221;。</p>
<p><strong style="COLOR: #993300">引用</strong></p>
<p>改善.NET程式的性能和可扩展性 (发布于 2006, February 12). </p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/36761.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-23 01:17 <a href="http://www.cnitblog.com/seeyeah/articles/36761.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高性能ASP.NET应用程式的最佳实践</title><link>http://www.cnitblog.com/seeyeah/articles/36759.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 22 Nov 2007 15:31:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36759.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36759.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36759.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36759.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36759.html</trackback:ping><description><![CDATA[<br>1、<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36591.html"><u>[2007-11-20]高性能ASP.NET应用程式的最佳实践(Point 1~4)</u></a><br><br>2、<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36700.html"><u>[2007-11-21]高性能ASP.NET应用程式的最佳实践(Point 5~10)</u></a> <br><br>3、<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36761.html"><u>[2007-11-23]高性能ASP.NET应用程式的最佳实践(Point 11~15)</u></a>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/36759.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-22 23:31 <a href="http://www.cnitblog.com/seeyeah/articles/36759.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[2007-11-21]高性能ASP.NET应用程式的最佳实践(Point 5~10)</title><link>http://www.cnitblog.com/seeyeah/articles/36700.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 21 Nov 2007 17:08:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36700.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36700.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36700.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36700.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36700.html</trackback:ping><description><![CDATA[<p><span style="COLOR: #000000">原文<br>标题：ASP.NET Best Practices for High Performance Applications<br>作者：Ali Khan (OKC)<br>链接：<a href="http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp">http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp</a><br>翻译时间：2007-11-23</span></p>
<p>
<p>
<hr>
<br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>5. 小心使用session【Use session variables carefully】</strong></span><br><br>避免在Session变量中存储大量的数据，确认你的Session超时是合理的。Session会消耗大量的服务器重要内存资源。记住，存储在Session的数据会在用户直接关掉浏览器后，还会存在相当的一段时间。太多的Session变量会把服务器弄垮。如果你在部分页面或程式不需要使用Session变量，应该禁用Session状态。
<p>&nbsp;</p>
<p>&nbsp;1）禁用一个页面的Session状态，直接设置@ Page 的EnableSessionState 属性为false。如：<br>&nbsp;&lt;%@ Page EnableSessionState="false" %&gt; <br>&nbsp;2）如果你的页面只需要访问Session变量而不需要创建、修改它们，直接设置@ Page 的EnableSessionState 属性为ReadOnly。如：<br>&nbsp;&lt;%@ Page EnableSessionState="ReadOnly" %&gt;&nbsp;&nbsp; <br>&nbsp;3）禁用服务器的所有程式使用Session，在Machine.config使用以下元素设置：<br>&nbsp;&lt;sessionState mode='Off'/&gt;<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>6. 使用Server.Transfer【Use Server.Transfer】</strong></span><br><br>在同一个应用程式中，使用Server.Transfer 方法重定向页面。</p>
<p>使用Server.Transfer这个语法，避免了不必要的客户端重定向。可以考虑使用Server.Transfer替代Response.Redirect。然而，你也不能总是使用Server.Transfer代替Response.Redirect 。如果你需要在重定向期间，做验证、授权处理，就必须使用Response.Redirect；因为这两种机制不相等。当你使用Response.Redirect，确认你使用了第二个参数为bool类型的重载版本，并传递false值，这样就可以确认内部的异常不会触发。同时，也要注意，你只能使用Server.Transfer 在同一个程式中，在页面定向间传递控件信息。如果要转页面到其他程式，必须使用Response.Redirect。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>7.适当使用服务器控件，避免嵌套深层的控件。【Use server controls when appropriate and avoid creating deeply nested controls】</strong></span><br><br>HTTP协议是无状态的；然而，服务器控件提供能强大的模型，使用了ViewState在管理页面间请求之间管理它的状态。没有免费的午餐，服务器控件需要一定数量的进程去建立自身控件和它的所有子控件。这一点，服务器控件对比HTML控件或静态的文本，相对地花费更多内存。当你不需要复杂的交互时，在用户界面使用一些内嵌服务器函数来替代服务器控件呈现界面。如果是以下条件，请替换服务器控件：</p>
<p>&nbsp;1）你不需要在回传之间维护状态<br>&nbsp;2）控件只负责静态输出数据，或者控件显示只读的数据<br>&nbsp;3）不需要在服务器端编程访问控件</p>
<p>替换服务器控件方法可选择，简单rendering、HTML元素、用&lt;%%&gt;尖括弧内嵌调用 Response.Write。平衡你的选择是非常重要的。如果你的程式性能还可以接受，或者你对你程式的性能要求有限，那就避免过渡优化你的程式。</p>
<p>深层级嵌套的复合控件，需要花费一定的内存去建立自身控件和它的所有子控件。深层级结构导致创建额外的进程；这可使用html控件或使用更简单层次的服务器控件来避免。当你使用的控件如Repeater, DataList, 和 DataGrid 就要特别注意，因为他们将会在他们的容器中创建许多附加的子控件。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>8.选择适合你的&#8220;检视&#8221;控件【Choose the data viewing control appropriate for your solution】</strong></span><br><br>怎样选择如何在Web Form页面呈现数据，通常的重要依据是看便利和性能方面的权衡。在你选择使用控件之前，一定要对比一下他们的优劣之处。举例，你可以选择这三个控件(DataGrid, DataList 和 Repeater)去呈现数据，你的任务是找出哪个控件能提供给你最大的好处。DataGrid 可以用最快捷、最简单的方法去呈现数据，但通常来说它是最耗费性能的。在一些简单的案例中，用自动生成HTML可以完成列表工作，但用户定制需求和浏览器兼容（browser targeting？）所引发出来的额外工作很快就会抵消之前的快捷和便利。Repeater 控件是一个在便利和性能之间折中的服务器控件。它高效、可定制、可设计。</p>
<br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>9. 优化代码和处理异常【Optimize code and exception handling】<br><br></strong></span>在一些性能关键代码瓶颈中，使用For代替Foreach可以优化耗费性能的循环。也不要依赖你代码的异常或写一些代码能避免异常。每当发生异常而导致性能下降时，你应该不是用正常的程式流程去控制他们。尽可能的在代码检查有可能出现异常的地方。在处理这些条件之前，不要让他自己捕获异常。不要用异常去控制逻辑。如，数据库连接失败是一个异常，然而用户只是用户忘记输入密码，这种简单判断应该用条件作处理。常见的情景包括：检查是否为null；分配一个字符串而它将会被转化为数字；在应用数据运算符前，检测具体值是否符合要求。下面的例子演示导致异常的代码和使用条件判断的代码。两者运行的结果是相同的。<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">'</span><span style="COLOR: #008000">不需要使用Exception</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">&nbsp;number<br></span><span style="COLOR: #0000ff">Catch</span><span style="COLOR: #000000">&nbsp;ex&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Exception<br>&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">&nbsp;推荐代码</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Not</span><span style="COLOR: #000000">&nbsp;number&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">&nbsp;number<br></span><span style="COLOR: #0000ff">Else</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">If</span></div>
<br>检查null值。如果一个对象有可能为null，就检查确认它不为空；比直接抛出异常做法好。这通常会发生在，当我们要向ViewState、Session、Application或cache和query string 、form 的变量中获取值的时候。举例，不要使用以下的代码去访问Session的信息。<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">'</span><span style="COLOR: #008000">不需要使用Exception</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br>value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;HttpContext.Current.Session(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Value</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).ToString<br></span><span style="COLOR: #0000ff">Catch</span><span style="COLOR: #000000">&nbsp;ex&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Exception<br>Response.Redirect(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main.aspx</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">False</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br>&nbsp;<br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">推荐代码</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Not</span><span style="COLOR: #000000">&nbsp;HttpContext.Current.Session(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Value</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">Is</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Nothing</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000"><br>value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;HttpContext.Current.Session(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Value</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).ToString<br></span><span style="COLOR: #0000ff">Else</span><span style="COLOR: #000000"><br>Response.Redirect(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main.aspx</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">False</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">If</span></div>
<br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>10.使用DataReader会更快更高效地绑定数据【Use a DataReader for fast and efficient data binding】</strong></span><br><br>如果你不需要缓存数据、或你只需呈现只读的数据、或者你只需要尽可能快速地加载数据到控件，你可以选择使用DataReader。DataReader 是在只向前读取数据中获取只读数据的最佳选择。加载数据到DataSet，然后绑定DataSet到控件，需要转移2次数据；你为了更好的性能，可以使用特殊的指定类型方法去获取数据。 
<img src ="http://www.cnitblog.com/seeyeah/aggbug/36700.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-22 01:08 <a href="http://www.cnitblog.com/seeyeah/articles/36700.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[2007-11-20]高性能ASP.NET应用程式的最佳实践(Point 1~4)</title><link>http://www.cnitblog.com/seeyeah/articles/36591.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 20 Nov 2007 15:48:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36591.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36591.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36591.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36591.html</trackback:ping><description><![CDATA[<p>原文<br>标题：ASP.NET Best Practices for High Performance Applications<br>作者：Ali Khan (OKC) <br>链接：<a href="http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp"><span>http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp</span></a><a href="http://www.codeproject.com/csharp/events.asp"></a><br>翻译时间：2007-11-20</p>
<p>
<hr>
<p>&nbsp;</p>
<p><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>摘要</strong></span><br><br>文章列出了一些能使你的ASP.NET应用程式最优化的一些技术。它提供了一些共同的问题，设计方针，以及一些编程技巧，让你可以建置最佳的和健壮的解决方案。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>简介【Introduction】</strong></span><br><br>ASP.NET比传统的ASP强大得多，然而了解怎么使用它的强大去建立一个高效的、可靠的、健壮的程式也是很重要的。在此篇章中，我尝试突出一些关键的技巧，让你能使用它去尽可能地优化你的ASP.NET页面。篇幅可能比较长，我只能强调最重要的一些点。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>1. 先计划调查，再做开发【Plan and research before you develop】</strong></span><br><br>研究和调查.NET怎么使用才能真的有利于你。.NET为各个层次的应用程式设计和开发提供能各种各样的方案。这需要你要非常了解你自身的状况，以及每个能达到你目的的开发环境的好与坏。Visual Studio是一个全面的开发包，为实现同一个业务逻辑可提供能许多选项。检查每一个选项，并且为你即将来临的任务选择最适合的方案是非常重要的。用分层的手法，逻辑上划分你的应用程式：表现层、业务层和数据层。这不仅能让你能创建可维护代码，并允许你分别监控和优化每一层的性能。同时，清晰的逻辑分层也为程式的伸缩性提供了更多的选择。尝试减少你在code-behind文件的代码量，可以改善程式的维护性和伸缩性。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>2. 字符串的串联【String concatenation】</strong></span><br><br>如果处理不当，字符串的链接真的会导致程式性能的下降。你可以用以下两个方式串联字符串。</p>
<p>第一，在使用字符串的时候，直接添加新的字符串到现有的字符串。然而，这样的做法是非常消耗性能的（特别是你在循环中使用这种串联字符串）。当你添加新的字符串到现有的字符串时，.NET框架会先同时复制已存在和新的数据到内存进行串连，然后删除已存在的字符串，最后在新的字符串读出数据。过分冗长的串联字符串操作会非常消耗时间。</p>
<p>第二，也是比较好的办法，使用StringBuilder串联字符串。以下两个例子做相同的实现。如果你考虑使用哪种字符串串联方式，请你自己亲自分别测试一下两段程式。也许你会对结果非常意外。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">'</span><span style="COLOR: #008000">使用&#8220;+=&#8221;串联字符串&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Response.Write(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;b&gt;String&nbsp;Class&lt;/b&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">str</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">String</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;startTime&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;DateTime&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now<br>Response.Write((</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&gt;Start&nbsp;time:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;startTime.ToString()))<br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">For</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">To</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">99999</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">str</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;i.ToString()<br></span><span style="COLOR: #0000ff">Next</span><span style="COLOR: #000000">&nbsp;i<br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;EndTime&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;DateTime&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now<br>Response.Write((</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&gt;End&nbsp;time:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;EndTime.ToString()))<br>Response.Write((</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&gt;#&nbsp;of&nbsp;time&nbsp;Concatenated:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;i.ToString))<br>Results:&nbsp;花了4分23秒完成100,000次串联<br><br></span><span style="COLOR: #0000ff">String</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;<br>Start&nbsp;time:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2006</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">21</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">24</span><span style="COLOR: #000000">&nbsp;AM&nbsp;<br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;time:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2006</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">25</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">47</span><span style="COLOR: #000000">&nbsp;AM&nbsp;<br>#&nbsp;of&nbsp;time&nbsp;Concatenated:&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">&nbsp;<br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">使用&#8220;StringBuilder&#8221;串联字符串&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;Response.Write(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;b&gt;StringBuilder&nbsp;Class&lt;/b&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br>&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;strbuilder&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;StringBuilder()<br>&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;startTime&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;DateTime&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now<br>&nbsp;Response.Write((</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&gt;Start&nbsp;time:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;startTime.ToString()))<br>&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000"><br>&nbsp;</span><span style="COLOR: #0000ff">For</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">To</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">99999</span><span style="COLOR: #000000"><br>&nbsp;strbuilder.Append(i.ToString())<br>&nbsp;</span><span style="COLOR: #0000ff">Next</span><span style="COLOR: #000000">&nbsp;i<br>&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;EndTime&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;DateTime&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now<br>&nbsp;Response.Write((</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&gt;Stop&nbsp;time:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;EndTime.ToString()))<br>&nbsp;Response.Write((</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&gt;#&nbsp;of&nbsp;time&nbsp;Concatenated:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;i.ToString))<br>Results:&nbsp;1秒内完成100,000次串联<br><br>StringBuilder&nbsp;</span><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;<br>Start&nbsp;time:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2006</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">31</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">22</span><span style="COLOR: #000000">&nbsp;AM&nbsp;<br></span><span style="COLOR: #0000ff">Stop</span><span style="COLOR: #000000">&nbsp;time:</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2006</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">31</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">22</span><span style="COLOR: #000000">&nbsp;AM&nbsp;<br>#&nbsp;of&nbsp;time&nbsp;Concatenated:&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">&nbsp;<br></span></div>
<br>/*********************************************/<br>【我的C#版测试】<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Program<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringConnect();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilderConnect();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;loopTime&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;StringConnect()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime&nbsp;start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;loopTime;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;i.ToString();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">String:{0}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,&nbsp;((TimeSpan)(DateTime.Now&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;start)).TotalSeconds);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;StringBuilderConnect()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime&nbsp;start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;StringBuilder()&nbsp;;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;loopTime;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str.Append(i.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">StringBuilder:{0}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,&nbsp;((TimeSpan)(DateTime.Now&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;start)).TotalSeconds);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p><br>结果：<br>String&nbsp;&nbsp;:151.5579296秒<br>StringBuilder&nbsp;:&nbsp; 0.0600864秒<br>/*********************************************/<br><br>这是ASP.NET在许多情况下能提供一种能极大地提高性能优于传统ASP的其中一种。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>3. 避免信息回传提交服务器【Avoid round trips to the server】</strong></span><br><br>你可以使用以下一些技巧去避免不必要的回传网站服务器：</p>
<ol>
    <li>尽可能地实现Ajax的UI。这个想法可以避免真个页面的刷新，并且只更新页面需要更新的一部分。在Scott's article(<a href="http://weblogs.asp.net/scottgu/archive/2006/01/01/434314.aspx">http://weblogs.asp.net/scottgu/archive/2006/01/01/434314.aspx</a>)给了很多怎样使用Ajax Atlas和&lt;atlas:updatepanel&gt; 控件的一些很好的建议。
    <li>使用客户端脚本。客户端验证可以帮助减少一些需要处理用户的请求。在ASP.NET，你也可以使用客户端控件去验证用户的输入。
    <li>使用Page.ISPostBack属性，确认你只需在页面第一次初始化加载时呈现出来的信息，不在客户回传事件中也会响应。<br>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 81.38%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; HEIGHT: 55px; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Not</span><span style="COLOR: #000000">&nbsp;IsPostBack&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;LoadJScripts()<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">If</span></div>
    <li>在某些情况下，不必要处理回传事件。你可以使用client callbacks 去从服务器端获取数据，代替整个页面的回传。详细请看<a href="http://msdn2.microsoft.com/en-us/library/ms178208.aspx">http://msdn2.microsoft.com/en-us/library/ms178208.aspx</a>。 </li>
</ol>
<p><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>4. 当必要时才使用viewstate【Save viewstate only when necessary】</strong></span><br><br>ViewState 主要被用于服务器控件在回传页面数据时能保持它自身的状态。这些信息会传到客户端，从一个hidden的变量读取回来。ViewState 不必要存在在不需要它的页面。随着ViewState数据的扩大，会影响垃圾回收的性能。你可以根据以下的一些提示。以便优化使用ViewState。</p>
<p>&nbsp;1）当你不需要ViewState的情况<br>&nbsp;在ASP.NET默认的状况下，ViewState的状态是开启的。你不需要ViewState的原因可能是你的页面只是用来输出数据而已，或者你已经明确用户的每次请求你都重新加载页面。以下情况下，你不需要使用ViewState。<br><br>&nbsp;a.你的页面不需要回传（postback）。如果页面不会回传信息给自己，或者页面只是用于输出数据，又或者页面不需要处理回应数据，你就不需要ViewState。<br><br>&nbsp;b.你不使用服务器事件。如果你的服务器控件不处理事件；服务器控件不是动态的或没有数据绑定属性值，或者他们在每次请求中都会在代码中进行重新设置属性值，你就不需要ViewState。<br><br>&nbsp;c.你会在每次页面刷新重新设置控件。如果你忽略旧数据，你在每次页面刷新的时候会重新设置服务器控件。你就不需要ViewState。</p>
<p>&nbsp;2）禁用ViewState<br>&nbsp;有几个方法可以不同程度禁用ViewState。<br><br>&nbsp;a.禁用在页面上单个控件的ViewState，把控件的EnableViewState属性设为false。<br><br>&nbsp;b.禁用单个页面的ViewState，在@ Page 的EnableViewState 属性指定为false。如：<br>&nbsp;&nbsp;&lt;%@ Page EnableViewState="false" %&gt;&nbsp;<br><br>&nbsp;c.在指定程式禁用ViewState，可以在相关程式的Web.config 文件中添加以下元素：<br>&nbsp;&nbsp;&lt;pages enableViewState="false" /&gt;<br><br>&nbsp;d.对网站服务器的所有网站程序都禁用ViewState，在Machine.config 中，修改&lt;pages&gt;元素如下所示：<br>&nbsp;&nbsp;&lt;pages enableViewState="false" /&gt;<br><br></p>
<p>&nbsp;3）确定你的ViewState大小。<br>&nbsp;启用页面的tracing 功能，你可以监控每一个控件ViewState的大小。你可以根据这些信息，决定优化ViewState的大小；或者决定哪些控件的ViewState需要禁用。<br><br><br></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/36591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-20 23:48 <a href="http://www.cnitblog.com/seeyeah/articles/36591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[2007-11-19]事件和委托的简单说明</title><link>http://www.cnitblog.com/seeyeah/articles/36521.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 19 Nov 2007 16:28:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/articles/36521.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36521.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/articles/36521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36521.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36521.html</trackback:ping><description><![CDATA[原文<br>标题：Events and Delegates simplified<br>作者：Maysam Mahfouzi. <br>链接：<a href="http://www.codeproject.com/csharp/events.asp">http://www.codeproject.com/csharp/events.asp</a><br>翻译完成时间：2007-11-19<br><br>
<hr>
<p><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>内容摘要</strong></span></p>
<ul>
    <li>介绍
    <li>什么是委托
    <li>理解事件
    <li>event 关键字
    <li>最后 </li>
</ul>
<p><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>介绍【<a name=Introduction1><font style="COLOR: #993300" color=#000000>Introduction</font></a>】</strong></span></p>
当我在学习事件和委托的概念时，我读了大量的文章想去完全地明白它们是怎么使用的；现在，我想在这里把我所有学的东西呈现在此，同时它们大部分也是你需要学习的知识。<br><br>
<p><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>什么是委托【What are delegates?】</strong></span></p>
<p>委托和时间两个概念是紧密关联的。委托只是一个函数指针（function pointers），也就是说，他们拥有方法（function）的引用。</p>
<p>委托是一个类。当你创建一个实例化时，你要传入一个这个委托所要引用的方法（function）的名称（将作为委托的构造函数的参数）。</p>
<p>每个委托都拥有一个签名（signature），如：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Delegate&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;SomeDelegate(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;s,&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;b);<br></span></div>
<p><br>是一个委托声明。我说这个委托拥有签名，这个签名的意思就是它表示返回一个int类型和携带2个参数，类型为string和bool。</p>
<p>我说，当你使用委托时，你需要传入一个这个委托所要引用的方法的名称作为它的构造函数参数。重要的一点是，只有拥有相同参数的方法才能作为委托的参数传入。</p>
<p>考虑以下方法：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;SomeFunction(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;str,&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;bln){<img src="http://www.cnitblog.com/Images/dot.gif">}<br></span></div>
<p>你可以传入这个方法作为SomeDelegate的构造函数，因为他们拥有相同的签名。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">SomeDelegate&nbsp;sd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SomeDelegate(SomeFunction);</span></div>
<p><br>现在，sd 引用了 SomeFunction；换句话说，SomeFunction 被注册到（registered&nbsp; to）sd。如果你调用sd，SomeFunction 将被调用。先记住我所说的&#8220;注册方法&#8221;（registered functions）。后面，我会引用注册方法。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">sd(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">somestring</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">);</span></div>
<p>&nbsp;</p>
<p>现在你明白了怎么使用委托，让我们继续看看事件。<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>理解事件【Understanding Events】</strong></span></p>
<ul>
    <li>Button是一个类，当你点击它的时候，click事件被触发。
    <li>Timer是一个类，每一毫秒，tick事件都被触发。 </li>
</ul>
<p>想知道怎么回事吗？我们通过一个例子学习：</p>
<p>一个假设情节（scenario）：我们有一个名为Counter的类。这个类有一个方法用来计算0到countTo的方法，名为CountTo(int countTo, int reachableNum)；以及每当计算到reachableNum就会引发NumberReached 事件。</p>
<p>我们的类有一个事件：NumberReached。事件是委托类型的变量。如果你需要声明一个事件，你只需要声明一个委托类型变量，并填写event关键字在你的声明处，如下所示：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">event</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler&nbsp;NumberReached;</span></div>
<p><br>在上面的声明中，NumberReachedEventHandler 只是一个委托。可能这样说比较好：NumberReachedDelegate，但注意，Microsoft 不会说MouseDelegate 或 PaintDelegate，取而代之的是MouseEventHandler 和 PaintEventHandler。那我们就可以方便地说用NumberReachedEventHandler 代替NumberReachedDelegate。好吗？Good！</p>
<p>在我们声明事件之前，我们需要定义我们的委托（我们的事件句柄（event handler））。如下图所示：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;NumberReachedEventArgs&nbsp;e);</span></div>
<p>就如你看的，我们的委托名称为：NumberReachedEventHandler，并且它的签名包括一个void的返回值和两个参数，参数类型分别为 object 和 NumberReachedEventArgs。如果你想在某处实例化这个委托，那么这个方法必须有相同的签名才能传入作为委托的构造函数参数。</p>
<p>你曾经在你的代码里面用过PaintEventArgs 或 MouseEventArgs ，去判断鼠标的位置，移到哪里，或者判断哪个对象触发了Paint 事件？实际上，我们为客户端提供的数据都继承于EventArgs 类。举例来说，在我们上面的例子，我们要提供一个需要到达的数字，我们就会这样定义类。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;NumberReachedEventArgs&nbsp;:&nbsp;EventArgs<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_reached;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;NumberReachedEventArgs(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;num)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">._reached&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;num;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ReachedNumber<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_reached;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></span></div>
<p>如果你并不需要提供给客户端任何信息，我们可以直接使用EventArgs 。</p>
<p>现在，万事俱备，我们看一看Counter 类：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;Events<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NumberReachedEventArgs&nbsp;e);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Counter<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">event</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler&nbsp;NumberReached;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Counter()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CountTo(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;countTo,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;reachableNum)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(countTo&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;reachableNum)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArgumentException(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">reachableNum&nbsp;should&nbsp;be&nbsp;less&nbsp;than&nbsp;countTo</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ctr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;ctr</span><span style="COLOR: #000000">&lt;=</span><span style="COLOR: #000000">countTo;ctr</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(ctr&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;reachableNum)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NumberReachedEventArgs&nbsp;e&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventArgs(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reachableNum);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OnNumberReached(e);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">不再计算</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnNumberReached(NumberReachedEventArgs&nbsp;e)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(NumberReached&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NumberReached(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">,&nbsp;e);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">引发事件</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></span></div>
<p><br>在以上代码，我们如果计算到达了期望值就会引发事件。这里有几点需要考虑：</p>
<p>&nbsp;1、完成&#8220;触发事件&#8221;是通过呼叫我们的事件（一个名称为NumberReachedEventHandler的委托实例）：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;NumberReached(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">,&nbsp;e);</span></div>
<p>&nbsp;这样，所有注册方法都会被调用。<br></p>
2、我们通过这样为注册方法提供数据：&nbsp;&nbsp;
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">NumberReachedEventArgs&nbsp;e&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventArgs(reachableNum);</span></div>
<p><br>3、提一个问题：为什么我们要通过OnNumberReached(NumberReachedEventArgs e)调用NumberReached(this, e)。为什么部门不直接像下面的代码那样调用。&nbsp;&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(ctr&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;reachableNum)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NumberReachedEventArgs&nbsp;e&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventArgs(reachableNum);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">OnNumberReached(e);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">之前的做法</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(NumberReached&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">新做法</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NumberReached(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">,&nbsp;e);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">引发事件</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">不再计算</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;}<br></span></div>
<p>&nbsp;提得好！如果你想知道为什么我们不直接调用，请再看看OnNumberReached的签名。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnNumberReached(NumberReachedEventArgs&nbsp;e)</span></div>
<ul>
    <li>&nbsp;这个方法是protected的，意味子类也可以使用。
    <li>&nbsp;这个方法是virtual，意味着可以被子类重写。<br>&nbsp;<br>&nbsp;以上两点是很有用的。想象一下，你要设计一个类继承于Counter 。通过重写OnNumberReached 方法，你既可以在引发事件之前，在你要设计的类里面添加一些额外的工作。如： </li>
</ul>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnNumberReached(NumberReachedEventArgs&nbsp;e)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">做额外工作</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">.OnNumberReached(e);<br>&nbsp;&nbsp;}</span></div>
<p>&nbsp;</p>
<p>&nbsp;注意，如果你没有呼叫base.OnNumberReached(e)，那么事件将永远不会被触发！当你想在子类里面除去它的事件时这样做就非常有用了。有趣的窍门呢，哈哈。</p>
<p>&nbsp;在实际使用中，你可以创建一个新的ASP.NET 网页应用程式，并看看里面生成的后台代码。如你所见，你的page继承自System.Web.UI.Page 类。这个类有一个virtual 和 protected 的方法名为OnInit。你看到在重写的方法中调用InitializeComponent() 做为额外的工作，然后调用基类的 OnInit(e)：<br>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">#region</span><span style="COLOR: #000000">&nbsp;Web&nbsp;Form&nbsp;Designer&nbsp;generated&nbsp;code</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnInit(EventArgs&nbsp;e)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">CODEGEN:&nbsp;This&nbsp;call&nbsp;is&nbsp;required&nbsp;by&nbsp;the&nbsp;ASP.NET&nbsp;Web&nbsp;Form&nbsp;Designer.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">.OnInit(e);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;Required&nbsp;method&nbsp;for&nbsp;Designer&nbsp;support&nbsp;-&nbsp;do&nbsp;not&nbsp;modify<br>&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;the&nbsp;contents&nbsp;of&nbsp;this&nbsp;method&nbsp;with&nbsp;the&nbsp;code&nbsp;editor.<br>&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;InitializeComponent()<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Load&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;System.EventHandler(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Page_Load);<br>&nbsp;&nbsp;}<br>&nbsp;</span><span style="COLOR: #0000ff">#endregion</span></div>
<p>&nbsp;</p>
<p>4、注意，NumberReachedEventHandler 委托定义在类的外面，在命名空间之内，可见于所有类。<br></p>
<p>好的。到时间实践使用一下我们的Counter 类：</p>
<p>在我们示例应用程式中，我们有2个textbox，命名分别为txtCountTo 和 txtReachable ，如图所示<br><img height=168 alt="sample application" src="http://www.codeproject.com/csharp/events/demo.jpg" width=232><br><br>这里就是处理btnRun 的Click事件的代码：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;cmdRun_Click(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;System.EventArgs&nbsp;e)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(txtCountTo.Text&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;txtReachable.Text</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Counter();<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached);<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter.CountTo(Convert.ToInt32(txtCountTo.Text),&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convert.ToInt32(txtReachable.Text));<br>}<br><br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;oCounter_NumberReached(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;NumberReachedEventArgs&nbsp;e)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;MessageBox.Show(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Reached:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;e.ReachedNumber.ToString());<br>}<br><br></span></div>
<p>这个就是初始化事件的语法。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached);</span></div>
<p>现在你明白我们在这里所做的一切了！你刚刚在初始化一个NumberReachedEventHandler 委托（就像你对其他对象一样）。关注一下oCounter_NumberReached 方法签名如之前所提到的要与委托签名相同。</p>
<p>还有，注意我们使用了 += 替代了简单的 = 。</p>
<p>这是因为，委托是一个特殊的对象，他可以持有多于一个的引用（在这里，应该说引用多于一个方法）。距离，如果我们有另外一个与 oCounter_NumberReached 有相同签名的方法oCounter_NumberReached2 ，2个方法同时可以通过以下方法被引用：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached);<br>oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached2);</span></div>
<p>现在，引发事件之后，两个方法会被依次调用。</p>
<p>如果在我们代码的某处，基于某些原因，我们决定oCounter_NumberReached2 引发NumberReached事件时不需要再调用，我们可以简单地如下这样做：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached2);</span></div>
<p><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>event关键字【event Keyword】</strong></span><br><br>基本上，声明event可以防止delegate设置为null。为什么这个这么重要？想象我现在已经添加一个委托调用列表到我们的类。这样，现在其他客户端可以运行得很好。忽然，有某人简单的使用了&#8220;=&#8221;代替了&#8220;+=&#8221;设置新的回调。这样就会抛弃了所有旧的委托，并且创建一个完全全新的委托到委托调用列表，而这样调用列表中只有它一项而已。这样，当时间到的时候，其他客户就不能收到他们回调函数。这是event 关键字所要解决的一种状况。如果我们在Counter类中移除了event关键，然后尝试编译下面的代码，会出现以下错误：<br><img height=80 src="http://www.codeproject.com/csharp/events/ERROR1.JPG" width=600 border=1><br><br>结论：事件的生命为实例化的委托添加了一层保护。这个保护防止客户端重置委托和它的调用列表，只能允许在调用列表中添加或移除对应目标。[引用<a href="http://weblogs.asp.net/rosherove/archive/2004/03/28/100444.aspx">http://weblogs.asp.net/rosherove/archive/2004/03/28/100444.aspx</a>]<br><br><span style="FONT-SIZE: 18pt; COLOR: #993300"><strong>最后【Finally】</strong></span><br><br>不要忘记在你的应用程式的主构造函数中命名下列代码，代替在cmdRun_Click 事件内定义。我定义他们到cmdRun_Click 事件处理内只是为了方便而已。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Form1()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Required&nbsp;for&nbsp;Windows&nbsp;Form&nbsp;Designer&nbsp;support<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//<br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;TODO:&nbsp;Add&nbsp;any&nbsp;constructor&nbsp;code&nbsp;after&nbsp;InitializeComponent&nbsp;call<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//<br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;oCounter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Counter();<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached);<br>&nbsp;&nbsp;&nbsp;&nbsp;oCounter.NumberReached&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NumberReachedEventHandler(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oCounter_NumberReached2);<br>}<br></span></div>
<p>&nbsp;</p>
<p>文章的源代码在上面提供下载。</p>
<p>如果你投票少于5分的话，请让我知道原因;-)。希望你读完这篇文章后会满意。<br></p><img src ="http://www.cnitblog.com/seeyeah/aggbug/36521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2007-11-20 00:28 <a href="http://www.cnitblog.com/seeyeah/articles/36521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>