﻿<?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 技术文集-随笔分类-C#</title><link>http://www.cnitblog.com/seeyeah/category/3169.html</link><description>不在乎选择什么，而在乎坚持多久……</description><language>zh-cn</language><lastBuildDate>Wed, 14 May 2008 14:02:07 GMT</lastBuildDate><pubDate>Wed, 14 May 2008 14:02:07 GMT</pubDate><ttl>60</ttl><item><title>你真的了解Ioc与AOP吗？</title><link>http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 14 May 2008 13:29:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/43719.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/43719.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/43719.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.cnblogs.com/zhenyulu/articles/233966.html">http://www.cnblogs.com/zhenyulu/articles/233966.html</a><br>
<hr>
<p>本系列的全部源代码及二进制文件可以从这里下载：<a href="http://www.cnblogs.com/Files/zhenyulu/IocInCSharp.rar"><u><font color=#0000ff>IocInCSharp.rar</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/233966.html"><u><font color=#800080>你真的了解Ioc与AOP吗？（1）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/233968.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（2）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/234069.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（3）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/234075.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（4）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/234074.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（5）</font></u></a> </p>
<hr width="95%">
<p>本部分示例代码请参考"src\Step1"、"src\Step2"目录</p>
<p>你真的了解Ioc与AOP吗？我现在还不是很了解，而且越学习越发现自己了解的很少，Ioc与AOP中蕴涵了大量的能量等待我们去开发。在这个系列中，我仅仅利用Sping.net这个框架向大家展示一下Ioc与AOP的强大功能（呵呵，其实写这段话的目的是因为&#8220;文章题目&#8221;牛皮吹得有点大了，给自己个台阶下罢了）。</p>
<p>在这个系列中一共包含6个案例，从简单到复杂，也是对问题分解、思考和解决的一个过程，它们分别是：（1）类之间的依赖；（2）接口依赖；（3）基于配置文件和Reflection的工厂模式；（4）使用Spring.net实现Ioc；（5）Romoting；（6）利用Ioc在不动一行代码的情况下实现Remoting。为了更好的理解文中的内容，最好顺序阅读。</p>
<p>作为一个应用系统，代码复用至关重要。如果在你的设计中，类与类存在很强的相互关联，那么你会发现在重用这些组件时就存在很严重的问题。在Step1到Step3-Reflection的例子中，我们试图 利用&#8220;针对接口编程&#8221;以及自己设计的Ioc对系统进行解耦。在Step3到Step5的例子中，我们将利用Spring.net提供的Ioc框架，轻松完成解耦以及系统改造等工作。</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/43719.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-05-14 21:29 <a href="http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Scott Mitchell的ASP.NET2.0数据指南中文版索引 【转载】</title><link>http://www.cnitblog.com/seeyeah/archive/2008/04/24/42710.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 24 Apr 2008 14:05:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/04/24/42710.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/42710.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/04/24/42710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/42710.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/42710.html</trackback:ping><description><![CDATA[摘至：<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/lovecherry/archive/2006/07/02/440840.html"><u><font color=#800080>【翻译】Scott Mitchell的ASP.NET2.0数据指南中文版索引</font></u></a> <br>
<hr>
<a href="http://www.asp.net/learn/dataaccess/default.aspx?tabid=63" target=_blank><u><font color=#0000ff>英文版本</font></u></a><br><br>
<dt>
<p>导言</p>
<ul>
    <li><a href="http://blog.joycode.com/saucer/articles/77807.aspx" target=_blank><u><font color=#0000ff>创建一个数据访问层</font></u></a>
    <li><a href="http://reeezak.cnblogs.com/archive/2006/06/24/434439.html" target=_blank><u><font color=#0000ff>创建一个业务逻辑层</font></u></a>
    <li><a href="http://yuyijq.cnblogs.com/archive/2006/06/25/435218.html" target=_blank><u><font color=#0000ff>母板页和站点导航</font></u></a>&nbsp; </li>
</ul>
<dt>基本报表&nbsp;
<ul>
    <li><a href="http://eddie005.cnblogs.com/articles/UsingObjectDataSource.html" target=_blank><u><font color=#0000ff>使用ObjectDataSource展现数据</font></u><a href="http://www.asp.net/learn/dataaccess/tutorial04cs.aspx?tabid=63"></a> </a>
    <li><a href="http://eddie005.cnblogs.com/archive/2006/06/26/DeclarativeParameters.html" target=_blank><u><font color=#0000ff>声明参数</font></u></a>
    <li><a href="http://eddie005.cnblogs.com/archive/2006/06/27/SetParameters.html" target=_blank><u><font color=#0000ff>编程设置ObjectDataSource的参数值</font></u></a> </li>
</ul>
<dt>主/从&nbsp;
<ul>
    <li><a href="http://lidong.cnblogs.com/archive/2006/06/23/434105.html" target=_blank><u><font color=#0000ff>使用DropDownList过滤的主/从报表</font></u></a>&nbsp;&nbsp;&nbsp;
    <li><a href="http://lidong.cnblogs.com/archive/2006/06/28/437704.html" target=_blank><u><font color=#0000ff>使用两个DropDownList过滤的主/从报表</font></u></a>
    <li><a href="http://lidong.cnblogs.com/archive/2006/07/05/443203.html" target=_blank><u><font color=#0000ff>跨页面的主/从报表</font></u></a>&nbsp;
    <li><a href="http://lidong.cnblogs.com/archive/2006/07/05/443207.html" target=_blank><u><font color=#0000ff>使用GridView 和DetailView实现的主/从报表</font></u></a> </li>
</ul>
<dt>自定义格式化&nbsp;
<ul>
    <li><a href="http://zhzkl.cnblogs.com/archive/2006/07/01/440614.html" target=_blank><u><font color=#0000ff>基于数据的自定义格式化</font></u></a>
    <li><a href="http://reeezak.cnblogs.com/archive/2006/07/06/444315.html" target=_blank><font color=#0000ff><u>在GridView控件中使用TemplateField </u></font></a>
    <li><a href="http://reeezak.cnblogs.com/archive/2006/07/06/444700.html" target=_blank><u><font color=#0000ff>在DetailsView控件中使用TemplateField</font></u></a>
    <li><a href="http://reeezak.cnblogs.com/archive/2006/07/07/445611.html" target=_blank><u><font color=#0000ff>使用FormView 的模板</font></u></a> <a href="http://reeezak.cnblogs.com/archive/2006/07/09/446444.html" target=_blank>
    <li>在GridView的页脚中显示统计信息 </a></li>
</ul>
<dt>&nbsp;&nbsp;编辑插入和删除数据&nbsp;
<ul>
    <li><a href="http://www.cnblogs.com/eddie005/archive/2006/08/28/488507.html" target=_blank><u><font color=#0000ff>概述插入、更新和删除数据</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/eddie005/archive/2006/08/18/EventsOfDataWebControl.html" target=_blank><u><font color=#0000ff>研究插入、更新和删除的关联事件</font></u></a>
    <li><a href="http://www.cnblogs.com/eddie005/archive/2006/08/08/BLLAndDALExceptions.html" target=_blank><u><font color=#0000ff>在ASP.NET页面中处理BLL/DAL层的异常</font></u></a>
    <li><a href="http://truly.cnblogs.com/archive/2006/06/27/437107.html" target=_blank><u><font color=#0000ff>给编辑和新增界面增加验证控件</font></u></a>&nbsp;
    <li><a href="http://truly.cnblogs.com/archive/2006/06/29/438526.html" target=_blank><u><font color=#0000ff>定制数据修改界面</font></u></a>
    <li><a href="http://www.cnblogs.com/eddie005/archive/2006/08/01/OptimisticConcurrency.html" target=_blank><u><font color=#0000ff>实现开放式并发&nbsp;</font></u></a>&nbsp;
    <li><a href="http://chagel.cnblogs.com/archive/2006/07/19/454440.html" target=_blank><u><font color=#0000ff>为删除数据添加客户端确认</font></u></a>
    <li><a href="http://chagel.cnblogs.com/articles/456883.html" target=_blank><u><font color=#0000ff>基于用户对修改数据进行限制</font></u></a> </li>
</ul>
<p>分页和排序&nbsp; </p>
<ul>
    <li><a href="http://www.cnblogs.com/lovecherry/archive/2006/08/25/486077.html"><u><font color=#0000ff>分页和排序报表数据</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/10/523992.html" target=_blank><u><font color=#0000ff>大数据量时提高分页的效率</font></u></a>
    <li><a href="http://www.cnblogs.com/lovecherry/archive/2006/09/05/494998.html" target=_blank><u><font color=#0000ff>排序自定义分页数据</font></u></a>
    <li><a href="http://blog.csdn.net/ksnoopy/archive/2006/08/27/1125097.aspx" target=_blank><u><font color=#0000ff>创建自定义排序用户界面</font></u></a>&nbsp;<a href="http://reeezak.cnblogs.com/archive/2006/07/06/444315.html" target=_blank></a> </li>
</ul>
<p>自定义按钮行为&nbsp; </p>
<ul>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/04/521400.html" target=_blank><u><font color=#0000ff>GridView里的Button &nbsp;</font></u></a> </li>
</ul>
<p>使用DataList和Repeater显示数据&nbsp; </p>
<ul>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/07/521593.html" target=_blank><u><font color=#0000ff>用DataList和Repeater来显示数据</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/08/523252.html" target=_blank><u><font color=#0000ff>格式化DataList和Repeater的数据</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/13/527119.html" target=_blank><u><font color=#0000ff>使用DataList来一行显示多条记录</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/17/527593.html" target=_blank><u><font color=#0000ff>数据控件的嵌套</font></u></a> </li>
</ul>
<p>使用DataList和Repeater过滤数据&nbsp; </p>
<ul>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/23/533180.html" target=_blank><u><font color=#0000ff>使用DropDownList过滤的主/从报表</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/26/537273.html" target=_blank><u><font color=#0000ff>跨页面的主/从报表</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/10/30/539128.html" target=_blank><u><font color=#0000ff>使用Repeater和DataList实现的主/从报表</font></u></a>&nbsp; </li>
</ul>
<p>使用DataList编辑和删除数据&nbsp; </p>
<ul>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/03/546974.html" target=_blank><u><font color=#0000ff>综叙：在DataList里编辑和删除数据</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/07/551210.html" target=_blank><u><font color=#0000ff>批量更新</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/08/551745.html" target=_blank><u><font color=#0000ff>处理BLL和DAL的异常</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/13/553095.html"><u><font color=#0000ff>在编辑和插入界面里添加验证控件</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/15/559289.html"><u><font color=#0000ff>自定义DataList编辑界面</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/21/561125.html"><u><font color=#0000ff>实现开放式并发</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/27/568200.html"><u><font color=#0000ff>为删除数据添加客户端确认</font></u></a>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/11/30/573628.html"><u><font color=#0000ff>基于用户对修改数据进行限制</font></u></a>&nbsp; </li>
</ul>
<p>DataList和Repeater的分页和排序<br></p>
<ul>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/12/04/577194.html"><u><font color=#0000ff>DataList和Repeater数据分页</font></u></a>&nbsp;&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/12/08/586061.html"><u><font color=#0000ff>DataList和Repeater数据排序（一）</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/12/14/592373.html"><u><font color=#0000ff>DataList和Repeater数据排序（二）</font></u></a>&nbsp;
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/12/14/592374.html"><u><font color=#0000ff>DataList和Repeater数据排序（三）</font></u></a>&nbsp; </li>
</ul>
<p>DataList和Repeater的自定义按钮行为</p>
<ul>
    <li><a href="http://www.cnblogs.com/ilovejolly/archive/2006/12/15/593555.html"><u><font color=#0000ff>DataList和Repeater里的自定义button</font></u></a> </li>
</ul>
<p>特别感谢<a href="http://www.cnblogs.com/ilovejolly/" target=_blank><u><font color=#0000ff>有些伤感</font></u></a>，近一半的文档都是他翻译的。<br><br>46之后可以在下面的地址找到：<br><br><font face="Times New Roman" color=#000000 size=3>http://www.cnblogs.com/Reeezak/archive/2007/08/13/853925.html</font></p>
<p><font face="Times New Roman" color=#000000 size=3>50之后可以在下面的地址找到：</font></p>
<p><font face="Times New Roman" color=#000000 size=3>http://blog.csdn.net/heker2007/archive/2007/06.aspx</font></p>
</dt>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/42710.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-04-24 22:05 <a href="http://www.cnitblog.com/seeyeah/archive/2008/04/24/42710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Silverlight技巧，诀窍，教程和链接 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/04/11/42269.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 11 Apr 2008 15:26:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/04/11/42269.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/42269.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/04/11/42269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/42269.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/42269.html</trackback:ping><description><![CDATA[<p>【原文地址】<a title=在Silverlight中做单元测试 href="http://weblogs.asp.net/scottgu/pages/silverlight-posts.aspx"><u><font color=#0000ff>Silverlight Tips, Tricks, Tutorials and Links Page </font></u></a></p>
<p>我将使用本页链接到有关Silverlight 2的文章和贴子（包括我写的和别人写的），请经常回来查看新的内容，因为我才开始。 </p>
<h3><u>入门教程</u></h3>
<ul>
    <li>
    <p><a href="http://blog.joycode.com/scottgu/archive/2008/02/23/114891.aspx" target=_blank mce_href="http://blog.joycode.com/scottgu/archive/2008/02/23/114891.aspx"><u><font color=#0000ff>Silverlight 2 初览</font></u></a>: 我建议先读这个贴子，如果你正考虑开始Silverlight 2开发的话。该文不仅对Silverlight 2提供的功能做了高层次的描述，还链接到了一个<a href="http://blog.joycode.com/scottgu/archive/2008/02/29/114918.aspx" target=_blank mce_href="http://blog.joycode.com/scottgu/archive/2008/02/29/114918.aspx"><u><font color=#0000ff>八个贴子的系列教程</font></u></a>，该教程对如何建造一个Digg客户端例程做了示范。这些教程贴子对Silverlight 2和WPF开发的概念提供了很好的介绍。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blog.joycode.com/scottgu/archive/2008/03/02/114920.aspx" target=_blank mce_href="http://blog.joycode.com/scottgu/archive/2008/03/02/114920.aspx"><u><font color=#0000ff>使用Expression Blend开发Silverlight 2应用 -- 初览</font></u></a>: 我建议下载Expression Blend 2.5 三月份预览版，按本教程贴子的步骤进行。我认为它很好地展示了Expression Blend的一些常见功能，用它建造了一个IM聊天客户端例程。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://www.jeff.wilcox.name/2008/03/31/silverlight2-unit-testing/" target=_blank mce_href="http://www.jeff.wilcox.name/2008/03/31/silverlight2-unit-testing/"><u><font color=#0000ff>Unit Testing with Silverlight 2</font></u></a>: Silverlight开发团队的Jeff Wilcox有一篇精彩贴子，讨论如何使用Silverlight SDK中的单元测试框架单元测试Silverlight 2应用。</p>
    </li>
</ul>
<h3><u>入门讲座</u></h3>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/mharsh/archive/2008/03/05/slides-and-demos-from-my-mix-08-talk.aspx" target=_blank mce_href="http://blogs.msdn.com/mharsh/archive/2008/03/05/slides-and-demos-from-my-mix-08-talk.aspx"><u><font color=#0000ff>Building Rich Internet Applications with Silverlight (Part 1 and 2)</font></u></a>: Joe Stegman和Mike Harsh在MIX 08上做了这分成2个部分的讲座， 讨论如何使用Silverlight建造应用。你可以使用上面的链接观看他们讲座的录像和下载相关讲义和示范例程。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://scorbs.com/2008/03/09/mix08-creating-rich-dynamic-user-interfaces-with-silverlight-2-controls/" target=_blank mce_href="http://scorbs.com/2008/03/09/mix08-creating-rich-dynamic-user-interfaces-with-silverlight-2-controls/"><u><font color=#0000ff>Creating Rich, Dynamic User Interfaces with Silverlight 2 Controls</font></u></a>: Karen Corby在MIX 08上有个极棒的讲座，很好地解释了样式，控件模板，用户控件等等。你可以在<a href="http://scorbs.com/2008/03/14/flickrviewr/" target=_blank mce_href="http://scorbs.com/2008/03/14/flickrviewr/"><u><font color=#0000ff>这里</font></u></a>运行和下载她完整的FlickR应用。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://weblogs.asp.net/scottgu/archive/2008/03/09/my-presentations-in-arizona-this-tuesday.aspx" target=_blank mce_href="http://weblogs.asp.net/scottgu/archive/2008/03/09/my-presentations-in-arizona-this-tuesday.aspx"><u><font color=#0000ff>我的Silverlight入门讲座</font></u></a>: 你可以下载我最近在亚利桑那做的&#8220;Silverlight 2入门&#8221;讲座的讲义和示范例程，请随意在你自己的讲座中重用这些讲义。</p>
    </li>
</ul>
<h3><u>文档链接</u></h3>
<ul>
    <li>
    <p><a href="http://silverlight.net/quickstarts/managed.aspx" target=_blank mce_href="http://silverlight.net/quickstarts/managed.aspx"><u><font color=#0000ff>Silverlight 2 QuickStart Tutorials</font></u></a>: 这些示范教程在上手Silverlight时会非常有用。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/brada/archive/2008/03/16/silverlight-2-developer-poster.aspx" target=_blank mce_href="http://blogs.msdn.com/brada/archive/2008/03/16/silverlight-2-developer-poster.aspx"><u><font color=#0000ff>Silverlight 2 Developer Poster:</font></u></a> 下载和打印Silverlight 2开发者海报。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/sburke/archive/2008/03/05/silverlight-2-beta-1-controls-available-including-source-and-unit-tests.aspx" target=_blank mce_href="http://blogs.msdn.com/sburke/archive/2008/03/05/silverlight-2-beta-1-controls-available-including-source-and-unit-tests.aspx"><u><font color=#0000ff>Silverlight Control Source and Unit Tests</font></u></a>: Shawn Burke提供了内置的Silverlight控件的源码以及相关单元测试的链接。 </p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://msdn2.microsoft.com/en-us/library/bb404700.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/bb404700.aspx"><u><font color=#0000ff>MSDN Silverlight 2 Beta1 Online Documentation</font></u></a>: 这个网页提供了正式的Silverlight 2文档的链接。你可以在<a href="http://blogs.msdn.com/silverlight_sdk/archive/2008/03/03/silverlight-offline-documentation-march-2008.aspx" target=_blank mce_href="http://blogs.msdn.com/silverlight_sdk/archive/2008/03/03/silverlight-offline-documentation-march-2008.aspx"><u><font color=#0000ff>这里</font></u></a>下载离线版本。</p>
    </li>
</ul>
<h3><u>教程和例程</u></h3>
<ul>
    <li>
    <p><a href="http://silverlight.net/Learn/videocat.aspx?cat=2" target=_blank mce_href="http://silverlight.net/Learn/videocat.aspx?cat=2"><u><font color=#0000ff>"How Do I?" with Silverlight</font></u></a>: 这个链接连到了含有一堆Silverlight 2录像教程的网页。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://sessions.visitmix.com/?selectedSearch=Hard Rock&amp;searchPlink=true" target=_blank><u><font color=#0000ff>Hard Rock Memorabilia Sample</font></u></a>: Vertigo Software公司的Scott Stanfield讨论三月份发布的使用Silverlight 2建造的很酷的<a href="http://memorabilia.hardrock.com/" target=_blank mce_href="http://memorabilia.hardrock.com/"><u><font color=#0000ff>Hard Rock Memorabilia</font></u></a>网站。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://geekswithblogs.net/SilverBlog/archive/2008/03/25/silverlight-2.0-application-with-multiscaleimage-control-and-deep-zoom-composer.aspx" target=_blank mce_href="http://geekswithblogs.net/SilverBlog/archive/2008/03/25/silverlight-2.0-application-with-multiscaleimage-control-and-deep-zoom-composer.aspx"><u><font color=#0000ff>Using Deep Zoom with Silverlight 2</font></u></a>: Jacek Ciereszko有一个很好的博客贴子，描述了如何使用Silverlight 2的 &#8220;Deep Zoom&#8221;功能实现跟Hard Rock例程类似的图像放大功能。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://silverlight.net/blogs/msnow/archive/2008/03/25/introduction.aspx" target=_blank mce_href="http://silverlight.net/blogs/msnow/archive/2008/03/25/introduction.aspx"><u><font color=#0000ff>Game Programming with Silverlight:</font></u></a> Mike Snow正打造一个分成十一个部分的博客系列，讨论如何使用Silverlight开发在线游戏。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://www.jeff.wilcox.name/2008/04/01/link-cloud/" target=_blank mce_href="http://www.jeff.wilcox.name/2008/04/01/link-cloud/"><u><font color=#0000ff>Homepage "Link Cloud" application</font></u></a>: Jeff Wilcox讨论他建造的一个很酷的标签云应用。</p>
    </li>
</ul>
<h3><u>部署体验</u></h3>
<ul>
    <li>
    <p><a href="http://timheuer.com/blog/archive/2008/03/25/creating-a-great-silverlight-deployment-experience.aspx" target=_blank mce_href="http://timheuer.com/blog/archive/2008/03/25/creating-a-great-silverlight-deployment-experience.aspx"><u><font color=#0000ff>Providing a Great Silverlight Deployment Experience</font></u></a>: Tim Heuer有个很好的贴子，讨论可以为你所用的技术来优化Silverlight安装体验。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/brada/archive/2008/03/14/using-silverlight-2-on-a-production-web-server.aspx" target=_blank mce_href="http://blogs.msdn.com/brada/archive/2008/03/14/using-silverlight-2-on-a-production-web-server.aspx"><u><font color=#0000ff>Using Silverlight 2 on a Production Web Server:</font></u></a> Brad Abrams有个很好的贴子，讨论在把Silverlight .xap文件拷贝到IIS web服务器时需要注意的几件事情。 </p>
    </li>
</ul>
<h3><u>控件模板</u></h3>
<ul>
    <li>
    <p><a href="http://mattberseth.com/blog/2008/03/creating_a_custom_skin_for_sil.html" target=_blank mce_href="http://mattberseth.com/blog/2008/03/creating_a_custom_skin_for_sil.html"><u><font color=#0000ff>Creating a Custom Skin for Silverlight's Button Control:</font></u></a> Matt Berseth的一个精彩好贴，讨论Silverlight控件的皮肤和样式功能。 </p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/sburke/archive/2008/03/22/tutorial-writing-a-templated-silverlight-2-control.aspx" target=_blank mce_href="http://blogs.msdn.com/sburke/archive/2008/03/22/tutorial-writing-a-templated-silverlight-2-control.aspx"><u><font color=#0000ff>Writing a Templated Silverlight Control</font></u></a>: Shawn Burke有个精彩贴子，详细描述了如何创建定制的Silverlight模板控件。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/delay/archive/2008/03/22/improving-everyone-s-access-to-silverlight-2-s-generic-xaml-resources-silverlightdefaultstylebrowser-tool-and-source-code.aspx" target=_blank mce_href="http://blogs.msdn.com/delay/archive/2008/03/22/improving-everyone-s-access-to-silverlight-2-s-generic-xaml-resources-silverlightdefaultstylebrowser-tool-and-source-code.aspx"><u><font color=#0000ff>Improving Access to Silverlight's Generic.xaml Resources</font></u></a> (也阅读 <a href="http://blogs.msdn.com/delay/archive/2008/03/22/improved-access-to-silverlight-2-s-generic-xaml-resources-silverlightdefaultstylebrowser-available-via-clickonce.aspx" target=_blank mce_href="http://blogs.msdn.com/delay/archive/2008/03/22/improved-access-to-silverlight-2-s-generic-xaml-resources-silverlightdefaultstylebrowser-available-via-clickonce.aspx"><u><font color=#0000ff>这里的Part 2</font></u></a>): David Anson有个很棒的工具，示范如何查看和提取内置Silverlight控件的默认XAML样式。</p>
    </li>
</ul>
<h3><u>ListBox和ScrollViewer场景</u></h3>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/delay/archive/2008/03/05/lb-sv-faq-examples-notes-tips-and-more-for-silverlight-2-beta-1-s-listbox-and-scrollviewer-controls.aspx" target=_blank mce_href="http://blogs.msdn.com/delay/archive/2008/03/05/lb-sv-faq-examples-notes-tips-and-more-for-silverlight-2-beta-1-s-listbox-and-scrollviewer-controls.aspx"><u><font color=#0000ff>Ultimate ListBox and ScrollViewer Frequently Asked Questions Guide</font></u></a>: David Anson，Silverlight ListBox和ScrollViewer控件的开发者，编篡了这个很棒的，关于所有这些控件的FAQ以及你可以使用它们的场景。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/delay/archive/2008/03/12/lb-sv-why-three-wacky-uses-for-silverlight-2-s-listbox-and-scrollviewer.aspx" target=_blank mce_href="http://blogs.msdn.com/delay/archive/2008/03/12/lb-sv-why-three-wacky-uses-for-silverlight-2-s-listbox-and-scrollviewer.aspx"><u><font color=#0000ff>Cool (wacky) uses of the ListBox and ScrollViewer controls</font></u></a>: David Anson的又一篇精彩贴子，展示了数据和控件模板的灵活性。</p>
    </li>
</ul>
<h3><u>DataGrid场景</u></h3>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/scmorris/archive/2008/03/21/using-the-silverlight-datagrid.aspx" target=_blank mce_href="http://blogs.msdn.com/scmorris/archive/2008/03/21/using-the-silverlight-datagrid.aspx"><u><font color=#0000ff>Using the Silverlight DataGrid</font></u></a> and <a href="http://blogs.msdn.com/scmorris/archive/2008/03/27/defining-columns-for-a-silverlight-datagrid.aspx" target=_blank mce_href="http://blogs.msdn.com/scmorris/archive/2008/03/27/defining-columns-for-a-silverlight-datagrid.aspx"><u><font color=#0000ff>Defining Columns for a Silverlight DataGrid</font></u></a>: Scott Morrison开始了一个精彩贴子系列，描述如何使用新的Silverlight 2 DataGrid控件（他是相关项目的主管，绝对精通！）</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/swiss_dpe_team/archive/2008/03/17/silverlight-2-beta1-wcf-linq-to-sql-a-powerfull-combination.aspx" target=_blank mce_href="http://blogs.msdn.com/swiss_dpe_team/archive/2008/03/17/silverlight-2-beta1-wcf-linq-to-sql-a-powerfull-combination.aspx"><u><font color=#0000ff>Using Silverlight 2's DataGrid with WCF + LINQ to SQL</font></u></a>: 这个15分钟的录像博客示范了如何在服务器上建造一个LINQ to SQL对象模型，然后用WCF将其发布，然后示范了如何建造一个使用了新的Silverlight DataGrid控件的Silverlight客户端，该客户端调用WCF服务获取LINQ to SQL数据，将其绑定到DataGrid上。 </p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/03/27/10290.aspx" target=_blank mce_href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/03/27/10290.aspx"><u><font color=#0000ff>Simple Editing of Web Service Data in a DataGrid:</font></u></a> Mike Taulty有一篇好贴，展示如何在服务器上建造WCF服务，然后从Silverlight 2客户端使用它来获取数据，绑定到DataGrid，允许用户更新数据行，添加/删除数据行，然后使用 Silverlight 2 Beta1将数据保存到服务器上。 </p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://mattberseth.com/blog/2008/03/sorting_with_silverlight_2s_da.html" target=_blank mce_href="http://mattberseth.com/blog/2008/03/sorting_with_silverlight_2s_da.html"><u><font color=#0000ff>Sorting with Silverlight 2's DataGrid Control:</font></u></a> Silverlight 2 Beta1中的DataGrid控件还没有内置的列数据排序支持（将在Beta2中提供），但这并没有阻止Matt Berseth！ 在这个贴子里，他展示了如何使用一个定制的header列方法来实现排序。也看一下Matt的 <a href="http://mattberseth.com/blog/2008/03/a_quick_look_at_silverlight_2s.html" mce_href="http://mattberseth.com/blog/2008/03/a_quick_look_at_silverlight_2s.html"><u><font color=#0000ff>这里</font></u></a>的贴子，该文提供了一个DataGrid测试页面，展示了目前DataGrid的若干特性。 </p>
    </li>
</ul>
<h3><u>Web Services 和 Networking</u></h3>
<ul>
    <li>
    <p><a href="http://blogs.msdn.com/silverlight_sdk/archive/2008/03/27/web-services-and-silverlight.aspx" target=_blank mce_href="http://blogs.msdn.com/silverlight_sdk/archive/2008/03/27/web-services-and-silverlight.aspx"><u><font color=#0000ff>Web Services and Silverlight</font></u></a>: 这个有用的贴子讨论了如何在Silverlight中使用web服务，并且提供了相关快速入门例程和文档的链接。</p>
    </li>
</ul>
<ul>
    <li>
    <p><a href="http://timheuer.com/blog/archive/2008/03/14/calling-web-services-with-silverlight-2.aspx" target=_blank mce_href="http://timheuer.com/blog/archive/2008/03/14/calling-web-services-with-silverlight-2.aspx"><u><font color=#0000ff>Calling Web Services with Silverlight 2 (Part 1)</font></u></a> and <a href="http://timheuer.com/blog/archive/2008/03/19/calling-services-with-silverlight-part-2.aspx" target=_blank mce_href="http://timheuer.com/blog/archive/2008/03/19/calling-services-with-silverlight-part-2.aspx"><u><font color=#0000ff>(Part 2)</font></u></a>: Tim Heuer的几篇精彩贴子，讨论如何使用Silverlight调用web服务。</p>
    </li>
</ul>
<h3><u>Video场景</u></h3>
<ul>
    <li>
    <p><a href="http://sessions.visitmix.com/?selectedSearch=Encoding Video for Microsoft Silverlight&amp;searchPlink=true" target=_blank><u><font color=#0000ff>Encoding Video for Microsoft Silverlight Delivery</font></u></a>: Ben Waggoner在MIX 08上的讲座，讨论编码Silverlight录像的最佳实践。</p>
    </li>
</ul>
<h3><u>Accessibility 和 508相容性</u></h3>
<ul>
    <li>
    <p><a href="http://www.visitmix.com/blogs/Joshua/Silverlight-2-Accessibility-with-Mark-Rideout/" target=_blank mce_href="http://www.visitmix.com/blogs/Joshua/Silverlight-2-Accessibility-with-Mark-Rideout/"><u><font color=#0000ff>Accessibility in Silverlight 2</font></u></a>: Silverlight开发团队的Mark Rideout讨论 Silverlight 2 中的accessibility支持，以及如何使用Silverlight建造与section 508相容的accessible方案。</p>
    </li>
</ul>
<p>希望本文对你有所帮助，</p>
<p>Scott</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/42269.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-04-11 23:26 <a href="http://www.cnitblog.com/seeyeah/archive/2008/04/11/42269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>13 Tips to Comment Your Code</title><link>http://www.cnitblog.com/seeyeah/archive/2008/03/27/41548.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 27 Mar 2008 03:14:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/03/27/41548.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/41548.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/03/27/41548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/41548.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/41548.html</trackback:ping><description><![CDATA[有效注释代码的13个技巧&#8230;&#8230;<br><a href="http://www.devtopics.com/13-tips-to-comment-your-code/">URL:http://www.devtopics.com/13-tips-to-comment-your-code/</a><br><br>
<hr>
<p><em>This article was written by Jos&#233; M. Aguilar in Spanish on his excellent blog </em><a href="http://www.variablenotfound.com/2007/12/13-consejos-para-comentar-tu-cdigo.html" target=_blank><em><u><font color=#0000ff>Variable Not Found</font></u></em></a><em>, and was translated, edited and republished here by Timm Martin (and <a href="http://www.google.com/translate?u=http%3A%2F%2Fwww.variablenotfound.com%2F2007%2F12%2F13-consejos-para-comentar-tu-cdigo.html&amp;langpair=es%7Cen&amp;hl=en&amp;ie=UTF8" target=_blank><u><font color=#0000ff>Google Translator</font></u></a>) with permission from Mr. Aguilar.</em></p>
<p>Following are 13 tips on how to comment your source code so that it is easier to understand and maintain over time.</p>
<p><span id=more-213></span></p>
<h3>1. Comment each level</h3>
<p>Comment each code block, using a uniform approach for each level.&nbsp; For example:
<ul>
    <li>For each class, include a brief description, author and date of last modification
    <li>For each method, include a description of its purpose, functions, parameters and results </li>
</ul>
<p>Adopting comment standards is important when working with a team.&nbsp; Of course, it is acceptable and even advisable to use comment conventions and tools (such as XML in C# or Javadoc for Java) to facilitate this task.<br>
<h3>2. Use paragraph comments</h3>
<p>Break code blocks into multiple "paragraphs" that each perform a single task, then add a comment at the beginning of each block to instruct the reader on what is about to happen.<br>
<blockquote><code>// Check that all data records<br>// are correct <br>foreach (Record record in records) <br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (rec.checkStatus()==Status.OK)<br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. . . <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>} <br>// Now we begin to perform <br>// transactions <br>Context ctx = new ApplicationContext(); <br>ctx.BeginTransaction();<br>. . .</code>
<p>&#160;</p>
</blockquote>
<h3>3. Align comments in consecutive lines</h3>
<p>For multiple lines of code with trailing comments, align the comments so they will be easy to read.</p>
<blockquote>
<p><code>const MAX_ITEMS = 10; // </code><code>maximum number of packets</code> <br><code>const MASK = 0x1F;&nbsp;&nbsp;&nbsp; // m</code><code>ask bit TCP</code> </p>
</blockquote>
<p>Some developers use tabs to align comments, while others use spaces.&nbsp; Because tab stops can vary among editors and IDEs, the best approach is to use spaces. </p>
<h3>4. Don't insult the reader's intelligence</h3>
<p>Avoid obvious comments such as: </p>
<blockquote>
<p><code>if (a == 5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// if a equals 5 <br>&nbsp;&nbsp;&nbsp;&nbsp;counter = 0; // set the counter to zero</code></p>
</blockquote>
<p>This wastes your time writing needless comments and distracts the reader with details that can be easily deduced from the code. </p>
<h3>5. Be polite</h3>
<p>Avoid rude comments like, <em>"Notice the stupid user has entered a negative number,"</em> or <em>"This fixes the side effect produced by the pathetically inept implementation of the initial developer."&nbsp; </em>Such comments do not reflect well upon their author, and you never know who may read these comments in the future: your boss, a customer, or the pathetically inept developer you just insulted. </p>
<h3>6. Get to the point</h3>
<p>Don't write more in comments than is needed to convey the idea.&nbsp; Avoid ASCII art, jokes, poetry and <a href="http://worsethanfailure.com/Articles/Hyperverbosity-.aspx" target=_blank><u><font color=#0000ff>hyperverbosity</font></u></a>.&nbsp; In short, keep the comments simple and direct. </p>
<h3>7. Use a consistent style</h3>
<p>Some people believe that comments should be written so that non-programmers can understand them.&nbsp; Others believe that comments should be directed at developers only.&nbsp; In any event, as stated in <a href="http://particletree.com/features/successful-strategies-for-commenting-code/" target=_blank><u><font color=#0000ff>Successful Strategies for Commenting Code</font></u></a>, what matters is that comments are consistent and always targeted to the same audience.&nbsp; Personally, I doubt many non-developers will be reading code, so comments should target other developers. </p>
<h3>8. Use special tags for internal use</h3>
<p>When working on code as a team, adopt a consistent set of tags to communicate among programmers.&nbsp; For example, many teams use a "TODO:" tag to indicate a section of code that requires additional work: </p>
<blockquote>
<p><code>int Estimate(int x, int y) <br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;// TODO: implement the calculations <br>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}</code></p>
</blockquote>
<p>Tag comments don't explain code; rather they seek attention or deliver a message.&nbsp; But if you use this technique, remember to follow up and actually do what the message is asking. </p>
<h3>9. Comment code while writing it</h3>
<p>Add comments while you write code and it's fresh in your memory.&nbsp; If you leave comments until the end, it will take you twice as long, if you do it at all.&nbsp; "I have no time to comment," "I'm in a hurry," and "The project is delayed" are all simply excuses to avoid documenting your code.&nbsp; Some developers believe you should <a href="http://freshmeat.net/articles/view/238/" target=_blank><u><font color=#0000ff>write comments before code</font></u></a> as a way to plan out your ultimate solution.&nbsp; For example:</p>
<blockquote>
<p><code>public void ProcessOrder()</code>&nbsp;<br><code>{</code><br><code>&nbsp;&nbsp;&nbsp; // </code><code>Make sure the products are available</code><br><code>&nbsp;&nbsp;&nbsp; // </code><code>Check that the customer is valid</code> <br><code>&nbsp;&nbsp;&nbsp; // </code><code>Send the order to the store</code> <br><code>&nbsp;&nbsp;&nbsp; // </code><code>Generate bill</code> <br><code>}</code></p>
</blockquote>
<h3>10. Write comments as if they were for you (in fact, they are)</h3>
<p>When it comes to commenting code, think not only about the developers who will maintain your code in the future, but also think about yourself.&nbsp; In the words of the great <a href="http://haacked.com/archive/2007/06/25/understanding-productivity-differences-between-developers.aspx" target=_blank><u><font color=#0000ff>Phil Haack</font></u></a>: </p>
<blockquote>
<p>"As soon as a line of code is laid on the screen, you&#8217;re in maintenance mode on that piece of code."</p>
</blockquote>
<p>As a result, we ourselves will be the first beneficiaries (or victims) of our good (or bad) comments. </p>
<h3>11. Update comments when you update the code</h3>
<p>There is no point in commenting correctly on code if the comments are not changed with the code.&nbsp; Both code and comments must move in parallel, otherwise the comments will actually make life more difficult for developers who maintain your code.&nbsp; Pay special attention to refactoring tools that automatically update code but leave comments unchanged and hence obsolete in the same instant. </p>
<h3>12. The golden rule of comments: readable code</h3>
<p>One of the basic principles for many developers<strong>:</strong> <strong><em>Let your code speak for itself.</em></strong>&nbsp; Although one suspects this movement is led by programmers who do not like to write comments, it is true that self-explanatory code can go a long way toward making code that's easier to understand and can even render comments unnecessary.&nbsp; For example, the code in my <a href="http://www.variablenotfound.com/2007/11/interfaces-fluidos-fluent-interfaces.html" target=_blank><u><font color=#0000ff>Fluid Interfaces</font></u></a> article shows how clear self-explanatory code can be: </p>
<blockquote>
<p><code>Calculator calc = new Calculator();<br>calc.Set(0);<br>calc.Add(10);<br>calc.Multiply(2);<br>calc.Subtract(4);<br>Console.WriteLine( "Result: {0}", calc.Get() );</code></p>
</blockquote>
<p>In this example, comments are not needed and would likely violate tip #4.&nbsp; To facilitate readable code, you might consider using proper names (as described in the classic <a href="http://www.objectmentor.com/resources/articles/naming.htm" target=_blank><u><font color=#0000ff>Ottinger's Rules</font></u></a>), ensure correct indentation, and adopt <a href="http://www.google.com/search?q=coding+style+guides&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a" target=_blank><u><font color=#0000ff>coding style guides</font></u></a>.&nbsp; Failure to comply with this tip may result in comments that seem to <a href="http://blogs.dovetailsoftware.com/blogs/gsherman/archive/2007/05/11/are-your-code-comments-a-way-to-say-i-m-sorry-for-the-actual-code.aspx" target=_blank><u><font color=#0000ff>apologize</font></u></a> for bad code. </p>
<h3>13. Share these tips with your colleagues</h3>
<p>Although tip #10 shows how we ourselves benefit immediately from good comments, these tips will benefit all developers, especially in the context of team working together.&nbsp; Therefore, feel free to share these commenting tips with your colleagues to create code that is easier to understand and maintain.</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/41548.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-03-27 11:14 <a href="http://www.cnitblog.com/seeyeah/archive/2008/03/27/41548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#强化系列文章 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/03/14/40953.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 14 Mar 2008 13:51:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/03/14/40953.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/40953.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/03/14/40953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/40953.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/40953.html</trackback:ping><description><![CDATA[摘至<a class=HeaderMainTitle id=Header1_HeaderTitle href="http://www.cnblogs.com/firstyi/"><u><font color=#0000ff>永春阁</font></u></a><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/firstyi/archive/2008/01/31/1059938.html"><u><font color=#800080>C#强化系列文章 </font></u></a>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/40953.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-03-14 21:51 <a href="http://www.cnitblog.com/seeyeah/archive/2008/03/14/40953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>可插拔windows服务 </title><link>http://www.cnitblog.com/seeyeah/archive/2007/12/21/37969.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 21 Dec 2007 15:38:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/12/21/37969.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37969.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/12/21/37969.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37969.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37969.html</trackback:ping><description><![CDATA[转载：<a href="http://www.cnblogs.com/lodestar/archive/2007/04/18/718615.html">http://www.cnblogs.com/lodestar/archive/2007/04/18/718615.html</a><br>
<hr>
<p>如何实现可插拔的windows服务<br>关于windows服务的创建相关资源很多，园子里面也有很多这样的文章。<br>整理了一下相关blog如下，<br><a href="http://www.cnblogs.com/wuxilin/archive/2006/06/04/416838.html"><font color=#800080><u>http://www.cnblogs.com/wuxilin/archive/2006/06/04/416838.html</u></font></a><br><a href="http://www.cnblogs.com/wujm/archive/2005/05/12/154369.html"><font color=#0000ff><u>http://www.cnblogs.com/wujm/archive/2005/05/12/154369.html</u></font></a><br><a href="http://www.cnblogs.com/caca/archive/2005/02/25/109028.html"><font color=#0000ff><u>http://www.cnblogs.com/caca/archive/2005/02/25/109028.html</u></font></a><br><a href="http://www.cnblogs.com/laiwen/archive/2005/08/21/219590.html"><u><font color=#0000ff>http://www.cnblogs.com/laiwen/archive/2005/08/21/219590.html</font></u></a></p>
<p>归纳一下步骤大概如下：<br>1.创建服务:<br>1.1我们应该创建windows服务类型的project，IDE会自动从serviceBase类继承一个类出来，在这个类里面有on_star和on_stop两个方法，可以在里面写入启动逻辑和停止逻辑<br>在设计视图下我们可以修改service的属性<br>Autolog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否自动写入系统的日志文件<br>CanHandlePowerEvent&nbsp;&nbsp;&nbsp;&nbsp; 服务时候接受电源事件<br>CanPauseAndContinue&nbsp;&nbsp;&nbsp;&nbsp; 服务是否接受暂停或继续运行的请求<br>CanShutdown&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务是否在运行它的计算机关闭时收到通知，以便能够调用 OnShutDown 过程<br>CanStop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务是否接受停止运行的请求<br>ServiceName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务名<br>1.2选择服务组件,并切换到设计模式,右键-&gt;Add Installer,生成安装文件。安装文件中的属性修改可以参考下面的内容：<br>projectInstall参数修改Account(指定用户还是使用本地系统用户)<br>ServiceInstall参数修改：<br>描述名：Description，<br>显示名：DisplayName,<br>ServiName:服务名，要和刚才建立的服务名一一对应才行<br>StartType：(Manual:服务安装后，必须手动启动.Automatic:每次计算机重新启动时，服务都会自动启动;Disabled:服务无法启动)</p>
<p>2安装<br>安装服务要使用微软提供的工具InstallUtil，这个工具在c:/windows/wicrosoft.net/framework/[version]中<br>使用InstallUtil 安装，使用InstallUtil /u 反安装服务</p>
<p>如果还有什么可以参考刚才说的那几个blog，ok一切都很简单。但是如果要做为一个企业级的应用，往往会有别的场景需求，下面说一下我曾碰到的场景要求<br>1.我们的windows服务可能不止满足一种业务逻辑，比如：如果你的机器安装了oracle的话，就会有OracleService服务，我们启动数据库的时候可以只是启动tns服务和OracleService服务就可以了，但是实际上启动OracleService服务的同时会启动好几个服务，例如:DBWR(数据文件写入),LGWR(日志文件写入),SMON(系统监护),PMON(用户进程监),CKPT(检查点,同步数据文件,日志文件,控制文件等)。有时为了性能的考虑，一个服务也可能要多线程的运行业务逻辑。比如一个导入文件的数据接口服务，如果数据量非常大就要这样考虑。一般如果执行多个任务，可以有两种方法：1.开多个线程；2.在一个线程中顺序进行(可以加上时间控制)。我觉得这里最灵活的方法是用.net本省的多线程支持来解决。<br>2.要能在不改变系统结构的情况下，可以非常快速的支持新的服务要求。这说明我们在onstar方法中不能写入相关类的处理逻辑，必须要用某种方法解耦才行。</p>
<p>实现方法：<br>参考下面的类图<br><img height=238 alt="" src="http://www.cnblogs.com/images/cnblogs_com/lodestar/wf/classview.jpg" width=482 border=0><br>servcive类和具体的业务实现类解耦，我们可以使用工厂模式生成业务逻辑类，每个业务逻辑类启动在一个新的线程中，在.net中工厂模式可以用反射非常方便的实现，这块代码如下：<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"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">typeInfo&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;node.Attributes[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">].Value;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Type.GetType(typeInfo);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IService&nbsp;instance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(IService)Activator.CreateInstance(type);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">初始化服务</span><span style="COLOR: #008000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instance.Initialize(node);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instanceArray.Add(instance);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">在新线程中运行服务,每个服务使用相同的安全上下文</span><span style="COLOR: #008000"><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ThreadStart&nbsp;ts&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ThreadStart(instance.Start);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Thread(ts);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.Start();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>从配置文件中读出需要加载的业务逻辑类，实例化后用ThreadStart调用其中的Start方法，启动新线程。这里对配置文件的读取如果要求比较高可以采用Enterprise Libary的Login block来做。<br>在OnStop方法中调用每个类的Stop方法，如果想对每个Stop方法异步调用，可以用delegate封装接口的Stop方法用<br>BeginInvoke方法实现异步调用<br></p>
<p>&#160;</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">foreach</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;o&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;instanceArray)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IService&nbsp;service&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(IService)o;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(service&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">异步调用每个服务的stop方法来停止业务组件</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OnStopDelegate&nbsp;osd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;OnStopDelegate(service.Stop);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;osd.BeginInvoke(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(Exception&nbsp;ex)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//<br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}</span></div>
<p><br>这样，整个windows服务就实现了，这里还有个额外的好处是可以热部署，即不需要删除已经部署的windows服务，将新的DLL覆盖将以前的DLL覆盖,修改*.exe.config文件并重新启动就可以了。其实我觉得停止服务，重新编译部署后在启动服务花费的时间可能比这样还少些。</p>
<p>关于调试：<br>windows服务常用的调试方法是用调试－&gt;附加到进程的方法。<br>选择显示所有用户进程，我们已经部署并启动的windows服务进程就会出现，并跳到我们设置好的断点处。但是这样对service中的onstart部分调试比较麻烦。我还是推荐创建一个porjec做为调试用，这里面可以写onstart部分的代码，代码不多，非常方便。大家就可以象调试普通windows程序一样调试这windows服务代码了</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37969.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-21 23:38 <a href="http://www.cnitblog.com/seeyeah/archive/2007/12/21/37969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]关于XML的Namespace</title><link>http://www.cnitblog.com/seeyeah/archive/2007/12/19/37853.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 18 Dec 2007 16:20:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/12/19/37853.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37853.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/12/19/37853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37853.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37853.html</trackback:ping><description><![CDATA[Scenario&nbsp; <br><br>现有XML文件：<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: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">xml&nbsp;version="1.0"</span><span style="COLOR: #0000ff">?&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">mso-application&nbsp;progid="Excel.Sheet"</span><span style="COLOR: #0000ff">?&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">Workbook&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:spreadsheet"</span><span style="COLOR: #ff0000"><br>&nbsp;xmlns:o</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:office"</span><span style="COLOR: #ff0000"><br>&nbsp;xmlns:x</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:excel"</span><span style="COLOR: #ff0000"><br>&nbsp;xmlns:ss</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:spreadsheet"</span><span style="COLOR: #ff0000"><br>&nbsp;xmlns:html</span><span style="COLOR: #0000ff">="http://www.w3.org/TR/REC-html40"</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">DocumentProperties&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:office"</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">Author</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">微软中国</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">Author</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">LastAuthor</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">微软中国</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">LastAuthor</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">Created</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">2007-12-18T14:27:37Z</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">Created</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">Company</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">微软中国</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">Company</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">Version</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">11.6360</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">Version</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">DocumentProperties</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">ExcelWorkbook&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:excel"</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">WindowHeight</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">8550</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">WindowHeight</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">WindowWidth</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">11700</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">WindowWidth</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">WindowTopX</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">240</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">WindowTopX</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">WindowTopY</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">75</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">WindowTopY</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">ProtectStructure</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectStructure</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">ProtectWindows</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectWindows</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">ExcelWorkbook</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">Styles</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">Style&nbsp;</span><span style="COLOR: #ff0000">ss:ID</span><span style="COLOR: #0000ff">="Default"</span><span style="COLOR: #ff0000">&nbsp;ss:Name</span><span style="COLOR: #0000ff">="Normal"</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">Alignment&nbsp;</span><span style="COLOR: #ff0000">ss:Vertical</span><span style="COLOR: #0000ff">="Center"</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">Borders</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">Font&nbsp;</span><span style="COLOR: #ff0000">ss:FontName</span><span style="COLOR: #0000ff">="宋体"</span><span style="COLOR: #ff0000">&nbsp;x:CharSet</span><span style="COLOR: #0000ff">="134"</span><span style="COLOR: #ff0000">&nbsp;ss:Size</span><span style="COLOR: #0000ff">="12"</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">Interior</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">NumberFormat</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">Protection</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">Style</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">Styles</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">Worksheet&nbsp;</span><span style="COLOR: #ff0000">ss:Name</span><span style="COLOR: #0000ff">="Sheet1"</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">Table&nbsp;</span><span style="COLOR: #ff0000">ss:ExpandedColumnCount</span><span style="COLOR: #0000ff">="0"</span><span style="COLOR: #ff0000">&nbsp;ss:ExpandedRowCount</span><span style="COLOR: #0000ff">="0"</span><span style="COLOR: #ff0000">&nbsp;x:FullColumns</span><span style="COLOR: #0000ff">="1"</span><span style="COLOR: #ff0000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x:FullRows</span><span style="COLOR: #0000ff">="1"</span><span style="COLOR: #ff0000">&nbsp;ss:DefaultColumnWidth</span><span style="COLOR: #0000ff">="54"</span><span style="COLOR: #ff0000">&nbsp;ss:DefaultRowHeight</span><span style="COLOR: #0000ff">="14.25"</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">WorksheetOptions&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:excel"</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">Selected</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">ProtectObjects</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectObjects</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">ProtectScenarios</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectScenarios</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">WorksheetOptions</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">Worksheet</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">Worksheet&nbsp;</span><span style="COLOR: #ff0000">ss:Name</span><span style="COLOR: #0000ff">="Sheet2"</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">Table&nbsp;</span><span style="COLOR: #ff0000">ss:ExpandedColumnCount</span><span style="COLOR: #0000ff">="0"</span><span style="COLOR: #ff0000">&nbsp;ss:ExpandedRowCount</span><span style="COLOR: #0000ff">="0"</span><span style="COLOR: #ff0000">&nbsp;x:FullColumns</span><span style="COLOR: #0000ff">="1"</span><span style="COLOR: #ff0000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x:FullRows</span><span style="COLOR: #0000ff">="1"</span><span style="COLOR: #ff0000">&nbsp;ss:DefaultColumnWidth</span><span style="COLOR: #0000ff">="54"</span><span style="COLOR: #ff0000">&nbsp;ss:DefaultRowHeight</span><span style="COLOR: #0000ff">="14.25"</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">WorksheetOptions&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:excel"</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">ProtectObjects</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectObjects</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">ProtectScenarios</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectScenarios</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">WorksheetOptions</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">Worksheet</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">Worksheet&nbsp;</span><span style="COLOR: #ff0000">ss:Name</span><span style="COLOR: #0000ff">="Sheet3"</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">Table&nbsp;</span><span style="COLOR: #ff0000">ss:ExpandedColumnCount</span><span style="COLOR: #0000ff">="0"</span><span style="COLOR: #ff0000">&nbsp;ss:ExpandedRowCount</span><span style="COLOR: #0000ff">="0"</span><span style="COLOR: #ff0000">&nbsp;x:FullColumns</span><span style="COLOR: #0000ff">="1"</span><span style="COLOR: #ff0000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x:FullRows</span><span style="COLOR: #0000ff">="1"</span><span style="COLOR: #ff0000">&nbsp;ss:DefaultColumnWidth</span><span style="COLOR: #0000ff">="54"</span><span style="COLOR: #ff0000">&nbsp;ss:DefaultRowHeight</span><span style="COLOR: #0000ff">="14.25"</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">WorksheetOptions&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:schemas-microsoft-com:office:excel"</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">ProtectObjects</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectObjects</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">ProtectScenarios</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">False</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">ProtectScenarios</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">WorksheetOptions</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">Worksheet</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">Workbook</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span></div>
<br><strong>1、要读取Worksheet节点个数</strong><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;XmlDocument&nbsp;doc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;XmlDocument();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doc.Load(</span><span style="COLOR: #000000">@"</span><span style="COLOR: #000000">D:\appTemp\Try\ClassLibrary1\Book1.xml</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlNode&nbsp;rootNode&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;doc.DocumentElement;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">根节点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlNamespaceManager&nbsp;namespaceManager&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;XmlNamespaceManager(doc.NameTable);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namespaceManager.AddNamespace(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">d</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">urn:schemas-microsoft-com:office:spreadsheet</span><span style="COLOR: #000000">"</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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namespaceManager.AddNamespace(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">o</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">urn:schemas-microsoft-com:office:office</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namespaceManager.AddNamespace(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">x</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">urn:schemas-microsoft-com:office:excel</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namespaceManager.AddNamespace(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ss</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">urn:schemas-microsoft-com:office:spreadsheet</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namespaceManager.AddNamespace(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://www.w3.org/TR/REC-html40</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(rootNode.SelectNodes(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/d:Workbook/d:Worksheet</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">调用默认的命名空间Prefix</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;namespaceManager).Count);<br></span></div>
<br>或者不使用XmlNamespaceManager，在XPath使用函数local-name()。<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">Console.WriteLine(rootNode.SelectNodes(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">//*[local-name()='Worksheet']</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).Count);</span></div>
<br>其中XPath意思：在整个XML所有元素中寻找<strong>处于第一位的节点的扩展名称本地部分</strong>为&#8220;Worksheet&#8221;的节点元素。<br><br><a href="ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/WD_XMLStd/html/4ccd4434-136a-40f5-9ab6-7c57a8215ed2.htm">MSND(vs2005)</a>：
<p>扩展名称通常包括命名空间 URI（或关联的前缀）、冒号 (:) 和本地部分。例如，<code>b:author</code> 是扩展名称，其中 <code>b</code> 是命名空间 URI 前缀，<code>author</code> 是本地部分。所以，对此节点应用 <code>local-name()</code> 函数将返回 <code>author</code>。如果节点没有扩展名称，例如 <code>author</code>，对此节点应用 <code>local-name()</code> 函数将返回原始节点名称，即 <code>author</code>。</p>
<br><strong>2、查找Workbook\DocumentProperties节点</strong><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;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">DocumentProperties使用另外的默认命名空间&#8220;urn:schemas-microsoft-com:office:office&#8221;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(rootNode.SelectSingleNode(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/d:Workbook/o:DocumentProperties</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;namespaceManager).InnerText);</span></div>
<p><br>注意，要用1的namespaceManager对象。<br><br><strong>3、获取Workbook中Name等于"Sheet1"的Worksheet节点中，Table的DefaultColumnWidth属性值。</strong><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">Console.WriteLine(rootNode.SelectSingleNode(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/d:Workbook/d:Worksheet[@ss:Name='Sheet1']/d:Table/@ss:DefaultColumnWidth</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;namespaceManager).Value);</span></div>
<br>
<p>注意，要用1的namespaceManager对象。<br></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37853.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-19 00:20 <a href="http://www.cnitblog.com/seeyeah/archive/2007/12/19/37853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]跨线程调用Winform控件</title><link>http://www.cnitblog.com/seeyeah/archive/2007/12/12/37640.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 12 Dec 2007 15:55:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/12/12/37640.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37640.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/12/12/37640.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37640.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37640.html</trackback:ping><description><![CDATA[<p>Scenario：</p>
<p>1、程式启动时，计算器在刷新时间。<br>2、点击&#8220;Go&#8221;，按钮无效状态，计算停止。<br>3、5秒后按钮恢复状态，计算重新启动。<br>4、2-3之间UI不能出现阻塞，即是要用多线程。<br><br><img id=ViewPicture1_GalleryImage style="BORDER-RIGHT: black 2px solid; BORDER-TOP: black 2px solid; BORDER-LEFT: black 2px solid; WIDTH: 300px; BORDER-BOTTOM: black 2px solid; HEIGHT: 300px" src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/5119/r_threadWinform1.JPG"><br><br>程序：<br>1、定义界面接口IForm</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">interface</span><span style="COLOR: #000000">&nbsp;IForm<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;启动Button<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;EnableButton();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;禁用Button<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DisableButton();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;停止计时器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;StopTimer();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;启用计时器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;RecoverTimer();<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p>2、异步运行程式<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;Test<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;执行<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;param&nbsp;name="form"&gt;&lt;/param&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&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;AsyncMethod(IForm&nbsp;form)<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: #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;form.DisableButton();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;form.StopTimer();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">停止5秒</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.Sleep(</span><span style="COLOR: #000000">5000</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><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">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Do(IForm&nbsp;form)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyProcess&nbsp;myProcess&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;MyProcess(AsyncMethod);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AsyncCallback&nbsp;callback&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AsyncCallback(MyCallback);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myProcess.BeginInvoke(form,&nbsp;callback,&nbsp;form);<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">void</span><span style="COLOR: #000000">&nbsp;MyCallback(IAsyncResult&nbsp;ar)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AsyncResult&nbsp;res&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(AsyncResult)ar;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyProcess&nbsp;del&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(MyProcess)res.AsyncDelegate;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;del.EndInvoke(ar);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IForm&nbsp;form&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(IForm)res.AsyncState;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;form.EnableButton();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;form.RecoverTimer();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p><br>3、界面代码<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;partial&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Form1&nbsp;:&nbsp;Form,&nbsp;IForm<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;Form1()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<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">void</span><span style="COLOR: #000000">&nbsp;btn_Click(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test.Do(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<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">void</span><span style="COLOR: #000000">&nbsp;timer1_Tick(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;EventArgs&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">this</span><span style="COLOR: #000000">.lblCurrentDate.Text&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;DateTime.Now.ToString(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">yyyy-MM-dd&nbsp;HH:mm:ss</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;<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;EnableButton()<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">this</span><span style="COLOR: #000000">.btn.Enabled&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><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;DisableButton()<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">this</span><span style="COLOR: #000000">.btn.Enabled&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><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;StopTimer()<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">this</span><span style="COLOR: #000000">.timer1.Stop();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><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;RecoverTimer()<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">this</span><span style="COLOR: #000000">.timer1.Start();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<br>如此调用，常理来说应该正确，但.net会抛出异常。<br><img id=ViewPicture1_GalleryImage style="BORDER-RIGHT: black 2px solid; BORDER-TOP: black 2px solid; BORDER-LEFT: black 2px solid; WIDTH: 402px; BORDER-BOTTOM: black 2px solid; HEIGHT: 251px" src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/5119/r_threadWinform2.JPG"><br><br><strong>解决办法<br><br></strong>根据&#8220;排错提示&#8221;，查看MSDN的&#8220;<span id=nsrTitle><a href="ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_fxmclictl/html/138f38b6-1099-4fd5-910c-390b41cbad35.htm"><span id=nsrTitle>如何：对 Windows 窗体控件进行线程安全调用</span></a>&#8221;即可得到答案。<br><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: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;EnableButton()<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: #008000">//</span><span style="COLOR: #008000">使用控件的InvokeRequired判断执行Invoke</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.btn.InvokeRequired)<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">this</span><span style="COLOR: #000000">.Invoke(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AscyUpdateControl(EnableButton));<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;</span><span style="COLOR: #0000ff">else</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">this</span><span style="COLOR: #000000">.btn.Enabled&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</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;}<br><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;DisableButton()<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">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.btn.InvokeRequired)<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">this</span><span style="COLOR: #000000">.Invoke(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AscyUpdateControl(DisableButton));<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;</span><span style="COLOR: #0000ff">else</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">this</span><span style="COLOR: #000000">.btn.Enabled&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</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;}<br><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;StopTimer()<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: #008000">//</span><span style="COLOR: #008000">如没有InvokeRequired属性，简写如下代码即可</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Invoke(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AscyUpdateControl(</span><span style="COLOR: #0000ff">delegate</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">this</span><span style="COLOR: #000000">.timer1.Stop();<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">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;RecoverTimer()<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">this</span><span style="COLOR: #000000">.Invoke(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AscyUpdateControl(</span><span style="COLOR: #0000ff">delegate</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">this</span><span style="COLOR: #000000">.timer1.Start();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p>&nbsp;</p>
<p><a href="http://www.cnitblog.com/Files/seeyeah/TimerTest.rar">代码</a></span></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37640.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 23:55 <a href="http://www.cnitblog.com/seeyeah/archive/2007/12/12/37640.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET MVC Overview 【From ASP.NET3.5 Extensive QuickStart】</title><link>http://www.cnitblog.com/seeyeah/archive/2007/12/10/37557.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 10 Dec 2007 13:26:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/12/10/37557.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37557.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/12/10/37557.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37557.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37557.html</trackback:ping><description><![CDATA[链接：<a href="http://quickstarts.asp.net/3-5-extensions/mvc/MVCOverview.aspx">http://quickstarts.asp.net/3-5-extensions/mvc/MVCOverview.aspx</a><br>我的翻译：<a class=titlelink id=Editor_Results_rprSelectionList_ctl01_LinkTitle href="http://www.cnitblog.com/seeyeah/articles/37563.html"><font style="COLOR: #0000ff" color=#000000>ASP.NET MVC 概述</font></a><br>
<hr>
<h2>Introduction</h2>
<p>The Model View Controller (MVC) architectural pattern separates an application into three main components: the model, the view, and the controller. The ASP.NET MVC framework provides an alternative to the ASP.NET Web-forms pattern for creating MVC-based Web applications. The ASP.NET MVC framework is a lightweight, highly testable presentation framework that (as with Web-forms-based applications) is integrated with existing ASP.NET features, such as master pages and membership-based authentication. The MVC framework is defined in the <span class=keyword>System.Web.Mvc</span> namespace and is a fundamental, supported part of the <span class=keyword>System.Web</span> namespace. </p>
<p>MVC is a standard design pattern that many developers are familiar with. Some types of Web applications will benefit from the MVC framework. Others will continue to use traditional ASP.NET application pattern that is based on Web forms and postbacks. Other types of Web applications will combine the two approaches; neither approach precludes the other.</p>
<p>The MVC framework does not use view state or server-based forms. This makes it ideal for developers who want full control over the behavior of an application. </p>
<p>On the other hand, Web forms-based applications support an event model that preserves state over HTTP, which benefits line-of-business Web application development. The Web-forms-based application provides dozens of events that are supported in hundreds of server controls. MVC uses a Front Controller pattern that enables you design an application that completely separates the tasks of presentation, business logic, and data access, and that supports a rich routing infrastructure. Web forms applications use a page-controller pattern that adds functionality to individual pages. These two patterns can be mixed as needed.</p>
<p>The MVC components are as follows:</p>
<ul>
    <li>
    <p><strong>Models</strong> - Model objects are the parts of your application that implement the domain logic. Often, model objects also retrieve and store model state in a database. For example, a Product object might retrieve information from a database, operate on it, and then write updated information back to a Products table in SQL Server. </p>
    <div class=alert><strong>note</strong>
    <p>In smaller applications, the model is often a conceptual separation rather than a physical one. For example, if the application only reads a data set and sends it to the view, the application does not have a physical model layer and associated classes. In that case, the data set takes on the role of a model object.</p>
    </div>
    <li>
    <p><strong>Views</strong> - Views are the components that display the application's user interface (UI). Typically, this UI is created from the model data. An example would be an edit view of a Products table that displays text boxes, drop-down lists, and check boxes based on the current state of a Product object.</p>
    <li>
    <p><strong>Controllers</strong> - Controllers are the components that handle user interaction, manipulate the model, and ultimately select a view to render that displays UI. In an MVC application, the view only displays information; the controller handles and responds to user input and interaction. For example, the controller handles query-string values, and passes these values to the model, which in turn queries the database by using the values.</p>
    </li>
</ul>
<p>The MVC pattern helps you to create applications that separate the different aspects of the application (input logic, business logic, and UI logic), while providing a loose coupling between these elements. The pattern specifies where each kind of logic should exist in the application. The UI logic belongs in the view. Input logic belongs in the controller. Business logic belongs in the model. This separation helps you manage complexity when you build an application, because it enables you to focus on one aspect of the implementation at a time. For example, you can focus on the view without depending on the business logic.</p>
<p>In addition to managing complexity, the MVC pattern makes testing applications easier than testing a traditional ASP.NET Web application. For example, in a traditional ASP.NET Web application, a single class is used both to display output and to respond to user input. Writing automated tests for traditional ASP.NET applications can be complex, because to test an individual page, you must instantiate the page class, all its child controls, and additional dependent classes in the application. Because so many classes are instantiated to run the page, it can be hard to write tests that focus exclusively on individual portions of the application. Tests for traditional ASP.NET applications can therefore be more difficult to implement than test within an MVC application. Moreover, tests within a traditional ASP.NET application require a Web server. The MVC framework decouples the components and makes heavy use of interfaces, which makes it possible to test individual components in isolation from the rest of the framework.</p>
<p>The loose coupling between the three main components of an MVC application also promotes parallel development. For instance, one developer can work on the view, a second developer can work on the controller logic, and a third developer can focus on the business logic in the model.</p>
<h2 class=subsectionTitle>Features of the ASP.NET MVC Framework</h2>
<p>The ASP.NET MVC framework provides the following features:</p>
<ul>
    <li>
    <p>Separation of application tasks (input logic, business logic, and UI logic), testability, and test-driven development (TDD) by default. All core contracts within the MVC framework are interface-based and can be tested by using mock objects. You can unit-test the application without having to run the controllers in an ASP.NET process, which makes unit testing fast and flexible. You can use any unit-testing framework that is compatible with the .NET Framework.</p>
    <li>
    <p>An extensible and pluggable framework. The components of the ASP.NET MVC framework are designed so that they can be easily replaced or customized. You can plug in your own view engine, URL routing policy, action-method parameter serialization, and other components. The ASP.NET MVC framework also supports using existing dependency injection and Inversion of Control (IOC) container models.</p>
    <li>
    <p>A powerful URL-mapping component that lets you build applications that have comprehensible and searchable URLs. URLs do not have to include file-name extensions, and are designed to support URL naming patterns that work well for search engine optimization (SEO) and representational state transfer (REST) addressing. For example, you could map the <span class=code>/products/edit/4</span> URL to the <span class=code>Edit</span> action of a <span class=code>ProductsController</span> class in your project, or map the <span class=code>/Blogs/YourSite/10-10-2007/SomeTopic/</span> URL to a <span class=code>DisplayPost</span> action of a <span class=code>BlogEngineController</span> class. URLs do not have to reference file names.</p>
    <li>
    <p>Support for using the markup in existing ASP.NET pages (.aspx files), user controls (.ascx files), and master pages (.master files) markup files as view templates. You can use existing ASP.NET features with the ASP.NET MVC framework, such as nested master pages, in-line expressions (<span class=code>&lt;%=&nbsp;</span><span class=code>%&gt;)</span>, declarative server controls, templates, data-binding, localization, and so on.</p>
    <li>
    <p>Support for existing ASP.NET features. ASP.NET MVC lets you use features such as forms and Windows authentication, URL authorization, membership and roles, output and data caching, session and profile state management, health monitoring, configuration system, the provider architecture, and other areas of ASP.NET.</p>
    </li>
</ul>
<h2 class=subsectionTitle>Background</h2>
<p>In an ASP.NET Web Site, URLs typically map to files stored on disk (typically .aspx files). These .aspx files include code or markup that is processed in order to respond to the request.</p>
<p>The ASP.NET MVC framework maps URLs to server code in a different way. Instead of mapping URLs to ASP.NET pages or handlers, the framework maps URLs directly to controller classes. Controller classes handle incoming requests, such as user input and interactions, and also execute appropriate application and data logic based on user input. A controller class typically calls a separate view component that generates the HTML output as the response.</p>
<p>The ASP.NET MVC framework separates the model, view, and controller components. The model component maintains state by typically persisting data inside a database. The view component is selected by the controller and renders the appropriate UI. By default, the ASP.NET MVC framework uses the existing ASP.NET page (.aspx), master page (.master), and user control (.ascx) types for rendering to the browser. The controller component locates the appropriate action method in the controller, gets the values to use as the action method's arguments, handles all errors that might occur during the execution of the action, and renders the requested view. Each set of components exists in a separate subdirectory of an MVC Web application project. </p>
<h2 class=subsectionTitle>URL Mapping</h2>
<p>The ASP.NET MVC framework includes a URL-mapping engine that provides flexibility for mapping URLs to controller classes. You can use the mapping engine to define routing rules that the ASP.NET MVC framework uses to evaluate incoming URLs and to select a controller to execute. You can also have the routing engine automatically parse variables defined in the URL and have the ASP.NET MVC framework pass these to the controller as parameter arguments. </p>
<h2 class=subsectionTitle>The MVC Framework and Postbacks</h2>
<p>ASP.NET MVC framework does not use the traditional ASP.NET postback model for interactions with the server. Instead, all end-user interactions are routed to a controller class. This maintains separation between UI logic and business logic and helps testability. As a result, ASP.NET view state and ASP.NET page life-cycle events are not integrated with MVC-based views.</p>
<h2 class=subsectionTitle>Creating an ASP.NET MVC Application</h2>
<p>The ASP.NET MVC framework includes Visual Studio project templates that let you create Web applications that are structured to support the MVC pattern. The <span class=ui>MVC Web Application</span> template is used to create a new Web application that is configured with the subdirectories, templates, and configuration-file entries that are required for an ASP.NET MVC application.</p>
<p>By default, when you create a new Web application by using this template, Visual Studio creates a solution and adds two projects to the solution. The first project is a Web project where you can implement your application. The second project is a testing project that you can write unit tests for your MVC components.</p>
<p>You can use any unit-testing framework that is compatible with the .NET Framework to test ASP.NET MVC applications. Visual Studio 2008 Professional includes built-in testing project support for MSTest.</p>
<h2 class=subsectionTitle>Understanding Web Application MVC Project Structure</h2>
<p>When you create an ASP.NET MVC Web application project, MVC components are separated based on the following project folders:</p>
<ul>
    <li>
    <p>Views folder. The Views folder is the recommended location for views. The views use .aspx, .ascx, and .master files, as well as any other files that are related to rendering views. The Views directory contains a folder for each controller that is named with the controller prefix. When loading a view, by default the ASP.NET MVC framework will look for an .aspx file with the requested view name in the Views\controllerName folder. There is also a default directory named Common that does not correspond to any controller. This is a useful location to put master pages, scripts, CSS files, and other files that are used when rendering a view. </p>
    <li>
    <p>Controller folder. The Controllers folder is the recommended location for controllers. </p>
    <li>
    <p>Model folder. The Models folder is the recommended location for classes that represent the application model for your MVC Web application. Typically, this includes code that defines the logic for interaction with the data store.</p>
    <li>
    <p>App_Data. The physical store for data. This folder has the same role as it does in Web-forms based ASP.NET Web applications.</p>
    </li>
</ul>
<p>In addition to the folders listed previously, a MVC Web application uses the following application elements:</p>
<ul>
    <li>
    <p>Global.asax and Global.asax.cs (or Global.asax.vb in Visual Basic). In Global.asax.cs, routes are initialized in the <span class=keyword>Application_Start</span> method. The following example shows a typical Global.asax file that includes default routing logic.</p>
    <div class=code>
    <pre>public class Global : System.Web.HttpApplication {
    protected void Application_Start(object sender, EventArgs e) {
    RouteTable.Routes.Add(new Route {
    Url = "[controller]/[action]/[id]",
    Defaults = new { action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
    });
    }
    }</pre>
    </div>
    <li>
    <p>Configuration. The MVC Web application Web.config file registers HTTP handlers and HTTP modules. The <span class=keyword>httpHandlers</span> section registers the <span class=keyword>MvcHandler</span> class, which routes requests to the appropriate controller. The following example shows the <span class=keyword>httpHandlers</span> section for an ASP.NET MVC application.</p>
    <div class=code>
    <pre>&lt;httpHandlers&gt;
    &lt;add verb="*" path="*.mvc" type="System.Web.Mvc.MvcHandler,
    System.Web.Extensions, Version=3.6.0.0, Culture=neutral,
    PublicKeyToken=31BF3856AD364E35"/&gt;
    &lt;/httpHandlers&gt;</pre>
    </div>
    <p>The <span class=keyword>httpModules</span> section registers the <span class=keyword>UrlRoutingModule</span> class, which parses the URL and routes requests to the appropriate handler. This entry enables the application to host MVC and non-MVC handlers in the same project. The following example shows the <span class=keyword>httpModules</span> section for an ASP.NET MVC application.</p>
    <div class=code>
    <pre>&lt;httpModules&gt;
    &lt;add name="UrlRoutingModule"
    type="System.Web.Mvc.UrlRoutingModule,
    System.Web.Extensions, Version=3.6.0.0, Culture=neutral,
    PublicKeyToken=31BF3856AD364E35" /&gt;
    &lt;/httpModules&gt;</pre>
    </div>
    </li>
</ul>
<p>When you create an MVC Web application project, the solution includes a Test project. You can create tests by using the MVC templates and create mock implementations of the intrinsic interfaces.</p>
<h2 class=subsectionTitle>Understanding the MVC Project Execution Process</h2>
<p>Requests to a Web site that is built by using the MVC framework are routed through an ASP.NET HTTP module and to an HTTP handler.</p>
<div class=alert><strong>note</strong>
<p>When an ASP.NET MVC Web application runs in IIS 7, no file name extension is required for MVC projects. However, in IIS6, the handler requires that you map the .mvc file name extension to the ASP.NET ISAPI DLL.</p>
</div>
<p>The module and handler are the entry points to the ASP.NET MVC framework and perform the following actions:</p>
<ul>
    <li>
    <p>Select the appropriate controller in an MVC Web application.</p>
    <li>
    <p>Obtain a specific controller instance.</p>
    <li>
    <p>Call the controller's <span class=keyword>Execute</span> method.</p>
    </li>
</ul>
<p>The following table lists the stages of execution for an MVC Web project:</p>
<table class=authoredTable cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td>
            <p>Stage</p>
            </td>
            <td>
            <p>Details</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Initial request</p>
            </td>
            <td>
            <p>In the Global.asax file, routes are added to the <span class=keyword>RouteTable</span> object.</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Routing</p>
            </td>
            <td>
            <p>The <span class=keyword>UrlRoutingModule</span> module creates the <span class=keyword>RouteData</span> object from the matched <span class=keyword>Route</span> object in the <span class=keyword>RouteTable</span> instance. Route data is used to determine which controller to request, and which action to invoke.</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Map to controller</p>
            </td>
            <td>
            <p>The <span class=keyword>MvcRouteHandler</span> handler attempts to create the type name for the controller, based on data in the <span class=keyword>RouteData</span> instance.</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Invoke controller builder</p>
            </td>
            <td>
            <p>The handler calls the global static <span class=keyword>CreateController</span> method of the <span class=keyword>ControllerBuilder</span> class, obtaining an <span class=keyword>IController</span> instance.</p>
            <p>If an <span class=keyword>IController</span> instance is not returned, the handler returns an HTTP 500 error that indicates a server error. </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Create controller</p>
            </td>
            <td>
            <p>The <span class=keyword>ControllerBuilder</span> instance creates a new controller directly, or uses an <span class=keyword>IControllerFactory</span> object to create the controller.</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Execute controller</p>
            </td>
            <td>
            <p>The <span class=keyword>MvcHandler</span> instance is added to the context and calls the controller's <span class=keyword>Execute</span> method.</p>
            </td>
        </tr>
    </tbody>
</table>
<h2 class=subsectionTitle>Example</h2>
<p>The following code shows the default structure that is created by Visual Studio when you create a new MVC Web application.</p>
<div class=live-code>
<div id=ctl00_MainBody_ctl00_LanguageChoicesDiv><span>Language:</span> <input id=ctl00_MainBody_ctl00_ctl01 onclick="document.getElementById('ctl00_MainBody_ctl00_ViewButton').href='/3-5-extensions/ViewSample.aspx?sref=MVCIntroProject%23MvcApplication%5CDefault.aspx&amp;lang=cs';" type=radio CHECKED value=ctl01 name=ctl00$MainBody$ctl00$LanguageChoices><label for=ctl00_MainBody_ctl00_ctl01>C#</label> </div>
<a class=view-button id=ctl00_MainBody_ctl00_ViewButton href="http://quickstarts.asp.net/3-5-extensions/ViewSample.aspx?sref=MVCIntroProject%23MvcApplication%5CDefault.aspx&amp;lang=cs" target=_blank><u><font color=#0000ff><span>View</span> </font></u></a></div>
<p class=disclaimer>This topic is ASP.NET 3.5 Extensions Preview pre-release documentation and is unsupported by Microsoft. Blank topics are included as placeholders and existing content is subject to change in future releases. To provide feedback or ask questions about the release, please go to the <a href="http://go.microsoft.com/fwlink/?LinkID=105855"><u><font color=#0000ff>ASP.NET 3.5 Extensions Preview forums</font></u></a>.</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37557.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-10 21:26 <a href="http://www.cnitblog.com/seeyeah/archive/2007/12/10/37557.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Concatenating Strings Efficiently</title><link>http://www.cnitblog.com/seeyeah/archive/2007/12/03/37196.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sun, 02 Dec 2007 17:05:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/12/03/37196.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37196.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/12/03/37196.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37196.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37196.html</trackback:ping><description><![CDATA[P.S.<br>讨论连接字符串用&#8220;+&#8221;、用&#8220;StringBuilder&#8221;还是有其他方法更有效。<br>
<hr>
<p>摘自：<a href="http://www.yoda.arachsys.com/csharp/stringbuilder.html">http://www.yoda.arachsys.com/csharp/stringbuilder.html</a><br><br>Concatenating Strings Efficiently<br><br>One of the first pieces of efficiency advice most .NET developers learn is "use <code>StringBuilder</code> to concatenate strings". A little bit like "<a href="http://www.yoda.arachsys.com/csharp/exceptions.html"><u><font color=#0000ff>exceptions are expensive</font></u></a>" this is a misunderstood piece of received wisdom. (Fortunately it's not nearly as harmful as the exception performance myth, but it comes up about as often...) </p>
<p>Before reading the rest of this page, you should be aware of <a href="http://www.yoda.arachsys.com/csharp/strings.html"><u><font color=#0000ff>the basics of the <code>String</code> type</font></u></a>. For the sake of readability, I'll stick to "string" rather than "<code>String</code>" or "<code>string</code>" from here onwards. Please <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#107;&#101;&#101;&#116;&#64;&#112;&#111;&#98;&#111;&#120;&#46;&#99;&#111;&#109;"><u><font color=#0000ff>let me know</font></u></a> if you find this confusing, and I'll change it. </p>
<p>I've included this in my list of general framework articles rather than in the list of C#-specific articles because I suspect every language targetting .NET is likely to use the same way of concatenating strings under the hood. </p>
<h2>The Problem We're Trying To Avoid</h2>
<p>There is a very real problem that this wisdom correctly addresses - that of building a load of strings (usually of increasing size) which are never used apart from contributing to the creation of other strings. Here's an example: </p>
<table class=code>
    <tbody>
        <tr>
            <td>
            <pre><span class=Namespace>using</span> System;
            <span class=Modifier>public</span> <span class=ReferenceType>class</span> Test
            {
            <span class=Modifier>static</span> <span class=ValueType>void</span> Main()
            {
            DateTime start = DateTime.Now;
            <span class=ReferenceType>string</span> x = <span class=String>""</span>;
            <span class=Statement>for</span> (<span class=ValueType>int</span> i=0; i &lt; 100000; i++)
            {
            x += <span class=String>"!"</span>;
            }
            DateTime end = DateTime.Now;
            Console.WriteLine (<span class=String>"Time taken: {0}"</span>, end-start);
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>On my (fairly fast) laptop, that takes nearly 10 seconds. Double the number of iterations, and it takes over a minute. The results are slightly better on .NET 2.0 beta 2, but not hugely. The problem is that strings are immutable - just because we're using "+=" here doesn't mean the runtime actually appends to the end of the existing string. In fact, <code>x += "!";</code> is absolutely equivalent to <code>x = x+"!";</code>. The concatenation here is creating an entirely new string, allocating enough memory for everything, copying all the data from the existing value of <code>x</code> and then copying the data from the string being appended ("!"). As the string grows, the amount of data it has to copy each time grows too, which is why the time taken didn't just double when I doubled the number of iterations. </p>
<p>This is clearly inefficient. If someone asked you to add something to a shopping list, you wouldn't write a new copy of the shopping list first, would you? Enter <code>StringBuilder</code>... </p>
<h2>The <code>StringBuilder</code> Solution</h2>
<p>Here is an equivalent (in terms of the final value of <code>x</code>) program, which is much, much faster: </p>
<table class=code>
    <tbody>
        <tr>
            <td>
            <pre><span class=Namespace>using</span> System;
            <span class=Namespace>using</span> System.Text;
            <span class=Modifier>public</span> <span class=ReferenceType>class</span> Test
            {
            <span class=Modifier>static</span> <span class=ValueType>void</span> Main()
            {
            DateTime start = DateTime.Now;
            StringBuilder builder = <span class=Keyword>new</span> StringBuilder();
            <span class=Statement>for</span> (<span class=ValueType>int</span> i=0; i &lt; 100000; i++)
            {
            builder.Append(<span class=String>"!"</span>);
            }
            <span class=ReferenceType>string</span> x = builder.ToString();
            DateTime end = DateTime.Now;
            Console.WriteLine (<span class=String>"Time taken: {0}"</span>, end-start);
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>On my laptop, this executes too fast for the rudimentary timing mechanism I'm using to give me any sensible results. Changing to a million iterations (i.e. ten times what the first program took nearly ten seconds to do), it takes about 30-40ms. The time taken is roughly linear in the number of iterations (i.e. double the iterations and it takes twice as long). It does this by avoiding unnecessary copying - only the data we're actually appending gets copied. <code>StringBuilder</code> maintains an internal buffer and appends to that, only copying its buffer when there isn't room for any more data. (In fact, the internal buffer is just a string - strings are immutable from a public interface perspective, but not from within the <code>mscorlib</code> assembly.) We could make the above code even more efficient by passing the final size of the string (which we happen to know in this case) to the constructor of <code>StringBuilder</code> to make it use a buffer of the right size to start with - then there'd be no unnecessary copying at all. Unless you're in a situation where you have that information readily to hand though, it's usually not worth worrying about - <code>StringBuilder</code> doubles its buffer size when it runs out of room, so it doesn't end up copying the data very many times anyway. </p>
<h2>So I Should Use <code>StringBuilder</code> Everywhere, Right?</h2>
<p>No, quite simply. The above is an explanation of why the received wisdom of "use <code>StringBuilder</code> for concatenation" is right some of the time. However, many people take it at face value without understanding the reasoning behind it. They start turning code like this: </p>
<table class=code>
    <tbody>
        <tr>
            <td>
            <pre><span class=ReferenceType>string</span> name = firstName + <span class=String>" "</span> + lastName;
            Person person = <span class=Keyword>new</span> Person (name);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>into code like this:</p>
<table class=code>
    <tbody>
        <tr>
            <td>
            <pre><span class=Attention>// Bad code! Do not use!</span>
            StringBuilder builder = <span class=Keyword>new</span> StringBuilder();
            builder.Append (firstName);
            builder.Append (<span class=String>" "</span>);
            builder.Append (lastName);
            <span class=ReferenceType>string</span> name = builder.ToString();
            Person person = <span class=Keyword>new</span> Person (name);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>All that in the name of inefficiency. Now, on a broader point, even if the second version were more efficient than the first, it probably wouldn't be <em>significantly</em> more efficient - unless that code ended up being called vast, vast numbers of times, the amount of time spent in the concatenation is likely to be tiny. Making something less readable (and I think you'll agree the second version takes far longer to understand) for a small performance gain is a really bad idea in the first place. </p>
<p>However, the second version is actually <em>less</em> efficient than the first! Not much less efficient - and if the second version were more readable, I'd go with it for the reasons above - but when the entire point of using <code>StringBuilder</code> is to <em>improve</em> efficiency, using the above is just plain nuts. </p>
<p>The first version (assuming that <code>firstName</code> and <code>lastName</code> are real variables, and not constants - I'll come onto that later) compiles to a call to <code>String.Concat</code>, like this: </p>
<table class=code>
    <tbody>
        <tr>
            <td>
            <pre><span class=ReferenceType>string</span> name = String.Concat (firstName, <span class=String>" "</span>, lastName);
            Person person = <span class=Keyword>new</span> Person (name);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p><code>String.Concat</code> takes a bunch of strings (or objects) and concatenates them together, plain and simple. There are various overloads - some take strings, some take objects (which are just converted into strings), some take arrays of objects or arrays of strings. They all do the same thing though. Now, <code>String.Concat</code> can work out the lengths of all the strings involved before it concatenates them together (at least if you pass it strings - if you pass it objects, it needs to create temporary strings and then concatenate <em>those</em> together). This means that no extra copying is involved - the data is copied once into the new string, which is of exactly the right length. </p>
<p>Compare this with the <code>StringBuilder</code> version. It doesn't know at construction time how big to make the buffer (because we haven't told it - doing so would make the code even less readable). That means it may have to copy the buffer, and it's likely to end up with a buffer which is actually larger than it needs to be. Oh, and there's the overhead of an extra object (the <code>StringBuilder</code> itself). Remind me why this was meant to be a good idea? </p>
<p>The important difference between this example and the previous one is that we can easily present all the strings which need to be concatenated together in one call to <code>String.Concat</code>. That means that no intermediate strings are needed. <code>StringBuilder</code> is efficient in the first example because it acts as a container for the intermediate result without having to copy that result each time - when there's no intermediate result anyway, it has no advantage. </p>
<h2>Constants</h2>
<p>Things get even crazier when it comes to string constants (literals, <code>const string</code> members). What do you suppose <code>string x = "hello" + " " + "there";</code> is compiled to? It would be reasonable to expect it to be another call to <code>String.Concat</code> - but it isn't. It's actually compiled to the exact same code as <code>string x = "hello there";</code>. The compiler knows that all the parts are constant, so it does all the concatenation at compile time, storing the full string in the compiled code. Converting <em>that</em> to use <code>StringBuilder</code> is inefficient in both memory and speed, as well as reducing readability. </p>
<h2>Rules Of Thumb</h2>
<p>So, when should you use <code>StringBuilder</code>, and when should you use the string concatenation operators? </p>
<ul>
    <li>Definitely use <code>StringBuilder</code> when you're concatenating in a non-trivial loop - <em>especially</em> if you don't know for sure (at compile time) how many iterations you'll make through the loop. For example, reading a file a character at a time, building up a string as you go using the <code>+=</code> operator is potentially performance suicide.
    <li>Definitely use the concatenation operator when you can (readably) specify everything which needs to be concatenated in one statement. (If you have an array of things to concatenate, consider calling <code>String.Concat</code> explicitly - or <code>String.Join</code> if you need a delimiter.)
    <li>Don't be afraid to break literals up into several concatenated bits - the result will be the same. You can aid readability by breaking a long literal into several lines, for instance, with no harm to performance.
    <li>If you need the intermediate results of the concatenation for something <em>other</em> than feeding the next iteration of concatenation, <code>StringBuilder</code> isn't going to help you. For instance, if you build up a full name from a first name and a last name, and then add a third piece of information (the nickname, maybe) to the end, you'll only benefit from using <code>StringBuilder</code> if you don't need the (first name + last name) string for other purpose (as we do in the example which creates a <code>Person</code> object).
    <li>If you just have a few concatenations to do, and you really want to do them in separate statements, it doesn't really matter which way you go. Which way is more efficient will depend on the number of concatenations the sizes of string involved, and what order they're concatenated in. If you really believe that piece of code to be a performance bottleneck, profile or benchmark it both ways. </li>
</ul>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37196.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-03 01:05 <a href="http://www.cnitblog.com/seeyeah/archive/2007/12/03/37196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Enterprise Library  资料</title><link>http://www.cnitblog.com/seeyeah/archive/2007/12/02/37147.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 01 Dec 2007 16:00:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/12/02/37147.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/37147.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/12/02/37147.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/37147.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/37147.html</trackback:ping><description><![CDATA[<p>下载资源：<br><br>1、<a href="http://www.microsoft.com/downloads/details.aspx?familyid=4C557C63-708F-4280-8F0C-637481C31718&amp;displaylang=en">M$ EL2007 May 3.1 官方下载地址</a><br><br>2、<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=6724e09b-ca2e-425a-8d71-8febad3ba203&amp;DisplayLang=en">EL2007 April3.0 DVD超级无敌详细介绍</a><br><br>
<hr>
<br>网上文档：<br><br>1、<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/doriandeng/archive/2007/10/23/935202.html"><u><font color=#800080>Enterprise Library 3.1 帮助文档中文翻译</font></u></a> <br>（<a href="http://wiki.entlib.net.cn/EnterpriseLibraryHelp31.ashx">http://wiki.entlib.net.cn/EnterpriseLibraryHelp31.ashx</a>）<br><a href="http://doriandeng.cnblogs.com/">http://doriandeng.cnblogs.com/</a><br><br>2、<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/Terrylee/archive/2006/08/01/Enterprise_Library.html"><u><font color=#800080>Enterprise Library系列文章回顾与总结</font></u></a> <br><a href="http://www.cnblogs.com/Terrylee/">http://www.cnblogs.com/Terrylee/</a><br><br>3、<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/rickie/archive/2005/02/21/104472.html"><u><font color=#0000ff>Microsoft patterns &amp; practices Enterprise Library系列分析文章</font></u></a> <br><img id=alimamatmpf0.12958921769821635 style="BORDER-RIGHT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; BORDER-LEFT: 0px; WIDTH: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: 0px; HEIGHT: 0px" src="http://p.mm.cn.yahoo.com/alimamal.php?u=http%3A%2F%2Fwww.cnblogs.com%2FTerrylee%2Farchive%2F2006%2F08%2F01%2FEnterprise_Library.html&amp;i=mm_10493229_559068_934720&amp;re=1024x768&amp;sz=12&amp;r=http%3A%2F%2Fwww.google.cn%2Fsearch%3Fq%3DEnterprise%2520Library%2520%26ie%3DUTF-8%26oe%3DGB2312%26hl%3Dzh-CN%26domains%3Dcnblogs.com%26sitesearch%3Dcnblogs.com&amp;sx=531&amp;sy=60&amp;w=468&amp;h=60" border=0 name=alimamatmpf0.12958921769821635><br><a href="http://rickie.cnblogs.com/"><u><font color=#0000ff>http://rickie.cnblogs.com/</font></u></a><br><br>4、<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/pw/archive/2006/06/27/437226.html"><u><font color=#800080>EnterpriseLibrary2.0系列文章及下载</font></u></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><a href="http://www.cnblogs.com/pw">http://www.cnblogs.com/pw</a><br><br>
<p>&#160;</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/37147.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-02 00:00 <a href="http://www.cnitblog.com/seeyeah/archive/2007/12/02/37147.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>英语技术文章 收藏夹</title><link>http://www.cnitblog.com/seeyeah/archive/2007/11/20/36522.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 19 Nov 2007 16:55:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/11/20/36522.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36522.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/11/20/36522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36522.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36522.html</trackback:ping><description><![CDATA[<p><strong>1、Asynchronous Method Invocation</strong><br>How to use .NET to call methods in a non-blocking mode.<br><a href="http://www.codeproject.com/csharp/AsyncMethodInvocation.asp">http://www.codeproject.com/csharp/AsyncMethodInvocation.asp</a> <br>我的翻译：<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36862.html">[2007-12-1]异步调用方法</a><br></p>
<p><strong><br>2、.NET Delegates: A C# Bedtime Story<br></strong>An exploratory story of delegates and events for C# programmers told in the style of a bedtime story.<br><a href="http://www.codeproject.com/csharp/delegate_bedtime.asp">http://www.codeproject.com/csharp/delegate_bedtime.asp</a> <br><strong><br>3、Dependency Injection for Loose Coupling</strong><br>This article describes the use of Dependency Injection, or Inversion-of-Control, to promote loose coupling and convenient unit testing.<br><a href="http://www.codeproject.com/cs/design/DependencyInjection.asp">http://www.codeproject.com/cs/design/DependencyInjection.asp</a> <br>我的翻译：<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36861.html">[2007-11-26]使用依赖注入解耦</a></p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/36522.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:55 <a href="http://www.cnitblog.com/seeyeah/archive/2007/11/20/36522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>英文技术文章 </title><link>http://www.cnitblog.com/seeyeah/archive/2007/11/18/36472.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sun, 18 Nov 2007 13:21:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/11/18/36472.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36472.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/11/18/36472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36472.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36472.html</trackback:ping><description><![CDATA[<hr>
<p><strong style="FONT-SIZE: 18pt">Events and Delegates simplified</strong><br>This article shows you how to design events for your classes.<br><a href="http://www.codeproject.com/csharp/events.asp">http://www.codeproject.com/csharp/events.asp</a><br>我的翻译：<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36521.html">[2007-11-19]事件和委托的简单说明</a> </p>
<p><strong style="FONT-SIZE: 24pt"><span style="FONT-SIZE: 18pt"><br>ASP.NET Best Practices for High Performance Applications</span></strong><br>This article lists the techniques that you can use to maximize the performance of your ASP.NET applications. It provides common issues, design guidelines, and coding tips to build optimal and robust solutions.<br><a href="http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp">http://www.codeproject.com/aspnet/ASPNET_Best_Practices.asp</a> </p>
我的翻译：<a id=viewpost1_TitleUrl href="http://www.cnitblog.com/seeyeah/articles/36759.html"><strong>高性能ASP.NET应用程式的最佳实践</strong></a>&nbsp;<br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/36472.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-18 21:21 <a href="http://www.cnitblog.com/seeyeah/archive/2007/11/18/36472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Implementing Model-View-Presenter in ASP.NET  By Alex Mueller. </title><link>http://www.cnitblog.com/seeyeah/archive/2007/11/10/36127.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 10 Nov 2007 13:47:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/11/10/36127.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/36127.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/11/10/36127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/36127.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/36127.html</trackback:ping><description><![CDATA[引用<a href="http://www.codeproject.com/useritems/MVP_in_ASPNET.asp">http://www.codeproject.com/useritems/MVP_in_ASPNET.asp</a><br>
<hr>
&nbsp;
<ul class=download>
    <li><a href="http://www.codeproject.com/useritems/MVP_in_ASPNET/MVPSampleApp.zip"><u><font color=#0000ff>Download MVPSampleApp.zip - 673.2 KB</font></u></a>
    <li><a href="http://www.codeproject.com/useritems/MVP_in_ASPNET/SQL2000SampleDb.zip"><u><font color=#0000ff>Download SQL2000SampleDb.zip - 1,177.7 KB</font></u></a> </li>
</ul>
<h2>Introduction</h2>
<p>I have been using the model-view-presenter pattern in my ASP.NET web applications for a little over a year now. I was first introduced to MVP in a smart-client application using an event-driven implementation well before applying it in ASP.NET. After spending some time in a thick client environment, I found that applying MVP to the web reveals a new set of problems that need to be addressed. This article will describe these issues and provide an implementation for ASP.NET that I feel maximizes usability and testability. </p>
<p>What this article will do is briefly explain the basics of the pattern and provide three implementations of MVP for ASP.NET. I provide three implementations to allow the reader to see how the pattern can vary, and how the roles for the ASPX page, ASCX user control, and Presenter are defined in each. There is no one correct implementation of MVP in ASP.NET. Whichever implementation is used is really just a matter of personal preference and theoretical debate. </p>
<h2>Model-View-Presenter in ASP.NET: Setting the Stage</h2>
<p>By default, ASP.NET implements a <a href="http://msdn2.microsoft.com/en-us/library/ms998548.aspx." target=_blank><u><font color=#0000ff>Page Controller</font></u></a> pattern that does not promote good separation of concerns nor testability. The dependency on the ASP.NET runtime makes testing of the implementation difficult without generating testing scenarios that are impractical. Since unit testing of view specific pages is difficult, we look for patterns that promote testability. MVP is such a pattern. </p>
<p>Model-view-presenter is a design pattern that aims to increase separation of concerns and testability. Its primary goal is to separate view specific logic from domain/business logic. As we design object-oriented applications, we desire objects that are loosely coupled and can be easily reused. In order to do so, we need to build classes and layers that are specific to certain tasks, such as view, presentation, service, and data access to name a few. In ASP.NET, it is too easy to add domain or business logic to our ASPX page or ASCX user control classes, creating tightly coupled classes that become difficult to reuse and test. MVP seeks to separate view-specific logic from domain/business logic by using a presentation layer. </p>
<p>The secondary goal of MVP is to improve testability of the view. It is difficult to write a unit test for a class that is dependent upon Session or ViewState, Ajax, Html or web controls, and domain/business objects. Instead, we leave that view-specific logic in the ASPX/ASCX classes and pull presentation and domain/business logic out of the view and put them in their appropriate classes. In MVP, the presenter acts as a mediator between the view and our domain/business logic. </p>
<p>Martin Fowler has split the MVP pattern into two new patterns, Supervising Controller and Passive View. Unlike a true MVC (model-view-controller) framework that enforces a strict separation of the view layer from the presentation (controller), in ASP.NET, this separation is not enforced by default. Because of this, it is difficult to enforce any one implementation of MVP without conscientious effort on the part of the developer, and the grey area between implementing a Supervising Controller and a Passive View widens. As a rule of thumb when creating my presenters, I try and pull as much logic as possible out of the view that I want under test, and put that into the presenter. I let the view handle view-specific logic such as JavaScript, HTML and WebControls, and Ajax frameworks. Since there is still some logic in my view, I tend to classify this as Supervising Controller versus Passive View, and after several sleepless nights debating this in my head, I am happy with Supervising Controller in ASP.NET. </p>
<p>If you need a more detailed introduction beyond what is mentioned above, you may find these links helpful. <br><a href="http://martinfowler.com/eaaDev/uiArchs.html" target=_blank><u><font color=#0000ff>GUI Architectures</font></u></a> <br><a href="http://martinfowler.com/eaaDev/SupervisingPresenter.html" target=_blank><u><font color=#0000ff>Supervising Controller</font></u></a> <br><a href="http://martinfowler.com/eaaDev/PassiveScreen.html" target=_blank><u><font color=#0000ff>Passive View</font></u></a> <br><a href="http://en.wikipedia.org/wiki/Presenter_First" target=_blank><u><font color=#0000ff>Presenter First</font></u></a> <br><a href="http://www.codeproject.com/aspnet/ModelViewPresenter.asp" target=_blank><u><font color=#800080>Model View Presenter with ASP.NET</font></u></a> <br><a href="http://haacked.com/archive/2006/08/09/ASP.NETSupervisingControllerModelViewPresenterFromSchematicToUnitTestsToCode.aspx" target=_blank><u><font color=#0000ff>ASP.NET Supervising Controller (Model View Presenter) From Schematic To Unit Tests to Code</font></u></a> </p>
<h2>Different Implementations of MVP in ASP.NET</h2>
<p>While implementing MVP in ASP.NET, my designs have followed a few different schools of thought. One such approach was detailed by <a href="http://www.codeproject.com/aspnet/ModelViewPresenter.asp" target=_blank><u><font color=#800080>Billy McCafferty</font></u></a> and another by <a href="http://haacked.com/archive/2006/08/09/ASP.NETSupervisingControllerModelViewPresenterFromSchematicToUnitTestsToCode.aspx" target=_blank><u><font color=#0000ff>Phil Haack</font></u></a>. Since my introduction to MVP was event-driven in a windows application, I applied the event-driven approach that was most familiar to me. The stateless nature of the web was the first obstacle I found I needed to overcome. In ASP.NET, we recreate our MVP relationship with each trip to the server. Persisting state and referencing "Page.IsPostBack" becomes necessary. The sample application and the code snippets below illustrate how we recreate our presenter and pass the IsPostBack value to manage this difficulty. What I have discovered with the MVP pattern is that it can have many variations in ASP.NET, and choosing which one to implement is really a matter of preference. My preferred implementation contains characteristics of some of the authors mentioned above as well as what I have discovered for myself over the past year. </p>
<p>The next section will be divided up into three parts, one for each implementation. I will start with my original introduction to MVP in ASP.NET, then move on to my more familiar event-driven approach. Finally, I will provide a third implementation that I feel provides greater reusability. The sample application I am including with this article has basic examples of each implementation. Each section will describe which modules in the sample app correspond. The code snippets I am providing below are extremely simplistic and are not complete. They are thorough enough to illustrate their points. </p>
<h2>The First Implementation</h2>
<p>The first implementation is <a href="http://www.codeproject.com/aspnet/ModelViewPresenter.asp" target=_blank><u><font color=#800080>Billy McCafferty's</font></u></a>. It introduces the role of the "view initializer and page redirector" to the ASPX page. The view is the ASCX user control, and the presenter only knows about the interface describing the view. The ASPX page is responsible for instantiating the presenter and passing it the view and any model objects the presenter requires. It then attaches the presenter to the view, so the view may reference the presenter when necessary. Lastly, it calls "InitView" on the presenter to simulate the Page.IsPostBack event in ASP.NET. </p>
<p>This example is implemented as the "Product" module in the sample application. </p>
<div class=precollapse id=premain0 style="WIDTH: 100%"><img id=preimg0 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="0"><span id=precollapse0 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="0"> Collapse</span></div>
<pre id=pre0 style="MARGIN-TOP: 0px"><strong>Note: The code below is used to highlight the main points of this design. Please see the sample application for a working model.</strong>
<strong>The Presenter</strong>
public class Presenter
{
public Presenter(IView view, IModel model)
{
this.view = view;
this.model = model;
}
public void InitView(bool isPostBack)
{
if(!isPostBack)
{
view.SetProducts(model.GetProducts());
}
}
public void SaveProducts(IList&lt;IProduct&gt; products)
{
model.SaveProducts(products);
}
}
<strong>The ASPX Page: The Starting Point</strong>
The ASPX HTML references the ASCX user control, and in code behind we have this.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
presenter = new Presenter(view,model;
view.AttachPresenter(presenter);
presenter.InitView(Page.IsPostBack);
}
<strong>The ASCX User Control</strong>
public void AttachPresenter(Presenter presenter)
{
this.presenter = presenter;
}
public void SetProducts(IList&lt;IProduct&gt; products)
{
<span class=cpp-comment>// bind products to view</span>
}
<strong>The View Interface</strong>
public interface IView
{
void AttachPresenter(Presenter presenter);
void SetProducts(IList&lt;IProduct&gt; products);
}
</pre>
<h2>The Second Implementation</h2>
<p>The second implementation is an event-driven approach. It uses the "view initializer and page redirector" role for the ASPX page just as the first. The ASCX user control implements a view interface that declares events that will be raised to a presenter. The view knows nothing about the presenter; it only knows how to raise events. The ASPX page initializes the presenter, passing to it the view and any model objects. The ASPX page is not responsible for attaching the presenter to a view, nor calling "InitView" on the presenter. Its only job is to wire up the presenter with the view instance and model objects, and to respond to events that the presenter might raise, such as a page redirect or some type of status event. </p>
<p>This example is implemented as the "Customer" module in the sample application. </p>
<div class=precollapse id=premain1 style="WIDTH: 100%"><img id=preimg1 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="1"><span id=precollapse1 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="1"> Collapse</span></div>
<pre id=pre1 style="MARGIN-TOP: 0px"><strong>Note: The code below is used to highlight the main points of this design. Please see the sample application for a working model.</strong>
<strong>The Presenter</strong>
public class Presenter
{
public Presenter(IView view, IModel model)
{
this.view = view;
this.model = model;
this.view.OnViewLoad += new EventHandler&lt;SingleValueEventArgs&lt;bool&gt;&gt;(OnViewLoadListener);
this.view.SaveProducts += new EventHandler&lt;SingleValueEventArgs&lt;IList&lt;IProduct&gt;&gt;&gt;(SaveProductListener);
}
private void OnViewLoadListener(object sender, SingleValueEventArgs&lt;bool&gt; isPostBack)
{
if (!isPostBack.Value)
{
<span class=cpp-comment>// Set the view for the first time</span>
view.SetProducts(model.GetProducts());
}
}
private void SaveProductListener(object sender, SingleValueEventArgs&lt;IList&lt;IProduct&gt;&gt; products)
{
model.SaveProducts(products.Value);
}
}
<strong>The ASPX Page: The Starting Point</strong>
The ASPX HTML references the ASCX user control, and in code behind we have this.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
presenter = new Presenter(this,model);
}
<strong>The ASCX User Control</strong>
protected override void OnLoad(EventArgs e)
{
EventHandler eventHandler = OnViewLoad;
if (eventHandler != null)
{
<span class=cpp-comment>// Invoke our delegate</span>
eventHandler(this, new SingleValueEventArgs&lt;bool&gt;(Page.IsPostBack));
}
base.OnLoad(e);
}
public void SetProducts(IList&lt;IProduct&gt; products)
{
<span class=cpp-comment>// bind products to view</span>
}
protected void btnSave_Click(object sender, EventArgs e)
{
<span class=cpp-comment>// Raise our event</span>
OnSaveProducts(GetProducts());
}
public event EventHandler&lt;SingleValueEventArgs&lt;string&gt;&gt; SaveProducts;
public virtual void OnSaveProducts(IList&lt;IProduct&gt;&gt; products)
{
EventHandler&lt;SingleValueEventArgs&lt;IList&lt;IProduct&gt;&gt;&gt; eventHandler = SaveProducts;
if (eventHandler != null)
{
eventHandler(this, new SingleValueEventArgs&lt;IList&lt;IProduct&gt;&gt;(products));
}
}
<strong>The View Interface</strong>
public interface IView
{
event EventHandler OnViewLoad;
event EventHandler&lt;SingleValueEventArgs&lt;IList&lt;IProduct&gt;&gt;&gt;SaveProducts;
void SetProducts(IList&lt;IProduct&gt; products);
}
</pre>
<h2>The Third Implemenation</h2>
<p>The third implementation delegates the responsibility of creating the presenter, passing in the view and model, and calling "InitView" on the presenter to the ASCX user control (view). The view has a reference to its presenter. The presenter only knows about an interface to the view. The ASPX page is used to add the user control to the page, nothing further. Since the ASPX's responsibilities from the first and second implementations now fall firmly within the responsibility of the ASCX user control, my views are easily reusable throughout my application. I can drag a user control onto a new page and with it comes its presenter, all ready to go out of the box. </p>
<p>This example is implemented as the "Employee" module in the sample application. </p>
<div class=precollapse id=premain2 style="WIDTH: 100%"><img id=preimg2 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="2"><span id=precollapse2 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="2"> Collapse</span></div>
<pre id=pre2 style="MARGIN-TOP: 0px"><strong>Note: The code below is used to highlight the main points of this design. Please see the sample application for a working model.</strong>
<strong>The Presenter</strong>
public class Presenter
{
public Presenter(IView view, IModel model)
{
this.view = view;
this.model = model;
}
public void InitView(bool isPostBack)
{
if(!isPostBack)
{
view.SetProducts(model.GetProducts());
}
}
public void SaveProducts(IList&lt;IProduct&gt; products)
{
model.SaveProducts(products);
}
}
<strong>The ASPX Page</strong>
The ASPX HTML references the ASCX user control, nothing futher in code behind.
<strong>The ASCX User Control: The Starting Point</strong>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
presenter = new Presenter(this,model);
presenter.InitView(Page.IsPostBack);
}
public void SetProducts(IList&lt;IProduct&gt; products)
{
<span class=cpp-comment>// bind products to view</span>
}
<strong>The View Interface</strong>
public interface IView
{
void SetProducts(IList&lt;IProduct&gt; products);
}
</pre>
<h2>Reflecting on the Implementations</h2>
<p>With each of the implementations, there are characteristics I favor and those I have difficulty accepting. Again, since there is no true MVP framework for ASP.NET as this time, there are no constraints forcing me to adhere to one implementation. Determining your flavor of MVP really depends on the level of separation of concerns with which you are most comfortable, and to what degree you feel your classes should be testable. </p>
<p>I like the use of the ASPX page as the "view initializer and page redirector" with the first two implementations. I feel that this is a well suited responsibility for the ASPX page that should not reside with the view. The view, in my opinion, should only be concerned with view-specific responsibilities. Determining what defines a view-specific responsibility is debatable and something I feel like I have wrestled with too often. </p>
<p>In the second implementation, I prefer how the view is ignorant of the presenter. The view is decoupled from the presenter. It only raises events, and the first event it raises, "OnViewLoad," signifies the control's loading state and passes the Page's IsPostBack value. The presenter listens for events on the view interface and commands the view to do some action when responding. The ASPX page instantiates the presenter, passing in the view instance and the model. It can register for events on the presenter as it needs. </p>
<p>What I do not like about the first two implementations is that since the ASPX page is involved, reusing the ASCX user control requires more work. If I want to add a user control to a different ASPX page, I now need to instantiate my model-view-presenter relationship in the new ASPX page. This becomes cumbersome when I have nested MVP relationships, where one user control may contain another user control. This dependency can be removed if I assign the responsibility of instantiating the presenter with the view and model from the ASPX page to the ASCX user control (view). As a result, the view now has more responsibility, but it is now more reusable. This added responsibility is something I may not agree with philosophically, but it helps improve usability, and my classes are still testable. </p>
<p>While I like the idea that my view is decoupled from the presenter in the event-driven approach, there really is no need for this separation. Using events is not always intuitive and reliable, and writing unit tests for events requires a little extra effort. There is no guarantee that the presenter subscribes to all the appropriate events on the view. </p>
<p>After settling my philosophical debates and finally feeling comfortable with certain responsibilities of the ASPX page, ASCX user control, and presenter in ASP.NET, I have created this third implementation. This third implementation is similar to the first implementation but it omits the role of the ASPX "view initializer and page redirector." On the positive side, my view is more reusable across my application since it is more self reliant. On the negative side, my view now has the added responsibility of creating the presenter and responding to events the presenter may raise. Even though I may feel that certain responsibilities are crossing boundaries, I keep reminding myself that this is MVP in ASP.NET - this is not a true MVC framework that enforces that good separation of concerns like <a href="http://www.castleproject.org/monorail/index.html" target=_blank><u><font color=#0000ff>Monorail</font></u></a>. </p>
<h2>Conclusion</h2>
<p>MVP provides a number of advantages, but to me, the two most important are separation of concerns and testability. There is a fair amount of overhead involved in using MVP, so if you are not planning on writing unit tests, I would definitely reconsider using the pattern. </p>
<p>As we see with the three different implementations, there are numerous ways to implement the pattern in ASP.NET. There are even more ways than what I have chosen to display. Choose an implementation that best suits your needs. I have to work hard at implementing MVP in ASP.NET, and there are certain tradeoffs I need to be willing to accept. As long as my code is testable, reusable, maintainable, and there exists a good degree of separation of concerns, I am happy. </p>
<p>With Microsoft's news of releasing an MVC framework for ASP.NET, there is hope on the horizon for a framework that enforces good separation of concerns and testability. The <a href="http://www.castleproject.org/monorail/index.html" target=_blank><u><font color=#0000ff>Castle Project's Monorail</font></u></a> is another MVC framework that I highly recommend. If you cannot wait for Microsoft's MVC framework, or do not wish to port your application to Monorail at this time, then implementing MVP could be your answer. </p>
<h2>About the Sample Project</h2>
<p>The sample project is written in ASP.NET 2.0 using C#. I am using the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=06616212-0356-46a0-8da2-eebc53a68034&amp;displaylang=en" target=_blank><u><font color=#0000ff>Northwind database</font></u></a>. I am using <a href="http://subsonicproject.com/" target=_blank><u><font color=#0000ff>SubSonic</font></u></a> as my data access layer. Since SubSonic is built using the active record pattern, I do have to use interfaces in order to make my DAO classes testable. For my unit testing, I am using <a href="http://www.ayende.com/projects/rhino-mocks.aspx" target=_blank><u><font color=#0000ff>RhinoMocks</font></u></a> as my mocking framework. </p>
<p>The sample application is comprised of five projects. The WebApp, Model, Presentation layer, Presentation.Tests, and SubSonic data access layer. This sample is simplistic and should be used as a demo. I may be doing some things in code for the sake of brevity and to simplify the concepts. This is my disclaimer for not providing "production" code with all the frameworks, tools, and layers I typically create. </p>
<h2>History</h2>
<p>Initial Upload: November 6, 2007.<br></p><img src ="http://www.cnitblog.com/seeyeah/aggbug/36127.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-10 21:47 <a href="http://www.cnitblog.com/seeyeah/archive/2007/11/10/36127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NHibernate 访问Access配置【NHibernate 版本“1.2.0.GA”】</title><link>http://www.cnitblog.com/seeyeah/archive/2007/10/12/34743.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 11 Oct 2007 17:05:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/10/12/34743.html</guid><description><![CDATA[在App.Config文件中<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: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">xml&nbsp;version="1.0"&nbsp;encoding="utf-8"&nbsp;</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><span style="COLOR: #000000"><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">configSections</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">section&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="hibernate-configuration"</span><span style="COLOR: #ff0000">&nbsp;type</span><span style="COLOR: #0000ff">="NHibernate.Cfg.ConfigurationSectionHandler,&nbsp;NHibernate"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br><br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">configSections</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">hibernate-configuration&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:hibernate-configuration-2.2"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;an&nbsp;ISessionFactory&nbsp;instance&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">session-factory&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="urn:nhibernate-configuration-2.2"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;properties&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br>&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">="connection.provider"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">NHibernate.Connection.DriverConnectionProvider</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</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">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="connection.driver_class"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">NHibernate.JetDriver.JetDriver,&nbsp;NHibernate.JetDriver</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><br>&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">="dialect"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">NHibernate.JetDriver.JetDialect,&nbsp;NHibernate.JetDriver</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</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">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="connection.connection_string"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">Provider=Microsoft.Jet.OLEDB.4.0;Data&nbsp;Source=D:\appTemp\TestCastle\Castle3\Test.mdb</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</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">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="show_sql"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">false</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</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">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="use_outer_join"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">true</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</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">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="use_proxy_validator"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">false</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">property</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">session-factory</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">hibernate-configuration</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>注意：<br>1、xmlns = "urn:nhibernate-configuration-2.2"必须加上。值urn:nhibernate-configuration-2.2和urn:hibernate-configuration-2.2效果一样。<br><br>2、use-proxy-validtor设置为false的话，POJO类的属性就不需要标记为virtual。</p>
<p><br>&nbsp;</p>
用NHibernate.Mapping.Attributes配置的简单Pojo类，可以省掉一大堆的XML 。本人喜欢Attribute配置。<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"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">[Class(Table&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Users</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&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;UserPojo<br><img id=Codehighlighter1_55_1392_Open_Image onclick="this.style.display='none'; Codehighlighter1_55_1392_Open_Text.style.display='none'; Codehighlighter1_55_1392_Closed_Image.style.display='inline'; Codehighlighter1_55_1392_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_55_1392_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_55_1392_Closed_Text.style.display='none'; Codehighlighter1_55_1392_Open_Image.style.display='inline'; Codehighlighter1_55_1392_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_55_1392_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_55_1392_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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">int</span><span style="COLOR: #000000">&nbsp;userID;<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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">string</span><span style="COLOR: #000000">&nbsp;name;<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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">int</span><span style="COLOR: #000000">&nbsp;age;<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;DateTime&nbsp;birthDate;<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&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">string</span><span style="COLOR: #000000">&nbsp;description;<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;UserPojo()<br><img id=Codehighlighter1_246_445_Open_Image onclick="this.style.display='none'; Codehighlighter1_246_445_Open_Text.style.display='none'; Codehighlighter1_246_445_Closed_Image.style.display='inline'; Codehighlighter1_246_445_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_246_445_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_246_445_Closed_Text.style.display='none'; Codehighlighter1_246_445_Open_Image.style.display='inline'; Codehighlighter1_246_445_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_246_445_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_246_445_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userID&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">);<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;age&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;birthDate&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(DateTime);<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">);<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Id(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;Column&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UserID</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;TypeType&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">))]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Generator(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;Class&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">identity</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;UserID<br><img id=Codehighlighter1_585_666_Open_Image onclick="this.style.display='none'; Codehighlighter1_585_666_Open_Text.style.display='none'; Codehighlighter1_585_666_Closed_Image.style.display='inline'; Codehighlighter1_585_666_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_585_666_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_585_666_Closed_Text.style.display='none'; Codehighlighter1_585_666_Open_Image.style.display='inline'; Codehighlighter1_585_666_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_585_666_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_585_666_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_603_620_Open_Image onclick="this.style.display='none'; Codehighlighter1_603_620_Open_Text.style.display='none'; Codehighlighter1_603_620_Closed_Image.style.display='inline'; Codehighlighter1_603_620_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_603_620_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_603_620_Closed_Text.style.display='none'; Codehighlighter1_603_620_Open_Image.style.display='inline'; Codehighlighter1_603_620_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_603_620_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_603_620_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;userID;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_638_656_Open_Image onclick="this.style.display='none'; Codehighlighter1_638_656_Open_Text.style.display='none'; Codehighlighter1_638_656_Closed_Image.style.display='inline'; Codehighlighter1_638_656_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_638_656_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_638_656_Closed_Text.style.display='none'; Codehighlighter1_638_656_Open_Image.style.display='inline'; Codehighlighter1_638_656_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_638_656_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_638_656_Open_Text><span style="COLOR: #000000">{&nbsp;userID&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Property(Column&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Age</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Int32</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Age<br><img id=Codehighlighter1_752_827_Open_Image onclick="this.style.display='none'; Codehighlighter1_752_827_Open_Text.style.display='none'; Codehighlighter1_752_827_Closed_Image.style.display='inline'; Codehighlighter1_752_827_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_752_827_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_752_827_Closed_Text.style.display='none'; Codehighlighter1_752_827_Open_Image.style.display='inline'; Codehighlighter1_752_827_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_752_827_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_752_827_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_770_784_Open_Image onclick="this.style.display='none'; Codehighlighter1_770_784_Open_Text.style.display='none'; Codehighlighter1_770_784_Closed_Image.style.display='inline'; Codehighlighter1_770_784_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_770_784_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_770_784_Closed_Text.style.display='none'; Codehighlighter1_770_784_Open_Image.style.display='inline'; Codehighlighter1_770_784_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_770_784_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_770_784_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;age;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_802_817_Open_Image onclick="this.style.display='none'; Codehighlighter1_802_817_Open_Text.style.display='none'; Codehighlighter1_802_817_Closed_Image.style.display='inline'; Codehighlighter1_802_817_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_802_817_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_802_817_Closed_Text.style.display='none'; Codehighlighter1_802_817_Open_Image.style.display='inline'; Codehighlighter1_802_817_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_802_817_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_802_817_Open_Text><span style="COLOR: #000000">{&nbsp;age&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Property(Column&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Name</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">string</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;Name<br><img id=Codehighlighter1_919_996_Open_Image onclick="this.style.display='none'; Codehighlighter1_919_996_Open_Text.style.display='none'; Codehighlighter1_919_996_Closed_Image.style.display='inline'; Codehighlighter1_919_996_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_919_996_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_919_996_Closed_Text.style.display='none'; Codehighlighter1_919_996_Open_Image.style.display='inline'; Codehighlighter1_919_996_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_919_996_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_919_996_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_937_952_Open_Image onclick="this.style.display='none'; Codehighlighter1_937_952_Open_Text.style.display='none'; Codehighlighter1_937_952_Closed_Image.style.display='inline'; Codehighlighter1_937_952_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_937_952_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_937_952_Closed_Text.style.display='none'; Codehighlighter1_937_952_Open_Image.style.display='inline'; Codehighlighter1_937_952_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_937_952_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_937_952_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;name;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_970_986_Open_Image onclick="this.style.display='none'; Codehighlighter1_970_986_Open_Text.style.display='none'; Codehighlighter1_970_986_Closed_Image.style.display='inline'; Codehighlighter1_970_986_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_970_986_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_970_986_Closed_Text.style.display='none'; Codehighlighter1_970_986_Open_Image.style.display='inline'; Codehighlighter1_970_986_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_970_986_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_970_986_Open_Text><span style="COLOR: #000000">{&nbsp;name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Property(Column&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BirthDate</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DateTime</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;&nbsp;DateTime&nbsp;BirthDate<br><img id=Codehighlighter1_1102_1189_Open_Image onclick="this.style.display='none'; Codehighlighter1_1102_1189_Open_Text.style.display='none'; Codehighlighter1_1102_1189_Closed_Image.style.display='inline'; Codehighlighter1_1102_1189_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1102_1189_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1102_1189_Closed_Text.style.display='none'; Codehighlighter1_1102_1189_Open_Image.style.display='inline'; Codehighlighter1_1102_1189_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1102_1189_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1102_1189_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_1120_1140_Open_Image onclick="this.style.display='none'; Codehighlighter1_1120_1140_Open_Text.style.display='none'; Codehighlighter1_1120_1140_Closed_Image.style.display='inline'; Codehighlighter1_1120_1140_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1120_1140_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1120_1140_Closed_Text.style.display='none'; Codehighlighter1_1120_1140_Open_Image.style.display='inline'; Codehighlighter1_1120_1140_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_1120_1140_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1120_1140_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;birthDate;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1158_1179_Open_Image onclick="this.style.display='none'; Codehighlighter1_1158_1179_Open_Text.style.display='none'; Codehighlighter1_1158_1179_Closed_Image.style.display='inline'; Codehighlighter1_1158_1179_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1158_1179_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1158_1179_Closed_Text.style.display='none'; Codehighlighter1_1158_1179_Open_Image.style.display='inline'; Codehighlighter1_1158_1179_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_1158_1179_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1158_1179_Open_Text><span style="COLOR: #000000">{&nbsp;birthDate&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Property(Column&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Description</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">string</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br><img src="http://www.cnitblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;Description<br><img id=Codehighlighter1_1295_1386_Open_Image onclick="this.style.display='none'; Codehighlighter1_1295_1386_Open_Text.style.display='none'; Codehighlighter1_1295_1386_Closed_Image.style.display='inline'; Codehighlighter1_1295_1386_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1295_1386_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1295_1386_Closed_Text.style.display='none'; Codehighlighter1_1295_1386_Open_Image.style.display='inline'; Codehighlighter1_1295_1386_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1295_1386_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1295_1386_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_1313_1335_Open_Image onclick="this.style.display='none'; Codehighlighter1_1313_1335_Open_Text.style.display='none'; Codehighlighter1_1313_1335_Closed_Image.style.display='inline'; Codehighlighter1_1313_1335_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1313_1335_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1313_1335_Closed_Text.style.display='none'; Codehighlighter1_1313_1335_Open_Image.style.display='inline'; Codehighlighter1_1313_1335_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_1313_1335_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1313_1335_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;description;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1353_1376_Open_Image onclick="this.style.display='none'; Codehighlighter1_1353_1376_Open_Text.style.display='none'; Codehighlighter1_1353_1376_Closed_Image.style.display='inline'; Codehighlighter1_1353_1376_Closed_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1353_1376_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1353_1376_Closed_Text.style.display='none'; Codehighlighter1_1353_1376_Open_Image.style.display='inline'; Codehighlighter1_1353_1376_Open_Text.style.display='inline';" src="http://www.cnitblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_1353_1376_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnitblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1353_1376_Open_Text><span style="COLOR: #000000">{&nbsp;description&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cnitblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br><span style="COLOR: red">注：以上的实体类有个错误，Id的Attribute一定要指定Name属性！！</span>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/34743.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-10-12 01:05 <a href="http://www.cnitblog.com/seeyeah/archive/2007/10/12/34743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>读GI源码、学JS编程——Javascript动态加载技术。 </title><link>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25845.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 17 Apr 2007 17:20:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25845.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/25845.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/25845.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/25845.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt">From&nbsp; <a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/city22/">city22</a></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体"><br><br>在大型</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">RIA<span lang=ZH-CN>中，动态加载技术十分重要，毕竟几百</span>K<span lang=ZH-CN>甚至</span>M<span lang=ZH-CN>级别的脚本让用户等待加载完了再浏览是不可能。大多数成熟的</span>framework<span lang=ZH-CN>都有动态加载技术的实现，就是说先加载一个最基础功能，然后利用动态加载技术慢慢把所有的脚本加进来，或者说需要某个功能的时候再加载某个模块所</span><span style="mso-spacerun: yes">&nbsp; </span><span lang=ZH-CN>需要的</span>javascript<span lang=ZH-CN>的文件。</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">好了不说那么多</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">P<span lang=ZH-CN>话了，尽快进入正题来看看</span>GI<span lang=ZH-CN>是怎么实现的动态加载技术。其实</span>GI<span lang=ZH-CN>的</span>load<span lang=ZH-CN>做的很复杂，因为他涉及到了进度条阿等等很多乱七八糟的东西，我们就不分析那么多东西了，来看看他最基础的东西是如何实现的吧。</span>GI<span lang=ZH-CN>中的动态加载有两种，一种是用的是</span>XMLHttpRequest<span lang=ZH-CN>来请求脚本内容，另一种则是加入一个</span> &lt;script&gt;<span lang=ZH-CN>标签的方式来动态加入脚本以达到动态加载的功能。网上也许还有其它得方法，但其它得方法也都是根据这两种演变来的，还是以这两种为基础得。我们来看看它是如何实现的。</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">首先是第一种<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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">*&nbsp;@private&nbsp;@jsxobf-clobber&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassLoader_prototype.loadJSFileSync&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">(strURI)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;req&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;jsx3.net.Request();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;req.open(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">GET</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;strURI,&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;req.send();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(req.getStatus()&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;jsx3.net.Request.STATUS_OK)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;script&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;req.getResponseText();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jsx3.eval(script);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br></span></div>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">呵呵，</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">XMLHttpRequest<span lang=ZH-CN>的</span>GET<span lang=ZH-CN>请求就可以吧</span>js<span lang=ZH-CN>文件拿下来，然后用</span>eval<span lang=ZH-CN>执行所有的脚本，这样就达到了加载脚本的功能了。方法也很简单，也就不用多介绍什么了吧。不过我记着有人说过</span>js<span lang=ZH-CN>必须要</span>UTG-8<span lang=ZH-CN>格式存的，但测试了一下，不用好像也可以。</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">我们看在</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">package<span lang=ZH-CN>。</span>Js<span lang=ZH-CN>文件里面有个有意思的方法</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"></span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体"><o: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">&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">*<br>&nbsp;&nbsp;&nbsp;*&nbsp;Ensures&nbsp;that&nbsp;one&nbsp;or&nbsp;more&nbsp;classes&nbsp;is&nbsp;available&nbsp;before&nbsp;this&nbsp;method&nbsp;returns.&nbsp;Any&nbsp;class&nbsp;that&nbsp;fails&nbsp;to&nbsp;load&nbsp;will<br>&nbsp;&nbsp;&nbsp;*&nbsp;throw&nbsp;an&nbsp;error.&nbsp;Only&nbsp;classes&nbsp;that&nbsp;can&nbsp;be&nbsp;found&nbsp;by&nbsp;the&nbsp;system&nbsp;class&nbsp;loader&nbsp;may&nbsp;be&nbsp;loaded&nbsp;in&nbsp;this&nbsp;manner.<br>&nbsp;&nbsp;&nbsp;*<br>&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;strClass&nbsp;{String<img src="http://www.cnblogs.com/Images/dot.gif">}&nbsp;the&nbsp;fully-qualified&nbsp;names&nbsp;of&nbsp;the&nbsp;classes&nbsp;to&nbsp;load.<br>&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;3.2<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;jsx3.require&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">(strClass)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">var</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;arguments.length;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;className&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;arguments[i];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;className&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;jsx3._REQUIRE_MAP[className]&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;className;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(jsx3.Class.forName(className)&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;jsx3.CLASS_LOADER.loadClass(className);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;};<br></span></div>
<br>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes">需要说明的是</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes">jsx3.ClASS_LOADER.loadClass()<span lang=ZH-CN>方法中其实就是调用了</span>loadJSFileSync()<span lang=ZH-CN>方法，这个方法就是在调用类之前如果该类没有被加载将会在被</span>load<span lang=ZH-CN>一次做到需要什么才用什么，不会把所有</span>Javascipt<span lang=ZH-CN>都加载进来。</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">然后我们再来看第二种方法，添加标签的方式来</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">load<span lang=ZH-CN>脚本<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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">*&nbsp;@private&nbsp;@jsxobf-clobber&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassLoader_prototype.loadScript&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">(strSrc,&nbsp;strId)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;instance&nbsp;a&nbsp;new&nbsp;DOM&nbsp;element</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;element&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;document.createElement(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.src&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strSrc;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;'text</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">javascript';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strId;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.language&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;'javascript';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;set&nbsp;up&nbsp;onload&nbsp;handler</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;me&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.IE)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.onreadystatechange&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">()&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;state&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.readyState;<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;(state&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">loaded</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;state&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">interactive</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;state&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">complete</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;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.onreadystatechange&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;me._loaded[strSrc]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;me._publish({subject:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">load</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;type:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;src:strSrc});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.MOZ&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.KON)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.onload&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">()&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.onload&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;me._loaded[strSrc]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;me._publish({subject:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">load</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;type:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;src:strSrc});&nbsp;<br>&nbsp;&nbsp;&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;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element.jsxid&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strSrc;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;bind&nbsp;the&nbsp;element&nbsp;to&nbsp;the&nbsp;browser&nbsp;DOM&nbsp;to&nbsp;begin&nbsp;loading&nbsp;the&nbsp;resource</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.getElementsByTagName(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">head</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].appendChild(element);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br></span></div>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体"><br>呵呵，相信大家都能看懂吧，就是在</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">head<span lang=ZH-CN>标签中加入了</span>script<span lang=ZH-CN>标签，</span>src<span lang=ZH-CN>当然就是重点了，而如何判断脚本加载结束，也明确的告诉我们，在</span>IE<span lang=ZH-CN>下用</span>onreadystatechange<span lang=ZH-CN>，在</span>Firefox<span lang=ZH-CN>下用</span>onload<span lang=ZH-CN>。呵呵，好像很简单吧。</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">到这里，我突然想到一个问题，</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">script<span lang=ZH-CN>标签好像功能很强大啊，竟然可以用来读服务器上的</span>Javascript<span lang=ZH-CN>文件，跟</span>XMLHttpRequest<span lang=ZH-CN>有同样的功能啊，看来这个东西可以被我们来利用一下了，做点手脚也许会有不同的效果哦，来看。</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">首先我们写一个</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">Handlers<span lang=ZH-CN>用来模拟一个</span>Javascript<span lang=ZH-CN>文件，然后用这个</span>handler<span lang=ZH-CN>来生成返回的内容，</span><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"></span><o: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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><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;&nbsp;&nbsp;&nbsp;&nbsp;&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;type</span><span style="COLOR: #0000ff">="JsTest.JsHandler"</span><span style="COLOR: #ff0000">&nbsp;path</span><span style="COLOR: #0000ff">="demo2.js"</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">httpHandlers</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span></div>
<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;&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;JsHandler:IHttpHandler,IRequiresSessionState<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">void</span><span style="COLOR: #000000">&nbsp;ProcessRequest(HttpContext&nbsp;context)<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">string</span><span style="COLOR: #000000">&nbsp;action&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;context.Request[</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">action</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">].ToString();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.Response.Write(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">alert(\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hello&nbsp;world&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;+&nbsp;action&nbsp;+&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></span></div>
<br>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt; TEXT-INDENT: 17.25pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">这个</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">Handler<span lang=ZH-CN>中我只是返回了一段</span>alert<span lang=ZH-CN>，呵呵，下面用</span>script<span lang=ZH-CN>来加载他吧，刚才看到的一样，只是</span>script<span lang=ZH-CN>中</span>src<span lang=ZH-CN>我们做了点手脚，嘿嘿指向的是</span>demo2.js?action=city22<span lang=ZH-CN>，哈哈看到了吧，就是个</span>GET<span lang=ZH-CN>访问方式啊！<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">window.onload</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;script</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">document.createElement(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;script.type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">'text</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">javascript';<br>&nbsp;&nbsp;&nbsp;&nbsp;script.language</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">'javascript';<br>&nbsp;&nbsp;&nbsp;&nbsp;script.src</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">demo2.js?action=city22</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;document.getElementsByTagName(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">head</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].appendChild(script);<br>}<br></span></div>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">测试成功，哈，看来还真是能模拟一个</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">XMLHttpRequest<span lang=ZH-CN>了。<br><img height=165 alt="" src="http://www.cnblogs.com/images/cnblogs_com/city22/testSuccess.jpg" width=390 border=0></span><o:p></o:p></span></p>
</span><o:p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 10pt"><span lang=ZH-CN style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">不过有人肯定该问了，这个有什么用</span><span style="FONT-FAMILY: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-theme-font: minor-fareast; mso-hansi-theme-font: minor-fareast; mso-fareast-font-family: 宋体">XMLHttpRequest<span lang=ZH-CN>已经很好用了啊，干嘛在来个这东西。我感觉这东西在一定的领域还是能发挥作用的。</span>XMLHttpRequest<span lang=ZH-CN>不能垮站访问，这是个问题，也就是说你在</span>www.a.net/index.html<span lang=ZH-CN>上写了一段</span>XMLHttpRequest<span lang=ZH-CN>不能调用</span>www.b.net<span lang=ZH-CN>上的任何东西，即使改动</span>document.domian <span lang=ZH-CN>也不可以，唉多可惜。当然了</span>Iframe<span lang=ZH-CN>给我们解决了这个问题，但是</span>script<span lang=ZH-CN>标签又给了我们新的选择，我们完全可以模拟</span>open(),send()<span lang=ZH-CN>，等这些方法，返回的脚本中使用变量作为返回内容来模拟</span>responseText<span lang=ZH-CN>。看来跨站问题又有了新的解决思路了。以后</span>script<span lang=ZH-CN>标签值得我们去深入研究一下咯。</span></span></p>
</span></span></span></o:p></o:p></o:p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/25845.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-04-18 01:20 <a href="http://www.cnitblog.com/seeyeah/archive/2007/04/18/25845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用ObjectDataSource实现自定义分页的心得总结 </title><link>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25844.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 17 Apr 2007 17:15:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25844.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/25844.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/25844.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/25844.html</trackback:ping><description><![CDATA[From <a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/weiweictgu/"><u><font color=#0000ff>漂泊雪狼的博客</font></u></a><br><br>&nbsp;在Web应用开发中列表的分页是难免要遇到的问题，在ASP.NET 2.0中微软为我们提供了很多数据源控件，如SqlDataSource、ObjectDataSource等，它们都可以实现默认分页，但是默认分页是在内存中实现的，用户量增大时Web服务器的负担会急剧增大，在多层体系结构程序开发中，往往把分页和排序的工作交给数据库服务器来完成，在网上也能找到很多能够快速实现分页的控件，但是做为一个程序员对分页的实现还是有一定的了解比较好，如果过渡的依赖于控件，你说写出的代码独立性就很差，一般在多层web应用开发中建议尽量使用ObjectDataSource，而不要使用SqlDataSource，因为ObjectDataSource有一下有点：<br>1、SqlDataSource是针对Sql Server的，对其他的数据库支持不够，例如在访问Oracle数据库时，要用存储过程返回结构集合SqlDataSource显得无能为力。<br>2、ObjectDataSource 提供一个 TypeName 属性（而不是 ConnectionString属性），该属性指定用于执行数据操作的业务逻辑类的类名，ObjectDataSource可以通过TypeName 属性直接调用业务层的类，在多层应用中ObjectDataSource 显得很实用，而SqlDataSource要在页面上指定ConnectionString、Command，系统的层次结构被搞乱，不便于系统的维护工作。<br>3、ObjectDataSource 控件提供了<span>EnablePaging</span><span>属性、SelectCountMethod属性、StartRowIndexParameterName属性和MaximumRowsParameterName属性专门支持数据源分页。</span>&nbsp;SelectCountMethod属性指定的是获取数据项总数的方法。StartRowIndexParameterName属性用于指定一个参数的名称，如程序中不特别设定，其默认参数名为startRowIndex，该参数代表该页数据项的开始行索引；MaximumRowsParameterName属性也用于指定一个参数名称，其默认参数名为maximumRows，该参数代表一页中容纳的数据项总数。SqlDataSource完全没有提供这些功能。<br>4、SqlDataSource只支持内存分页，而不支持数据库分页，ObjectDataSource 两者都支持，内存分页每次都检索出所有数据并将其绑定到数据绑定控件中，虽然该控件只能一页一页显示这些数据，但是所有数据其实都已经被绑定到控件上了。而数据库分页的含义是显示到哪一页就检索并绑定哪一页的数据。显然在大数据量的情况下，数据库分页的效率会高很多。<br><strong>关于分页方法<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很多人写分页的方法喜欢创建临时表，虽然这是一个快捷的实现方法，但这样做效率肯定很低，其实在SQL Server和Oracle中分别使用Top和ROWNUM可以很方便的使用排序，充分利用数据库服务器来做计算可以降低web服务的负担。<br><br>SQL Server的分页代码：<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"><img id=Code_Closed_Image_111156 onclick="this.style.display='none'; Code_Closed_Text_111156.style.display='none'; Code_Open_Image_111156.style.display='inline'; Code_Open_Text_111156.style.display='inline';" height=16 src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width=11 align=top><img id=Code_Open_Image_111156 style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_111156.style.display='none'; Code_Closed_Image_111156.style.display='inline'; Code_Closed_Text_111156.style.display='inline';" height=16 src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width=11 align=top><span id=Code_Closed_Text_111156 style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">SelectByPage</span><span id=Code_Open_Text_111156 style="DISPLAY: none"><br><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">SET</span><span style="COLOR: #000000">&nbsp;QUOTED_IDENTIFIER&nbsp;</span><span style="COLOR: #0000ff">ON</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">GO</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">SET</span><span style="COLOR: #000000">&nbsp;ANSI_NULLS&nbsp;</span><span style="COLOR: #0000ff">ON</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">GO</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">ALTER</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">proc</span><span style="COLOR: #000000">&nbsp;SelectByPage(</span><span style="COLOR: #008000">@startRowIndex</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">int</span><span style="COLOR: #000000">,</span><span style="COLOR: #008000">@maximumRows</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">int</span><span style="COLOR: #000000">,</span><span style="COLOR: #008000">@SortBy</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">varchar</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">50</span><span style="COLOR: #000000">))<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">as</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">declare</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@TotalCnt</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">int</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">declare</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">varchar</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">8000</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">begin</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">select</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@TotalCnt</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">count</span><span style="COLOR: #000000">(</span><span style="COLOR: #808080">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;sys_user<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">select&nbsp;top&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">convert</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #000000">varchar</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">20</span><span style="COLOR: #000000">),</span><span style="COLOR: #008000">@maximumRows</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;*&nbsp;from&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">(</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;select&nbsp;top&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">convert</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #000000">varchar</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">20</span><span style="COLOR: #000000">),(</span><span style="COLOR: #008000">@TotalCnt</span><span style="COLOR: #808080">-</span><span style="COLOR: #008000">@startRowIndex</span><span style="COLOR: #000000">))&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;*&nbsp;from&nbsp;sys_user&nbsp;a&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;order&nbsp;by&nbsp;a.</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@SortBy</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;desc&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">)&nbsp;b</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;order&nbsp;by&nbsp;b.</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">@SortBy</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">exec</span><span style="COLOR: #000000">(</span><span style="COLOR: #008000">@sql</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">print&nbsp;@sql</span><span style="COLOR: #008080"><br></span><span style="COLOR: #008080">23</span><span style="COLOR: #008080"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">end</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">GO</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">SET</span><span style="COLOR: #000000">&nbsp;QUOTED_IDENTIFIER&nbsp;</span><span style="COLOR: #0000ff">OFF</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">GO</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">SET</span><span style="COLOR: #000000">&nbsp;ANSI_NULLS&nbsp;</span><span style="COLOR: #0000ff">ON</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">GO</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span></span></div>
<br><br>Oracle中的分页方法：<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"><img id=Code_Closed_Image_111620 style="DISPLAY: none" onclick="this.style.display='none'; Code_Closed_Text_111620.style.display='none'; Code_Open_Image_111620.style.display='inline'; Code_Open_Text_111620.style.display='inline';" height=16 src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width=11 align=top><img id=Code_Open_Image_111620 style="DISPLAY: inline" onclick="this.style.display='none'; Code_Open_Text_111620.style.display='none'; Code_Closed_Image_111620.style.display='inline'; Code_Closed_Text_111620.style.display='inline';" height=16 src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width=11 align=top><span id=Code_Closed_Text_111620 style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">select_by_page </span><span id=Code_Open_Text_111620 style="DISPLAY: inline"><br><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #008080">&nbsp;1</span><img id=Codehighlighter1_0_58_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_58_Open_Text.style.display='none'; Codehighlighter1_0_58_Closed_Image.style.display='inline'; Codehighlighter1_0_58_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_0_58_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_58_Closed_Text.style.display='none'; Codehighlighter1_0_58_Open_Image.style.display='inline'; Codehighlighter1_0_58_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span id=Codehighlighter1_0_58_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_0_58_Open_Text><span style="COLOR: #008080">/*</span><span style="COLOR: #008080">&nbsp;Formatted&nbsp;on&nbsp;2007/04/16&nbsp;11:16&nbsp;(Formatter&nbsp;Plus&nbsp;v4.8.8)&nbsp;</span><span style="COLOR: #008080">*/</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">CREATE</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #808080">OR</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">REPLACE</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">PROCEDURE</span><span style="COLOR: #000000">&nbsp;diswebuser.select_by_page&nbsp;(<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;p_start_page&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">NUMBER</span><span style="COLOR: #000000">,<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;p_page_size&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">NUMBER</span><span style="COLOR: #000000">,<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;p_sort_by&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">VARCHAR2</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>)<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">AS</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_cnt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">INTEGER</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">VARCHAR2</span><span style="COLOR: #000000">&nbsp;(</span><span style="FONT-WEIGHT: bold; COLOR: #800000">4000</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_start_index&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">INTEGER</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_end_index&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #000000">INTEGER</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">BEGIN</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">SELECT</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff00ff">COUNT</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #808080">*</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">INTO</span><span style="COLOR: #000000">&nbsp;v_cnt<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">FROM</span><span style="COLOR: #000000">&nbsp;side_slope;<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008080">--</span><span style="COLOR: #008080">v_start_index&nbsp;:=&nbsp;(p_start_page&nbsp;-&nbsp;1)&nbsp;*&nbsp;p_page_size&nbsp;+&nbsp;1;</span><span style="COLOR: #008080"><br></span><span style="COLOR: #008080">18</span><span style="COLOR: #008080"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;v_start_index&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;p_start_page&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #800000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_end_index&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;p_start_page&nbsp;</span><span style="COLOR: #808080">+</span><span style="COLOR: #000000">&nbsp;p_page_size;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;v_sql&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">SELECT&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;v_sql&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;(SELECT&nbsp;&nbsp;&nbsp;ROWNUM&nbsp;AS&nbsp;row_id,&nbsp;a.*&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;v_sql&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;side_slope&nbsp;a&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;v_sql&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ORDER&nbsp;BY&nbsp;side_slope_id)&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v_sql<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;&nbsp;WHERE&nbsp;row_id&nbsp;BETWEEN&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;TO_CHAR&nbsp;(v_start_index)<br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;AND&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;TO_CHAR&nbsp;(v_end_index)<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">&nbsp;&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;v_sql&nbsp;:</span><span style="COLOR: #808080">=</span><span style="COLOR: #000000">&nbsp;v_sql&nbsp;</span><span style="COLOR: #808080">||</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #ff0000">ORDER&nbsp;BY&nbsp;side_slope_id&nbsp;</span><span style="COLOR: #ff0000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.put_line&nbsp;(v_sql);<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">END</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #808080">/</span></span></div>
<br><br>当然在Oracle存储中返回结构集要使用ref cursor，使用Oracle的朋友一定很清楚，我在这里就不罗嗦了，那样写还得创建包，麻烦^_^，上面只是打印出了sql语句。<br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/25844.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-04-18 01:15 <a href="http://www.cnitblog.com/seeyeah/archive/2007/04/18/25844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(C#)Windows Shell 编程系列1 - 基础，浏览一个文件夹 </title><link>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25843.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 17 Apr 2007 17:08:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25843.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/25843.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25843.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/25843.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/25843.html</trackback:ping><description><![CDATA[From <a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/lemony/"><strong>柠檬的...</strong></a><br><br><span style="COLOR: red">（本系列文章由柠檬的(lc_mtt)原创，转载请注明出处，谢谢～）</span><br><br>Windows Shell 编程，即 Windows 外壳编程。我们所看到的资源管理器以及整个桌面，都是一个 Shell。<br><br>关于 Windows 外壳的基本概念，我这里不做详细介绍，不了解的朋友，可以看看 姜伟华 的 <a title=Windows外壳名字空间的浏览 href="http://blog.csdn.net/kingcom_xu/archive/2003/03/18/18943.aspx"><font color=#1a8bc8>Windows外壳名字空间的浏览</font></a>。<br><font lang=ZH-CN face=宋体><br>好，现在让我们从基础学起，早日做出一个强大的资源管理器软件。（偶也是初学者，多多指教）<br><br>
<p><span><strong>1 - 基础，浏览一个文件夹</strong></span></p>
<p><strong><span>我们知道，在</span><span>win32</span><span>中是以外壳名字空间</span><span>的形式来组织文件系统的，在外壳名字空间里的每一个对象(注)都实现了一个</span><span>IShellFolder</span></strong><span><strong>的接口，通过这个接口我们可以直接查询或间接得到其他相关的接口。<br>（注：这里的对象指的是外壳名字空间中的一个节点，对象有可能是一个文件夹，有可能是一个文件，也有可能是一个虚拟文件夹，例如：我的电脑，网上邻居，控制面板等）<br><br>在C#中，我们这样定义 IShellFolder 接口：<br><br></strong></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"><strong><img id=Code_Closed_Image_201358 style="DISPLAY: inline" onclick="this.style.display='none'; Code_Closed_Text_201358.style.display='none'; Code_Open_Image_201358.style.display='inline'; Code_Open_Text_201358.style.display='inline';" height=16 src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width=11 align=top><img id=Code_Open_Image_201358 style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_201358.style.display='none'; Code_Closed_Image_201358.style.display='inline'; Code_Closed_Text_201358.style.display='inline';" height=16 src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width=11 align=top><span id=Code_Closed_Text_201358 style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: inline; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">IShellFolder.cs</span></strong><span id=Code_Open_Text_201358 style="DISPLAY: none"><br><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">using</span></strong><strong><span style="COLOR: #000000">&nbsp;System;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span></strong><strong><span style="COLOR: #000000">&nbsp;System.Collections.Generic;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span></strong><strong><span style="COLOR: #000000">&nbsp;System.Text;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span></strong><strong><span style="COLOR: #000000">&nbsp;System.Runtime.InteropServices;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">namespace</span></strong><strong><span style="COLOR: #000000">&nbsp;WinShell<br><img id=Codehighlighter1_125_298_Open_Image onclick="this.style.display='none'; Codehighlighter1_125_298_Open_Text.style.display='none'; Codehighlighter1_125_298_Closed_Image.style.display='inline'; Codehighlighter1_125_298_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_125_298_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_125_298_Closed_Text.style.display='none'; Codehighlighter1_125_298_Open_Image.style.display='inline'; Codehighlighter1_125_298_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_125_298_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_125_298_Open_Text><strong><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;[ComImport]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;[Guid(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">000214E6-0000-0000-C000-000000000046</span><span style="COLOR: #000000">"</span></strong><strong><span style="COLOR: #000000">)]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">interface</span></strong><strong><span style="COLOR: #000000">&nbsp;IShellFolder<br><img id=Codehighlighter1_290_296_Open_Image onclick="this.style.display='none'; Codehighlighter1_290_296_Open_Text.style.display='none'; Codehighlighter1_290_296_Closed_Image.style.display='inline'; Codehighlighter1_290_296_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_290_296_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_290_296_Closed_Text.style.display='none'; Codehighlighter1_290_296_Open_Image.style.display='inline'; Codehighlighter1_290_296_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_290_296_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_290_296_Open_Text><span style="COLOR: #000000"><strong>{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</strong></span></span><span style="COLOR: #000000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</strong></span></span></span></div>
<br><strong>当然，这个接口还没有列出细节函数。我们要做的仅仅是从最基础开始。<br><br>首先我们必须了解，在外壳编程中，要使用 PIDL 路径代替普通路径（如果对 PIDL 不熟悉，请看</strong><a title=Windows外壳名字空间的浏览 href="http://blog.csdn.net/kingcom_xu/archive/2003/03/18/18943.aspx"><strong><font color=#1a8bc8>Windows外壳名字空间的浏览</font></strong></a><strong>）。<br><br>&#8220;桌面&#8221;是最顶级的文件夹，外壳名字空间中其他各项都可以用从&#8220;桌面&#8221;开始的 PIDL </strong><font lang=ZH-CN face=宋体><strong>加以表示。<br><br>如何获取&#8220;桌面&#8221;的 PIDL 和其 IShellFolder 接口呢，可以通过 API SHGetDesktopFolder：<br><br></strong>
<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"><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">[DllImport(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">shell32.dll</span><span style="COLOR: #000000">"</span></strong><strong><span style="COLOR: #000000">)]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&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">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;Int32&nbsp;SHGetDesktopFolder(</span><span style="COLOR: #0000ff">out</span></strong><strong><span style="COLOR: #000000">&nbsp;IntPtr&nbsp;ppshf);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_101_160_Open_Image onclick="this.style.display='none'; Codehighlighter1_101_160_Open_Text.style.display='none'; Codehighlighter1_101_160_Closed_Image.style.display='inline'; Codehighlighter1_101_160_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_101_160_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_101_160_Closed_Text.style.display='none'; Codehighlighter1_101_160_Open_Image.style.display='inline'; Codehighlighter1_101_160_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_101_160_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span></strong><span id=Codehighlighter1_101_160_Open_Text><strong><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></span><span style="COLOR: #808080"><strong>///</strong></span><strong><span style="COLOR: #008000">&nbsp;获得桌面&nbsp;Shell<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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"></span></strong></span><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&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">static</span><span style="COLOR: #000000">&nbsp;IShellFolder&nbsp;GetDesktopFolder(</span><span style="COLOR: #0000ff">out</span></strong><strong><span style="COLOR: #000000">&nbsp;IntPtr&nbsp;ppshf)<br><img id=Codehighlighter1_239_392_Open_Image onclick="this.style.display='none'; Codehighlighter1_239_392_Open_Text.style.display='none'; Codehighlighter1_239_392_Closed_Image.style.display='inline'; Codehighlighter1_239_392_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_239_392_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_239_392_Closed_Text.style.display='none'; Codehighlighter1_239_392_Open_Image.style.display='inline'; Codehighlighter1_239_392_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_239_392_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_239_392_Open_Text><strong><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SHGetDesktopFolder(</span><span style="COLOR: #0000ff">out</span></strong><strong><span style="COLOR: #000000">&nbsp;ppshf);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;Marshal.GetObjectForIUnknown(ppshf);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span></strong><span style="COLOR: #000000"><strong>&nbsp;(IShellFolder)obj;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</strong></span></span></div>
<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"><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获得桌面&nbsp;PIDL</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></strong></span><strong><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;desktopPtr;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IShellFolder&nbsp;desktop&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;API.GetDesktopFolder(</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;desktopPtr);</span></strong></div>
</font></span></font><br><font face=Verdana><strong>好的，我们取得&#8220;桌面&#8221;的 IShellFolder 接口，就已经成功了一半。现在我需要通过&#8220;桌面&#8221;，来获取&#8220;C:\&#8221;这个路径的 PIDL 和 </strong></font><strong><font face=宋体>IShellFolder 接口，可以通过 IShellFolder 的 ParseDisplayName 和 BindToObject 函数来实现：<br><br></strong>
<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"><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">void</span></strong><strong><span style="COLOR: #000000">&nbsp;ParseDisplayName(<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;hwnd,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;pbc,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[MarshalAs(UnmanagedType.LPWStr)]&nbsp;</span><span style="COLOR: #0000ff">string</span></strong><strong><span style="COLOR: #000000">&nbsp;pszDisplayName,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">uint</span></strong><strong><span style="COLOR: #000000">&nbsp;pchEaten,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">out</span></strong><strong><span style="COLOR: #000000">&nbsp;IntPtr&nbsp;ppidl,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">ref</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">uint</span></strong><strong><span style="COLOR: #000000">&nbsp;pdwAttributes);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span></strong><strong><span style="COLOR: #000000">&nbsp;BindToObject(<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;pidl,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;pbc,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[In()]&nbsp;</span><span style="COLOR: #0000ff">ref</span></strong><strong><span style="COLOR: #000000">&nbsp;Guid&nbsp;riid,<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;IShellFolder&nbsp;ppv);</span></strong></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"><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获取&nbsp;C&nbsp;盘的&nbsp;PIDL</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></strong></span><strong><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;FolderPath&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">@"</span><span style="COLOR: #000000">C:\</span><span style="COLOR: #000000">"</span></strong><strong><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;Pidl&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;IntPtr.Zero;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IShellFolder&nbsp;Root;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">uint</span><span style="COLOR: #000000">&nbsp;i,&nbsp;j&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span></strong><strong><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;desktop.ParseDisplayName(Handle,&nbsp;IntPtr.Zero,&nbsp;FolderPath,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;i,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;Pidl,&nbsp;</span><span style="COLOR: #0000ff">ref</span></strong><strong><span style="COLOR: #000000">&nbsp;j);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;desktop.BindToObject(Pidl,&nbsp;IntPtr.Zero,&nbsp;</span><span style="COLOR: #0000ff">ref</span><span style="COLOR: #000000">&nbsp;Guids.IID_IShellFolder,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;Root);</span></strong></div>
</font><br><strong><font face=Verdana>前提是你应该保证路径存在，因为我没有做任何出错控制。这样我们就获得了一个 Root，它表示C盘。通过这个Root，我们可以用 EnumObjects 来循环获取其子项（子文件和子文件夹）：<br><br></font></strong>
<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"><strong><font face=Verdana><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></font></strong><strong><span style="COLOR: #000000">[PreserveSig]<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;EnumObjects(IntPtr&nbsp;hWnd,&nbsp;SHCONTF&nbsp;flags,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;IntPtr&nbsp;enumIDList);</span></strong></div>
<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"><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">循环查找&nbsp;C&nbsp;盘下面的文件/文件夹的&nbsp;PIDL</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></strong></span><strong><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IEnumIDList&nbsp;fileEnum&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span></strong><strong><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IEnumIDList&nbsp;folderEnum&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span></strong><strong><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;fileEnumPtr&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;IntPtr.Zero;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;folderEnumPtr&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;IntPtr.Zero;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntPtr&nbsp;pidlSub;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span></strong><strong><span style="COLOR: #000000">&nbsp;celtFetched;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获取子文件夹</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></strong></span><strong><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(Root.EnumObjects(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Handle,&nbsp;SHCONTF.FOLDERS&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;SHCONTF.INCLUDEHIDDEN,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;fileEnumPtr)&nbsp;</span><span style="COLOR: #000000">==</span></strong><strong><span style="COLOR: #000000">&nbsp;API.S_OK)<br><img id=Codehighlighter1_412_789_Open_Image onclick="this.style.display='none'; Codehighlighter1_412_789_Open_Text.style.display='none'; Codehighlighter1_412_789_Closed_Image.style.display='inline'; Codehighlighter1_412_789_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_412_789_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_412_789_Closed_Text.style.display='none'; Codehighlighter1_412_789_Open_Image.style.display='inline'; Codehighlighter1_412_789_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_412_789_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_412_789_Open_Text><strong><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileEnum&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;(IEnumIDList)Marshal.GetObjectForIUnknown(fileEnumPtr);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(fileEnum.Next(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;pidlSub,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;celtFetched)&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: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;celtFetched&nbsp;</span><span style="COLOR: #000000">==</span></strong><strong><span style="COLOR: #000000">&nbsp;API.S_FALSE)<br><img id=Codehighlighter1_619_775_Open_Image onclick="this.style.display='none'; Codehighlighter1_619_775_Open_Text.style.display='none'; Codehighlighter1_619_775_Closed_Image.style.display='inline'; Codehighlighter1_619_775_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_619_775_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_619_775_Closed_Text.style.display='none'; Codehighlighter1_619_775_Open_Image.style.display='inline'; Codehighlighter1_619_775_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_619_775_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_619_775_Open_Text><strong><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获取显示名称</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top></strong></span><strong><span style="COLOR: #000000">&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">string</span><span style="COLOR: #000000">&nbsp;name&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;API.GetNameByPIDL(pidlSub);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lvFile.Items.Add(name,&nbsp;</span><span style="COLOR: #000000">1</span></strong><span style="COLOR: #000000"><strong>);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</strong></span></span><span style="COLOR: #000000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</strong></span></span><span style="COLOR: #000000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></span><strong><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获取子文件</span></strong><span style="COLOR: #008000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top></strong></span><strong><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(Root.EnumObjects(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Handle,&nbsp;SHCONTF.NONFOLDERS&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;SHCONTF.INCLUDEHIDDEN,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;folderEnumPtr)&nbsp;</span><span style="COLOR: #000000">==</span></strong><strong><span style="COLOR: #000000">&nbsp;API.S_OK)<br><img id=Codehighlighter1_946_1300_Open_Image onclick="this.style.display='none'; Codehighlighter1_946_1300_Open_Text.style.display='none'; Codehighlighter1_946_1300_Closed_Image.style.display='inline'; Codehighlighter1_946_1300_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_946_1300_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_946_1300_Closed_Text.style.display='none'; Codehighlighter1_946_1300_Open_Image.style.display='inline'; Codehighlighter1_946_1300_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_946_1300_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_946_1300_Open_Text><strong><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;folderEnum&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;(IEnumIDList)Marshal.GetObjectForIUnknown(folderEnumPtr);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(folderEnum.Next(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;pidlSub,&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;celtFetched)&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: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;celtFetched&nbsp;</span><span style="COLOR: #000000">==</span></strong><strong><span style="COLOR: #000000">&nbsp;API.S_FALSE)<br><img id=Codehighlighter1_1159_1286_Open_Image onclick="this.style.display='none'; Codehighlighter1_1159_1286_Open_Text.style.display='none'; Codehighlighter1_1159_1286_Closed_Image.style.display='inline'; Codehighlighter1_1159_1286_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1159_1286_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1159_1286_Closed_Text.style.display='none'; Codehighlighter1_1159_1286_Open_Image.style.display='inline'; Codehighlighter1_1159_1286_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1159_1286_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span></strong><span id=Codehighlighter1_1159_1286_Open_Text><strong><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&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">string</span><span style="COLOR: #000000">&nbsp;name&nbsp;</span><span style="COLOR: #000000">=</span></strong><strong><span style="COLOR: #000000">&nbsp;API.GetNameByPIDL(pidlSub);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lvFile.Items.Add(name,&nbsp;</span><span style="COLOR: #000000">0</span></strong><span style="COLOR: #000000"><strong>);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</strong></span></span><span style="COLOR: #000000"><br><strong><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</strong></span></span></div>
<br><strong>事实上，代码到此结束。然而我发现有太多的结构体和枚举没有介绍（以后会有更多），有兴趣的朋友可以自己查 MSDN ，否则就等待我下一节再介绍了。<br><br></strong>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/25843.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-04-18 01:08 <a href="http://www.cnitblog.com/seeyeah/archive/2007/04/18/25843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows外壳名字空间的浏览 From 姜伟华</title><link>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25842.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 17 Apr 2007 17:05:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/04/18/25842.html</guid><description><![CDATA[From : <a href="http://blog.csdn.net/kingcom_xu/archive/2003/03/18/18943.aspx">http://blog.csdn.net/kingcom_xu/archive/2003/03/18/18943.aspx</a>
<hr>
<p align=justify><br><br>Windows95/98<font lang=ZH-CN face=宋体>对</font>Dos/Win3.x<font lang=ZH-CN face=宋体>作了许多重大改进，在文件系统方面，它除了采用长文件名替代</font>Dos<font lang=ZH-CN face=宋体>中的</font>8.3<font lang=ZH-CN face=宋体>文件名以外，引入外壳名字空间（</font>Shell Name Space<font lang=ZH-CN face=宋体>）来代</font>Dos<font lang=ZH-CN face=宋体>文件系统是其又一大突破．本文将简要地介绍如何在</font>Windows 95/98<font lang=ZH-CN face=宋体>或</font>Windows NT4.0<font lang=ZH-CN face=宋体>以上版本。</p>
<ol>
    <li>概述 </li>
</ol>
<ol>
    <li><font color=#0000ff><strong>简介</strong></font>
    <p>　　在</font><font face="宋体, MS Song">Dos/Win3.x</font><font lang=ZH-CN face=宋体>中，每个逻辑分区构成一棵目录树，文件系统由这一统一的根，而且每个目录或文件必须一一对应于文件系统中客观存在的项。但</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>引入了&#8220;外壳名字空间&#8221;（</font><font face="宋体, MS Song"> Shell Name Space</font><font lang=ZH-CN face=宋体>）的概念之后，这一切就都变了。</p>
    <p align=justify>　外壳名字空间是</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>下的标准文件系统，它大大扩展了</font><font face="宋体, MS Song">Dos</font><font lang=ZH-CN face=宋体>文件系统，形成了以&#8220;桌面&#8221;（</font><font face="宋体, MS Song">Desktop</font><font lang=ZH-CN face=宋体>）为根的单一的文件系统树，原有的Ｃ盘、Ｄ盘等目录树变成了&#8220;我的电脑&#8221;这一外壳名字空间子树的下一级子树，而像&#8220;控制面板&#8221;、&#8220;回收站&#8221;、&#8220;网上邻居&#8221;等应用程序及&#8220;打印机&#8221;等设备也被虚拟成了外壳名字空间中的节点。另外，与ＤＯＳ中物理存储只能和文件系统项一一对应这一点不同的是，一个实际目录在外壳名字空间中可以表现为不同的项。例如&#8220;我的文档&#8221;与&#8220;</font><font face="宋体, MS Song">C;\My Documents&#8221;</font><font lang=ZH-CN face=宋体>其实都指向&#8220;</font><font face="宋体, MS Song">C;\My Documents</font><font lang=ZH-CN face=宋体>&#8221;目录，但它们在外壳名字空间中是不同的项。如果我们运行</font><font face="宋体, MS Song">Windows </font><font lang=ZH-CN face=宋体>自带的&#8220;</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>资源管理器&#8221;看一下的话，那么在它的左部树型视图中我们就可以清楚的看到整个外壳名字空间替代ＤＯＳ文件系统，</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>在文件系统的组织与管理上终于有了质的飞跃。</p>
    <p align=justify>　　为了区别于ＤＯＳ中&#8220;目录&#8221;的概念，</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>引入了&#8220;文件夹&#8221;（</font><font face="宋体, MS Song">Folder</font><font lang=ZH-CN face=宋体>）的概念。&#8220;文件夹&#8221;一般是指外壳名字空间树中的非叶节点，既可以是ＤＯＳ下的目录，也可是&#8220;控制面板&#8221;、&#8220;回收站&#8221;这类虚拟的目录。但外壳名字空间中有些项本身并不是文件夹（即不具有文件夹属性），但却含有子文件夹，比如&#8220;网上邻居&#8221;等。以下为讲座方便，我们也认为它们是文件夹。</p>
    <p align=justify>　　在下面的讲座过程中我们将用&#8220;文件系统&#8221;一词来指代ＤＯＳ文件系统，而用&#8220;外壳名字空间&#8221;一词来指代</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>中的外壳名字空间：另外用&#8220;文件&#8221;一词来指代外壳名字空间这棵树中的叶节点（虽然它们不都是物理存储上的文件）。</p>
    <p align=justify>　　在</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>中，</font><font face="宋体, MS Song">Win3.x</font><font lang=ZH-CN face=宋体>的文件操作函数，如</font><font face="宋体, MS Song">FindFirstFile</font><font lang=ZH-CN face=宋体>、</font><font face="宋体, MS Song">FindNextFile</font><font lang=ZH-CN face=宋体>、</font><font face="宋体, MS Song">SetCurrentDirectory</font><font lang=ZH-CN face=宋体>等，虽然仍可使用，但用它们只能浏览文件系统，却无法浏览与操纵整个外壳名字空间。要浏览</font><font face="宋体, MS Song">Windows</font><font lang=ZH-CN face=宋体>中的外壳名字空间，就必须使用一套全新的、基于ＣＯＭ（组件对象模型）基础上的方法。</p>
    <li><strong><font color=#0000ff>新的&#8220;路径&#8221;</font></strong><strong><font color=#0000ff>PIDL</font></strong>
    <p align=justify>　在讨论基于　COM<font lang=ZH-CN face=宋体>的方法之前，我们先来介绍一下外壳名字空间中&#8220;路径&#8221;的表示问题。</font>DOS<font lang=ZH-CN face=宋体>的字符串路径只能表示文件系统，而无法表示整个外壳名字空间，所以外壳名字空间提供了一种&#8220;路径&#8221;的替代物椩乇晔斗斜恚虺莆?/FONT&gt;PIDL）。</p>
    <p align=justify>　　PIDL<font lang=ZH-CN face=宋体>是一个元素类型为</font>ITEMIDLIST<font lang=ZH-CN face=宋体>结构的数组，数组中元素的个数是未知的，但紧接着数组末尾的必是一个双字节的零。每个数组元素代表了外壳名字空间树中的一层（即一个文件夹或文件），数组中的前一元素代表的是后一元素的父文件夹。由此可见，</font>PIDL<font lang=ZH-CN face=宋体>实际上就是指向一块由若干个顺序排列的</font>ITEMIDLIST<font lang=ZH-CN face=宋体>结构组成、并在最后有一个双字节零的空间的指针。所以</font>PIDL<font lang=ZH-CN face=宋体>的类型就被</font>Windows<font lang=ZH-CN face=宋体>定义为</font>ITEMIDLIST<font lang=ZH-CN face=宋体>结构的指针。</p>
    <p align=justify>　　</font>PIDL<font lang=ZH-CN face=宋体>亦有&#8220;绝对路径&#8221;与&#8220;相对路径&#8221;的概念。表示&#8220;相对路径&#8221;的</font>PIDL<font lang=ZH-CN face=宋体>（本文简称为&#8220;相对</font>PIDL<font lang=ZH-CN face=宋体>&#8221;）只有一个</font>ITEMIDLIST<font lang=ZH-CN face=宋体>结构的元素，用于标识相对于父文件夹的&#8220;路径&#8221;；表示&#8220;绝对路径&#8221;的</font>PIDL<font lang=ZH-CN face=宋体>（简称为&#8220;绝对</font>PIDL<font lang=ZH-CN face=宋体>&#8221;）有若干个</font>ITEMIDLIST<font lang=ZH-CN face=宋体>结构的元素，第一个元素表示外壳名字空间根文件夹（&#8220;桌面&#8221;）下的某一子文件夹</font>A<font lang=ZH-CN face=宋体>，第二个元素则表示文件夹</font>A<font lang=ZH-CN face=宋体>下的某一子文件夹</font>B<font lang=ZH-CN face=宋体>，其余依此类推。这样绝对</font>PIDL<font lang=ZH-CN face=宋体>就通过保存一条从&#8220;桌面&#8221;下的直接子文件夹或文件的绝对</font>PIDL<font lang=ZH-CN face=宋体>与相对</font>PIDL<font lang=ZH-CN face=宋体>是相同的，而其他的文件夹或文件的相对</font>PIDL<font lang=ZH-CN face=宋体>就只是其绝对</font>PIDL<font lang=ZH-CN face=宋体>的最后一部分了。</p>
    <p align=justify>　　但现在就出现了一个问题：即&#8220;桌面&#8221;的表示问题。外壳名字空间中其他各项都可以用从&#8220;桌面&#8221;开始的绝对</font>PIDL<font lang=ZH-CN face=宋体>加以表示，但&#8220;桌面&#8221;的</font>PIDL<font lang=ZH-CN face=宋体>数组显然一个元素都没有。这样就只剩下</font>PIDL<font lang=ZH-CN face=宋体>数组最后的那个双字节的零了。所以，&#8220;桌面&#8221;的</font>PIDL<font lang=ZH-CN face=宋体>就是一个</font>16<font lang=ZH-CN face=宋体>位的零。注意：&#8220;桌面&#8221;内容是一个双字节的零。另外，虽然&#8220;桌面&#8221;表示的是&#8220;</font>C:\ Windows \Desktop&#8221;<font lang=ZH-CN face=宋体>文件夹（这里假定</font>Windows<font lang=ZH-CN face=宋体>的系统目录为&#8220;</font>C:\ Windows<font lang=ZH-CN face=宋体>&#8221;）的内容，但&#8220;桌面&#8221;与&#8220;</font>C:\ Windows \Desktop<font lang=ZH-CN face=宋体>&#8221;文件夹的</font>PIDL<font lang=ZH-CN face=宋体>是完全不同的。这一点同样适用于&#8220;我的文档&#8221;与&#8220;</font>C:\ My Documents<font lang=ZH-CN face=宋体>&#8221;等文件夹。</p>
    <p align=justify>　　</font>DOS<font lang=ZH-CN face=宋体>中的路径是一个字符串，但</font>PIDL<font lang=ZH-CN face=宋体>是一种二进制结构，所以我们不能直接从</font>PIDL<font lang=ZH-CN face=宋体>中获知它所代表的到底是哪个文件夹或文件，而必须调用相应的函数把它转换成代表路径的字符串。如果某绝对</font>PIDL<font lang=ZH-CN face=宋体>是文件系统的一部分，则调用</font>SHGetPathFromIDList<font lang=ZH-CN face=宋体>函数即可；但如不是，就无法获得路径字符串了，因为</font>DOS<font lang=ZH-CN face=宋体>中根本就不存在这种路径。但很可惜的是，</font>Windows<font lang=ZH-CN face=宋体>并没有提供一个函数来让我们方便地把文件系统的路径字符串转换成</font>PIDL<font lang=ZH-CN face=宋体>。不过我们可用一个我们自己实现的函数</font>ParsePidlFromPath<font lang=ZH-CN face=宋体>（）来达目的（具体函数的实现见下文）。</p>
    <p align=justify>　　</font>PIDL<font lang=ZH-CN face=宋体>的创建与释放一般并不使用</font>C++<font lang=ZH-CN face=宋体>的</font>new<font lang=ZH-CN face=宋体>和</font>delete<font lang=ZH-CN face=宋体>操作或</font>C<font lang=ZH-CN face=宋体>语言的</font>malloc<font lang=ZH-CN face=宋体>和</font>free<font lang=ZH-CN face=宋体>函数</font>,<font lang=ZH-CN face=宋体>而必须使用专门的方法进行</font>.<font lang=ZH-CN face=宋体>首先调用</font>SHGEetMallocI<font lang=ZH-CN face=宋体>函数得到</font>Malloc<font lang=ZH-CN face=宋体>接口</font>(COM<font lang=ZH-CN face=宋体>接口的一种</font>,<font lang=ZH-CN face=宋体>关于</font>COM<font lang=ZH-CN face=宋体>接口下面将详述</font>)<font lang=ZH-CN face=宋体>的指针</font>,<font lang=ZH-CN face=宋体>再调用该接口的</font>Alloc<font lang=ZH-CN face=宋体>方法为</font>PIDL<font lang=ZH-CN face=宋体>分配空间</font>,<font lang=ZH-CN face=宋体>或调用该接口的</font>Free<font lang=ZH-CN face=宋体>方法释放某个</font>PIDL<font lang=ZH-CN face=宋体>占用的空间。最后调用该接口的</font>Release<font lang=ZH-CN face=宋体>方法释放该接口。</font></p>
    <font lang=ZH-CN face=宋体>
    <p align=justify>　除了下面将要介绍的</font>IShellFolder<font lang=ZH-CN face=宋体>、</font>IEnumIDList<font lang=ZH-CN face=宋体>等</font>COM<font lang=ZH-CN face=宋体>接口可以操作</font>PIDL<font lang=ZH-CN face=宋体>外，还有很多以</font>SH<font lang=ZH-CN face=宋体>开头的</font>Windows API<font lang=ZH-CN face=宋体>函数也可操作</font>PIDL<font lang=ZH-CN face=宋体>，不过一般这些函数都要求使用绝对</font>PIDL<font lang=ZH-CN face=宋体>作参数。例如</font>SHGetFileInfo<font lang=ZH-CN face=宋体>函数可得到某一</font>PIDL<font lang=ZH-CN face=宋体>所指对象的各种信息，包括名字、图标、属性等；</font>SHFileOperation<font lang=ZH-CN face=宋体>函数可对外壳名字空间中的项进行拷贝、移动、改名、删除等操作；</font>SHBrowseForFolder<font lang=ZH-CN face=宋体>可以显示一个让用户选择外壳名字空间中某一文件夹的浏览对话框</font>.</p>
    <font lang=ZH-CN face=宋体>
    <li><strong><font color=#0000ff>基于</font></strong></font><strong>COM</strong><font lang=ZH-CN face=宋体><strong><font color=#0000ff>的方法</font></strong> </li>
</ol>
<p align=justify>　　讨论清楚了</font>PIDL<font lang=ZH-CN face=宋体>的概念之后</font>,<font lang=ZH-CN face=宋体>我们回过头来讨论基于</font>COM<font lang=ZH-CN face=宋体>之上的浏览外壳名字空间的方法。如果说</font>PIDL<font lang=ZH-CN face=宋体>是外壳的名字空间中的&#8220;路径&#8221;的话，那么下面所说的两个</font>COM<font lang=ZH-CN face=宋体>接口</font>IshellFolder<font lang=ZH-CN face=宋体>与</font>IEnumIDList<font lang=ZH-CN face=宋体>就起着与</font>Win 3.x<font lang=ZH-CN face=宋体>中的</font>FindFirstFile<font lang=ZH-CN face=宋体>、</font>FindNextFile<font lang=ZH-CN face=宋体>等函数类似的功能。</p>
<p align=justify>　　在</font>Windows<font lang=ZH-CN face=宋体>中，每个文件夹都由操作系统实现了一个派生自</font>Iunknown<font lang=ZH-CN face=宋体>接口（</font>COM<font lang=ZH-CN face=宋体>接口的最基本类）的接口</font>IshellFolder<font lang=ZH-CN face=宋体>。通过调用某个文件夹的该接口，即可实现对该文件夹的浏览，得到该文件夹中子项（子文件夹或文件）的各种相关信息。</p>
<p align=justify>　　我们可以调用</font>SHGetDesktopFolder<font lang=ZH-CN face=宋体>函数来获得外壳名字空间的根文件夹（即&#8220;桌面&#8221;）的</font>IshellFolder<font lang=ZH-CN face=宋体>接口。对于某个文件夹</font>A<font lang=ZH-CN face=宋体>，以它的子文件夹</font>B<font lang=ZH-CN face=宋体>的相对</font>PIDL<font lang=ZH-CN face=宋体>为参数，调用它的</font>IshellFolder<font lang=ZH-CN face=宋体>接口的</font>BindToObject<font lang=ZH-CN face=宋体>方法即可得到子文件夹</font>B<font lang=ZH-CN face=宋体>的</font>IshellFolder<font lang=ZH-CN face=宋体>接口。如要枚举某个文件夹下的子项，则只需调用它的</font>IshellFolder<font lang=ZH-CN face=宋体>接口的</font>EnumObjects<font lang=ZH-CN face=宋体>方法即可获得一个</font>IEnumIDList<font lang=ZH-CN face=宋体>接口。通过调用该</font>IEnumIDList<font lang=ZH-CN face=宋体>接口的</font>Next<font lang=ZH-CN face=宋体>方法我们即可枚举出该文件夹的所有子项（包括文件夹和文件等对象），获得它们的相对</font>PIDL<font lang=ZH-CN face=宋体>。使用父文件夹的</font>IshellFolder<font lang=ZH-CN face=宋体>接口和这些相对</font>PIDL<font lang=ZH-CN face=宋体>，我们即可获得这些子项的各种相关信息，包括显示名称、图标、属性等，甚至还可以获得它的右键菜单。例如，调用该接口的</font>GetDisplayNameOf<font lang=ZH-CN face=宋体>方法可获得该文件夹下子项的显示名称；调用</font>ParseDisplayName<font lang=ZH-CN face=宋体>方法可把某个子项的用</font>Unicode<font lang=ZH-CN face=宋体>内码表示的字符串路径翻译成对应的</font>PIDL<font lang=ZH-CN face=宋体>。这样通过</font>PIDL<font lang=ZH-CN face=宋体>和这两个接口，我们就可以遍历和操纵整个外壳名字空间了。</p>
<p align=justify>　　除了</font>IshellFolder<font lang=ZH-CN face=宋体>和</font>IEnumIDList<font lang=ZH-CN face=宋体>接口以外，</font>Windows <font lang=ZH-CN face=宋体>外壳名字空间还提供了很多其他</font>COM<font lang=ZH-CN face=宋体>接口，例如</font>IshellBrowser<font lang=ZH-CN face=宋体>、</font>IshellLink<font lang=ZH-CN face=宋体>、</font>IshellIcom<font lang=ZH-CN face=宋体>、</font>IshellView<font lang=ZH-CN face=宋体>等。通过这些接口，应用于程序就可以更好的与外壳名字空间交互。由于本文篇幅有限，这些接口就不详细介绍了，有兴趣的读者可参阅相关资料。</p>
<p align=justify>　　值得注意的是，</font>COM<font lang=ZH-CN face=宋体>中的接口虽然在使用上与</font>C++<font lang=ZH-CN face=宋体>中的类是非常相似（事实上</font>COM<font lang=ZH-CN face=宋体>接口在</font>C ++<font lang=ZH-CN face=宋体>中就是以类的形式声明的），但维护其正确的引用计数机制是非常重要的。每增加一个对该接口的引用，就要调用一次它的</font>AddRef( )<font lang=ZH-CN face=宋体>方法；而在使用完后必须调用它的</font>Release( )<font lang=ZH-CN face=宋体>方法释放该接口。关于</font>COM<font lang=ZH-CN face=宋体>及</font>COM<font lang=ZH-CN face=宋体>接口的细节请参见相关资料，这里不再赘述。</p>
<p align=justify>　　可惜的是，虽然我们可依照上文给出的方法实现外壳名字空间的逐层展开，但外壳名字空间却并没有提供一种让我们自由跳转到某一文件夹的方法，也没有提供返回到上一级文件夹的方法，因为我们无法方便地获得父文件夹的</font>IshellFolder<font lang=ZH-CN face=宋体>接口。如果要返回，就必须由应用程序自己想方法获得父文件夹的</font>IshellFolder<font lang=ZH-CN face=宋体>接口。一种可行的方法是在展开外壳名字空间时保存每个文件夹的</font>IShellFolder<font lang=ZH-CN face=宋体>接口指针和它的绝对</font>PIDL<font lang=ZH-CN face=宋体>，这样就可以相对容易地实现自由跳转了。</p>
<p align=justify>　　但无论如何，外壳名字空间提供的浏览和操作的方法比起</font>DOS/ Windows 3.x<font lang=ZH-CN face=宋体>的函数来还是有着巨大的飞跃的。只要我们理解清楚了这种方法的优点与不足，我们就可以扬长避短，开发出各种各样的使用外壳名字空间的程序来。</p>
<ol>
    <li>相关接口、函数和数据结构 </li>
</ol>
<p align=justify>　　对于本文所涉及的一些比较复杂的接口、函数和数据结构，以下仅列举出作者在</font>Visual C++6.0<font lang=ZH-CN face=宋体>查到的声明与定义</font>,<font lang=ZH-CN face=宋体>并配上相应的注释</font>.<font lang=ZH-CN face=宋体>一些较简单的则从略</font>,<font lang=ZH-CN face=宋体>未列出的请参见相关资料。</p>
<ol>
    <li>数据结构 </li>
</ol>
</font>
<p align=justify>typedf IshellFolder*LPSHELLFOLDER;</p>
<p align=justify>//IshellFolder<font lang=ZH-CN face=宋体>接口指针的声明</p>
</font>
<p align=justify>typedef struct _ITEMIDLIST{//ITEMIDLIST<font lang=ZH-CN face=宋体>结构的定义</p>
</font>
<p align=justify>SHITEMID mkid;</p>
<p align=justify>}ITEMIDLIST, * LPITEMIDLIST;</p>
<p align=justify>typedef struct _SHITEMID{//ITEMIDLIST<font lang=ZH-CN face=宋体>结构中元素的定义</p>
</font>
<p align=justify>USHORT cb;//<font lang=ZH-CN face=宋体>本结构的长度</font>(<font lang=ZH-CN face=宋体>以字节计</font>)</p>
<p align=justify>BYTE abID[1];//<font lang=ZH-CN face=宋体>可变长的元素标识符</p>
<p align=justify>}</font>SHITEMID, *LPSHITEMID;</p>
<p align=justify>typedef struct _SHFILEINFO{//SFFILEINFO<font lang=ZH-CN face=宋体>结构的定义</p>
</font>
<p align=justify>HICON hicon;//<font lang=ZH-CN face=宋体>文件图标的句柄</p>
</font>
<p align=justify>Int ilcon;//<font lang=ZH-CN face=宋体>图标在系统图像列表中的序号</p>
</font>
<p align=justify>DWORD dwAttributes;//<font lang=ZH-CN face=宋体>文件的属性</p>
</font>
<p align=justify>Char szDisplayName [MAX_PATH];//<font lang=ZH-CN face=宋体>显示名称或路径</p>
</font>
<p align=justify>Char szTypeName[80];//<font lang=ZH-CN face=宋体>表示文件类型的字符串</p>
<p align=justify>}</font> SHFILEINFO;</p>
<p align=justify>2.<font lang=ZH-CN face=宋体>相关接口</p>
</font>
<p align=justify>2.1 IshellFolder<font lang=ZH-CN face=宋体>接口的方法</p>
<ol></font>
    <li>BindToObject <font lang=ZH-CN face=宋体>
    <p align=justify>格式</font>:HRESULT BindToObject( LPCITEMIDLLIST pidl, LPBC pbcreserved, REFIID riid, LPVOID *ppvOut);</p>
    <font lang=ZH-CN face=宋体>
    <p align=justify>作用：得到本文件夹中某一子文件夹的</font>IShellFolder<font lang=ZH-CN face=宋体>接口。</p>
    <p align=justify>参数：</font>Riid<font lang=ZH-CN face=宋体>应为</font>IID_IshellFolder, pbcReserved<font lang=ZH-CN face=宋体>应为</font>NNUL,pidl<font lang=ZH-CN face=宋体>为表示该子文件夹的&#8220;相对路径&#8221;的</font>PIDL,<font lang=ZH-CN face=宋体>从</font>ppvOut<font lang=ZH-CN face=宋体>中返回要求的</font>IshellFolder<font lang=ZH-CN face=宋体>接口的指针。</p>
    </font>
    <li>EnumObjects </li>
</ol>
<blockquote><font lang=ZH-CN face=宋体>
<p align=justify>格式：</font>HRSULT EnumObjects( HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST*ppenumIDList);</p>
<font lang=ZH-CN face=宋体>
<p align=justify>作用：枚举本文件夹的成员。</p>
<p align=justify>参数：</font>hwndOwmer<font lang=ZH-CN face=宋体>为父窗口句柄，</font>grfFlags<font lang=ZH-CN face=宋体>决定枚举世闻名的内容，可为</font>SHCONTF_FOLDERS<font lang=ZH-CN face=宋体>、</font>SHCONTF_NONFOLDERS<font lang=ZH-CN face=宋体>、</font>SHCONTF_INCLUDEHIDDEN<font lang=ZH-CN face=宋体>的组合</font>,<font lang=ZH-CN face=宋体>从</font>ppenumIDList<font lang=ZH-CN face=宋体>返回</font>IEnumIDList<font lang=ZH-CN face=宋体>接口的指针。</p>
<p align=justify>（</font>3<font lang=ZH-CN face=宋体>）</font>GetDisplayNameOf</p>
<font lang=ZH-CN face=宋体>
<p align=justify>格式：</font>HRESULT GetDisplayNameOf (LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRERT lpName);</p>
<font lang=ZH-CN face=宋体>
<p align=justify>作用：得到本文件夹中某一对象的显示名称。</p>
<p align=justify>参数：</font>pidl<font lang=ZH-CN face=宋体>为表示该子文件夹的&#8220;相对路径&#8221;的</font>PIDL, uFlags<font lang=ZH-CN face=宋体>为</font> SHGDN_NORMAL<font lang=ZH-CN face=宋体>、</font>SHGDN_INFOLDER<font lang=ZH-CN face=宋体>、</font>SHGFI_SYSICONINDEX<font lang=ZH-CN face=宋体>、</font>SHGFI_EXETYPE<font lang=ZH-CN face=宋体>、</font>SHGFI_ATTRIBUTES<font lang=ZH-CN face=宋体>、</font>SHGFI_PIDL<font lang=ZH-CN face=宋体>、</font>SHGFI_DISPLAYNAME<font lang=ZH-CN face=宋体>、</font>SHGFI_LARGEICON<font lang=ZH-CN face=宋体>等。</p>
</font>
<p align=justify><font lang=ZH-CN face=宋体>返回值：如</font>uFlags<font lang=ZH-CN face=宋体>包含</font>SHGFI-EXETYPE<font lang=ZH-CN face=宋体>标志，则返回值为该可执行文件夹类型；如</font>uFlags<font lang=ZH-CN face=宋体>包含</font>SHGFI_SYSICONINDEX<font lang=ZH-CN face=宋体>标志</font>,<font lang=ZH-CN face=宋体>则返回值为系统图像列表的句柄。否则</font>,<font lang=ZH-CN face=宋体>如本函数调用成功则返回非零值，失败则返回零。</p>
</blockquote>
<ol>
    <li>应用举例 </li>
</ol>
<ol>
    <li>几个非常有用的函数的实现 </li>
</ol>
</font>
<p align=justify>1<font lang=ZH-CN face=宋体>．</font>1ParsePidlFromPath</p>
<font lang=ZH-CN face=宋体>
<p align=justify>描述：将文件系统路径翻译成对应的</font>PIDL<font lang=ZH-CN face=宋体>。</font>LPITEMIDLIST ParsePidlFromPath(LPCSTR path)</p>
<p align=justify>{</p>
<p align=justify>//<font lang=ZH-CN face=宋体>存放以</font>Unicode<font lang=ZH-CN face=宋体>内码表示的路径字符串的缓冲区</p>
</font>
<p align=justify>OLECHAR szOleChar[MAX_PATH];</p>
<p align=justify>//&#8220;<font lang=ZH-CN face=宋体>桌面&#8220;的</font>IshellFolder<font lang=ZH-CN face=宋体>接口指针</p>
</font>
<p align=justify>LPSHELLFOLDER IpsfDeskTop;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>返回的</font>PIDL</p>
<p align=justify>LPITEMIDLIST Ipifq;</p>
<p align=justify>ULONG ulEaten, ulAttribs;</p>
<p align=justify>HRESULT hres;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>得到&#8220;桌面&#8221;的</font>IshellFolderr <font lang=ZH-CN face=宋体>接口指针</p>
</font>
<p align=justify>SHGetDesktopFolder(&amp;lpsfDeskTop);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>将</font>Ansi<font lang=ZH-CN face=宋体>字符集的路径字符串转换成</font>Unicode<font lang=ZH-CN face=宋体>字符串，</p>
<p align=justify>存入</font>szOleChar</p>
<p align=justify>MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,</p>
<p align=justify>Path,-1,szOleChar,sizeof(szOleChar));</p>
<p align=justify>//<font lang=ZH-CN face=宋体>将</font>szOleChar,<font lang=ZH-CN face=宋体>中的路径径字符串翻译成相应的</font>PIDL<font lang=ZH-CN face=宋体>，存入</font>lpifq</p>
<p align=justify>hres=lpsfDeskTop-&gt;Release( );</p>
<p align=justify>//<font lang=ZH-CN face=宋体>如果翻译失败，则返回</font>NULL</p>
<p align=justify>if(FAILED(hres))return NULL;</p>
<p align=justify>return lpifq;</p>
<p align=justify>1.2 GetItemIcon</p>
<font lang=ZH-CN face=宋体>
<p align=justify>描述：返回</font>lpi<font lang=ZH-CN face=宋体>这个绝对</font>PIDL<font lang=ZH-CN face=宋体>所指项的图标在系统图像列表中的序号，</font>uFlags<font lang=ZH-CN face=宋体>为要求的图标类型。</p>
</font>
<p align=justify>Int Getltemlcon(LPITEMIDLIST lpi, UINT uFlags)</p>
<p align=justify>{</p>
<p align=justify>//<font lang=ZH-CN face=宋体>存放文件信息的结构</p>
</font>
<p align=justify>SHFILEINFO sfi;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>给</font>uFlags<font lang=ZH-CN face=宋体>增加一些公共标志（</font>lpi<font lang=ZH-CN face=宋体>为</font>PIDL<font lang=ZH-CN face=宋体>、要求返回系统图像列表、要求小图标）</p>
</font>
<p align=justify>uFlags|=SHGFI-PIDL |SHGFI_SYSICONINDEX |SHGFI_SMALLICON;</p>
<font lang=ZH-CN face=宋体>
<p align=justify>获得图标</p>
</font>
<p align=justify>SHGetFileinfo( (LPCSTR) lpi, 0, &amp; sfi , sizeof(SHFILEINFO),uFlags);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>返回图标在系统图像列表中的序号</p>
</font>
<p align=justify>return sfi,ilcon;</p>
<p align=justify>}</p>
<p align=justify>1.3 GetName</p>
<font lang=ZH-CN face=宋体>
<p align=justify>描述：</font>lpio lpsf<font lang=ZH-CN face=宋体>所指的</font>IshellFolder<font lang=ZH-CN face=宋体>接口代表的文件夹下的相对</font>PIDL<font lang=ZH-CN face=宋体>，本函数获得</font>lpi<font lang=ZH-CN face=宋体>所指项的显示名称，</font>dwFlags<font lang=ZH-CN face=宋体>表明欲得到的显示名称类型，</font>lpFriendlyName<font lang=ZH-CN face=宋体>为存放显示名称的缓冲区。</p>
</font>
<p align=justify>BOOL GetName(LPSHELLFOLDER lpsf,LPITEMIDLIST lpi,DWORD dwFlags,LPSTR lpFriendlyName)</p>
<p align=justify>{</p>
<p align=justify>STRRET str;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>得到显示名称</p>
</font>
<p align=justify>if(NOERROR!=lpsf-&gt;GetDisplayNameOf()lpi,dwFlags,&amp;str))</p>
<p align=justify>return FALSE;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>根据返回值进行转换</p>
</font>
<p align=justify>switch(str uType)</p>
<p align=justify>{</p>
<p align=justify>//<font lang=ZH-CN face=宋体>如为</font>Unicode<font lang=ZH-CN face=宋体>字符串，则转成</font>Ansi<font lang=ZH-CN face=宋体>字符集的字符串</font>case STRRET_WSTR:</p>
<p align=justify>WideCharToMultiByte(CP_ACP,0,str.pOleStr,-1,ipFriendlyName,sizeof(lpFriendlyName),NULL,NULL);</p>
<p align=justify>Break;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>如为偏移量，则去除偏移量</p>
</font>
<p align=justify>case STRRET_OFFSET:</p>
<p align=justify>lstrcpy(lpFriendlyName,(LPSTR)lpi+str.uOffset);</p>
<p align=justify>break;</p>
<font lang=ZH-CN face=宋体>
<p align=justify>如为</font>Ansi<font lang=ZH-CN face=宋体>字符串，则直接拷贝</p>
</font>
<p align=justify>case STRRET_CSTR:</p>
<p align=justify>Lstrcpy(lpFriendlyName,(LPSTR)str.cStr);</p>
<p align=justify>Break;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>非法情况</p>
</font>
<p align=justify>default:</p>
<p align=justify>return FALSE;</p>
<p align=justify>}</p>
<p align=justify>return TRUE;</p>
<ol><font lang=ZH-CN face=宋体>
    <li>一个实例 </li>
</ol>
<blockquote>
<p align=justify>以下我们将用</font>Visual C++6.0<font lang=ZH-CN face=宋体>制作一个例子来演示外壳名了空间的浏览。具体为使用</font>Ctreer View,<font lang=ZH-CN face=宋体>展开外壳名字空间中的&#8220;桌面&#8221;文件夹，枚举出该文件夹下的所有子文件夹。</p>
<p align=justify>在这个项目中，</font>CtreeView <font lang=ZH-CN face=宋体>的图像列表我们使用</font>Windows <font lang=ZH-CN face=宋体>的系统图像列表，而不是自己创建一个。</p>
<p align=justify>首先，用</font>AppWizard<font lang=ZH-CN face=宋体>新建一个项目，类型为</font>MFC AppWizard(exe),<font lang=ZH-CN face=宋体>项目名为</font>Test<font lang=ZH-CN face=宋体>；在第一步中选择</font>Single document;<font lang=ZH-CN face=宋体>在第六步中将</font>CtestView<font lang=ZH-CN face=宋体>的基类改为</font>CtreeView<font lang=ZH-CN face=宋体>。其它均使用默认设置。</p>
</font>
<p align=justify><font lang=ZH-CN face=宋体>其次，在</font>CtestView<font lang=ZH-CN face=宋体>中加一个私有成员变量</font>m_ImageList,<font lang=ZH-CN face=宋体>类型为</font>CimageList,<font lang=ZH-CN face=宋体>用于保存系统列表。（</font>Windows<font lang=ZH-CN face=宋体>中所有的图标都保存在系统图像列表中，我们可以在程序中得到这个图像列表）。</p>
</font>
<p align=justify><font lang=ZH-CN face=宋体>第三步，将上文提到的</font>GetName <font lang=ZH-CN face=宋体>和</font>GetItemIcon <font lang=ZH-CN face=宋体>这两个函数的实现拷贝到</font>CtestView.cpp<font lang=ZH-CN face=宋体>的较开头的位置。</p>
</font>
<p align=justify><font lang=ZH-CN face=宋体>第四步，在</font>CtestView<font lang=ZH-CN face=宋体>的</font>OnInitialUpdate( )<font lang=ZH-CN face=宋体>函数中加入以下代码：</p>
</font>
<p align=justify>//<font lang=ZH-CN face=宋体>系统图像列表的句柄</p>
</font>
<p align=justify>HIMAGELIST himlSmall;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>存放文件信息的结构</p>
</font>
<p align=justify>SHFILEINFO sfi;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>存放树型控件中的节点的信息</p>
</font>
<p align=justify>TV_INEM tvi;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>向树型控件中插入节点时使用的结构</p>
</font>
<p align=justify>TV_INSERTSTRUCT tvis;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>欲插入节点的前一节点的句柄</p>
</font>
<p align=justify>HTREEITEM hParent=TVI_FIRST;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>欲节点的父节点的句柄</p>
</font>
<p align=justify>HTREEITEM hParent=TV_ROOT;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>某一文件夹的</font>IshellFolder<font lang=ZH-CN face=宋体>接口指针</p>
</font>
<p align=justify>LPSHELLFOLDER lpsf=0;</p>
<p align=justify>//IenumiDList<font lang=ZH-CN face=宋体>接口的指针</p>
</font>
<p align=justify>LPENUMIDLIST lpe=0;</p>
<p align=justify>//lpi<font lang=ZH-CN face=宋体>为一</font>PIDL</p>
<p align=justify>LPITEMIDLIST lpi=0;</p>
<p align=justify>//IMalloc<font lang=ZH-CN face=宋体>接口的指针</p>
</font>
<p align=justify>LPMALLOC lpMalloc=0;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>枚举的个数</p>
</font>
<p align=justify>ULONG ulFetched;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>存放显示名称的缓冲区</p>
</font>
<p align=justify>char szBuff[MAX_PATH];</p>
<p align=justify>//<font lang=ZH-CN face=宋体>获得系统图像列表，并把它赋给</font>CtestView<font lang=ZH-CN face=宋体>的</font>CtreeCtrl<font lang=ZH-CN face=宋体>控件</p>
</font>
<p align=justify>himlsmall=(HIMAGELIST)SHGetFileinfo(&#8220;C:\\&#8221;,0,&amp;</p>
<p align=justify>sfi, sizeof(SHFIEINFO), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);</p>
<p align=justify>m_lmageList.Attach(himlsmall);</p>
<p align=justify>GetTreeCtrl().SetlmageList(&amp;m_imageList,TVSIL_NORMAL);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>获得</font>Imalloc<font lang=ZH-CN face=宋体>接口的指针</p>
</font>
<p align=justify>SHGetMalloc(&amp;lpMalloc);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>获得&#8220;桌面&#8221;文件夹的</font>IshellFolder<font lang=ZH-CN face=宋体>接口指针</p>
</font>
<p align=justify>SHGetDesktopFloder(&amp;lpsf);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>创建一个&#8220;桌面&#8221;的绝对</font>PIDL</p>
<p align=justify>lpi=(LPITEMIDLIST)lpMalloc-&gt;Alloc(sizeof(USHORT0));</p>
<p align=justify>*((USHORT*)lpi)=0</p>
<strong>
<p align=justify>//</strong><font lang=ZH-CN face=宋体>设置要插入的树节点信息</p>
</font>
<p align=justify>tvi,mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|</p>
<p align=justify>TVIF_CHILDREN;</p>
<p align=justify>tvi.cchTextMax=MAX_PATH;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>设置显示名称</p>
</font>
<p align=justify>tvi.pszText=_T<font lang=ZH-CN face=宋体>（&#8220;桌面&#8221;）；</p>
</font>
<p align=justify>//<font lang=ZH-CN face=宋体>获得标准图标和展开时的图标</p>
</font>
<p align=justify>tvi.ilmage=Tetltemlcon(lpi,NULL);</p>
<p align=justify>tvi.iSelectedlmage=Getltemlcon(lpi,SHGFI_OPENICON);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>设置插入位置</p>
</font>
<p align=justify>tvis.item=tvi;</p>
<p align=justify>tvis.hlnsertAfter=TVI_FIRST;</p>
<p align=justify>tvis.hParent=TVI_ROOT;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>插入根节点</p>
</font>
<p align=justify>hpParent=GetTreeCtrl().Instrtltem(&amp; tvis);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>释放</font>lpi<font lang=ZH-CN face=宋体>所占的空间</p>
</font>
<p align=justify>lpMalloc-&gt;Free(lpi);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>获得&#8220;桌面&#8221;文件夹的</font>IenumiDList<font lang=ZH-CN face=宋体>接口指针</font>lpe</p>
<p align=justify>lpsf-&gt;EnumObjects(m_hWnd, SHCONTF_FOLDERS |</p>
<p align=justify>SHCONTF_NONFOLDERS,&amp; lpe);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>枚举&#8220;桌面&#8221;下的各个子文件夹</p>
</font>
<p align=justify>while(S_OK= =lpe-&gt; Next(1,&amp;lpi,&amp;ulFetched))</p>
<p align=justify>{</p>
<p align=justify>//<font lang=ZH-CN face=宋体>获得</font>lpi<font lang=ZH-CN face=宋体>表示的子文件夹的显示名称</p>
</font>
<p align=justify>GetName(lpsf,lpi,SHGDN_NORMAL,szBuff);</p>
<p align=justify>tvi.pszText=szBuff;</p>
<p align=justify>// <font lang=ZH-CN face=宋体>获得该项的图标</p>
</font>
<p align=justify>//<font lang=ZH-CN face=宋体>由于是&#8220;桌面&#8221;下的直接子项，所以它的相对</font>PIDL<font lang=ZH-CN face=宋体>与绝对</font>PIDL<font lang=ZH-CN face=宋体>是一致的</p>
</font>
<p align=justify>tvi.ilmage=Getltemlcon(lpi,NULL);</p>
<p align=justify>tvi.iSelectedimage=Getltemlcon(lpi,SHGFI_OPENICON);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>设置插入位置</p>
</font>
<p align=justify>tvis.item=tvi;</p>
<p align=justify>tvis.hinsertAfter=hPrev;</p>
<p align=justify>tvis.hParent=hParent;</p>
<p align=justify>//<font lang=ZH-CN face=宋体>插入节点</p>
</font>
<p align=justify>hPrev=GetTreeCtrl(). insertltem(&amp; tvis);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>释放</font>lpi<font lang=ZH-CN face=宋体>所占的空间</p>
</font>
<p align=justify>ipMalloc-&gt;Free(lpi);</p>
<p align=justify>}</p>
<p align=justify>//<font lang=ZH-CN face=宋体>释放</font>Imalloc<font lang=ZH-CN face=宋体>和</font>IsshellFolder<font lang=ZH-CN face=宋体>接口</p>
</font>
<p align=justify>lpMalloc-&gt;Release();</p>
<p align=justify>lpsf-&gt;Release();</p>
<p align=justify>//<font lang=ZH-CN face=宋体>对生成的节点进行排序</p>
</font>
<p align=justify>GetTreeCtrl( ).SortChildren(hParent);</p>
<p align=justify>//<font lang=ZH-CN face=宋体>将</font>CtestView<font lang=ZH-CN face=宋体>中的&#8220;桌面&#8221;节点展开</p>
</font>
<p align=justify>GetTreeCtrl( ).Selectltem(hParent);</p>
<p align=justify>GetTreeCtrl( ).Expand(hParent,TVE_EXPAND);</p>
<p align=justify><font lang=ZH-CN face=宋体>最后，响应</font>CtestView<font lang=ZH-CN face=宋体>的</font>WM_DESTROY<font lang=ZH-CN face=宋体>消息，加入以下代码：</p>
</font>
<p align=justify>//<font lang=ZH-CN face=宋体>由于使用了系统图像列表，退出时必须释放对它的所有权</p>
</font>
<p align=justify>//<font lang=ZH-CN face=宋体>否则，退出后</font>Windows<font lang=ZH-CN face=宋体>将一个图标没有</p>
</font>
<p align=justify>m_imageList.Detach( );</p>
<font lang=ZH-CN face=宋体>
<p align=justify>这个演示程序的效果如下图所示：</p>
</blockquote>
<ol>
    <li>后记 </li>
</ol>
<p align=justify>　　由于篇幅的关系，本文所举的例子只能非常简单的演示一下外壳名字空间的浏览，很多较复杂的编程方法都没有表现出来。</font><font lang=ZH-CN face=宋体>最后，希望本文能够起到抛砖引玉的作用，让更多的开发者认识与使用外壳名字空间，开发出更好的程序来。</p>
</font>
<p align=justify><font lang=ZH-CN face=宋体>参考文献</p>
<ol></font>
    <li>MicrosoftCorporation. Microsoft Windows95<font lang=ZH-CN face=宋体>程序员指南，清华大学出版社，</font>1996
    <li>StefamoMaruzzi.Windows95<font lang=ZH-CN face=宋体>开发者必读，电子工业出版社，</font>1997 </li>
</ol>
</font></font>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/25842.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-04-18 01:05 <a href="http://www.cnitblog.com/seeyeah/archive/2007/04/18/25842.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.Net中多语言版本的实现 [vs2003]</title><link>http://www.cnitblog.com/seeyeah/archive/2007/03/29/24894.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 29 Mar 2007 15:31:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/03/29/24894.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/24894.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/03/29/24894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/24894.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/24894.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Copy From 陈迪臣.Net中两个比较重要的命名空间System.Globalization和System.Resources提供多语言版本的很好解决方案。在这个命名空间中你可以使用手工或者自动的方式来实现你的多语言版本。如果是手工的话，在工程中自己添加一个资源文件或者借助其它工作来生成资源文件，然后通过ResourceManager来读取就可以。在VS2003中，你不用写任何代码也能实...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2007/03/29/24894.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/24894.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-03-29 23:31 <a href="http://www.cnitblog.com/seeyeah/archive/2007/03/29/24894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Generate a client-side proxy for a webservice using HTTP Handlers, Mootools and JSON</title><link>http://www.cnitblog.com/seeyeah/archive/2007/03/23/24545.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 23 Mar 2007 15:24:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/03/23/24545.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/24545.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/03/23/24545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/24545.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/24545.html</trackback:ping><description><![CDATA[
		<div style="OVERFLOW: scroll; WIDTH: 100%; WORD-BREAK: break-all; HEIGHT: 500px">
				<div style="FONT-WEIGHT: bold; FONT-SIZE: 16pt">Generate a client-side proxy for a webservice using HTTP Handlers, Mootools and JSON</div>
				<b>By <a href="http://www.codeproject.com/script/Articles/list_articles.asp?userid=2118410">Bruno R. Figueiredo</a></b>. <br /><br /><div style="FONT-SIZE: 12px">We will create code that will generate all the javascript necessary to call a webservice, sending and recieving Json. This will allow us to choose wich javascript library (such as Mootools, prototype, scriptaculous, etc...) to use and still be able to performe this task.<br /><br /><ul class="download"><li><a href="http://www.codeproject.com/useritems/clientproxyfor_webservice/ClientProxyCP.zip"><font color="#002c99">Download ClientProxyCP.zip - 73.8 KB</font></a></li></ul><h2>Introduction </h2><p>With the release of the MSFT Ajax Extensions, calling a webservice from client-side is a kids task.</p><p>But what if you, like me, want to call a webservice but don't want to use the Ajax Extensions, using instead another library, like mootools? Well you could *just* create the soap body and send it to the webservice. That's seems easy, right?</p><p>Well, I like things that generate themselves.</p><p>In this post I will create a simple client-side proxy from a webservice, and if all ends well, we will be able to call it and get a response.</p><h2>Background info</h2><p>For understanding how this should be done, I went and "reflected" the MSFT Ajax Extensions assemblies to see how did they get this to work. So some of the code presented in this proof of concept is based on this. Again, the main ideia is to understand how to build a proxy similar to the used by the MSFT Ajax Extensions but without really using it.</p><h2>"Why don't you use the MSFT Ajax Extensions?"</h2><p>Well, first of all I wanted to learn how the whole process worked.</p><p>I also wanted to be able to call a webservice by sending and receiving Json without using the MSFT Ajax Extensions. Many small sized libraries make XHR calls. Why not used them.</p><p>Another issue, not covered here, is the usage of this code (with some slight changes) on the v1.1 of the .NET Framework.</p><h2>The first thing...</h2><p>... that we need to do is understand the life cycle of this:</p><p>Given a webservice (or a list of webservices), the application will validate if the webservice has the [AjaxRemoteProxy] attribute. If so, we will grab all the [WebMethod] methods that are public and generate the client-side proxy. When the client-proxy is called, on the server we need to get the correct method, invoke him, and return its results "json style". All of this server-side is done with some IHttpHandlers.</p><p>A HandlerFactory will do the work on finding out what is needed: The default webservice handler, a proxy handler, or a response handler.</p><p>The proxy file will be the asmx itself, but now we will add a "/js" to the end of the call, resulting in something like this:</p><pre lang="html">&lt;script src="http://www.codeproject.com/ClientProxyCP/teste.asmx/js" type="text/javascript"&gt;&lt;/script&gt;
</pre><p>When the call is made to this, a handler will now that a javascript is needed, and generate it.</p><h2>"Show me some code"</h2><p>The first thing we need to have is the <code>AjaxRemoteProxy</code> attribute. This attribute will allow us to both mark wich webservices and web methods we will be able to call on client-side: </p><div class="precollapse" id="premain1" style="WIDTH: 100%"><img id="preimg1" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="1" /><span id="precollapse1" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="1"> Collapse</span></div><pre lang="cs" id="pre1" style="MARGIN-TOP: 0px">using System;

namespace CreativeMinds.Web.Proxy
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class AjaxRemoteProxyAttribute : Attribute
    {
<span class="cs-preprocessor">        #region Private Declarations</span>
        private bool  _ignore = false;
<span class="cs-preprocessor">        #endregion Private Declarations</span><span class="cs-preprocessor">        #region Properties</span><span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Gets or sets a value indicating whether the target is ignored.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;value&gt;&lt;c&gt;true&lt;/c&gt; if ignore; otherwise, &lt;c&gt;false&lt;/c&gt;.&lt;/value&gt;</span>
        public bool  Ignore
        {
            get { return _ignore; }
            set { _ignore = value; }
        }
<span class="cs-preprocessor">        #endregion Properties</span><span class="cs-preprocessor">        #region Constructor</span><span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Initializes a new instance of the &lt;see cref="AjaxRemoteProxyAttribute"/&gt; class.</span><span class="cs-comment">/// &lt;/summary&gt;</span>
        public AjaxRemoteProxyAttribute()
        {
        }
        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Initializes a new instance of the &lt;see cref="AjaxRemoteProxyAttribute"/&gt; class.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;param name="_ignore"&gt;if set to &lt;c&gt;true&lt;/c&gt; if we wish to ignore this target.&lt;/param&gt;</span>
        public AjaxRemoteProxyAttribute(bool _ignore)
        {
            this._ignore = _ignore;
        }
<span class="cs-preprocessor">        #endregion Constructor</span>
    }
}
</pre><p>Now that we have our attribute, lets create a simple Webservice:</p><pre lang="cs">using System.Web.Services;
using CreativeMinds.Web.Proxy;

namespace CreativeMinds.Web.Services{
    [AjaxRemoteProxy()]
    [WebService(Namespace = <span class="cpp-string">"http://tempuri.org/"</span>)]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class MyWebService : WebService
    {
        [WebMethod]
        public string HelloWorld()
        {
            return <span class="cpp-string">"Hello World"</span>;
        }
        [WebMethod]
        public string HelloYou(string name)
        {
            return <span class="cpp-string">"Hello "</span> + name;
        }
    }
}
</pre><p>Notice that the webservice class is marked with our newly created attribute. </p><p>Now comes the cool code. The first thing we now need to do is to let the application know that the calls to *.asmx are now handled by us. So we need to do two things: First create the Handler and then change the web.config file. </p><strong>The WebServices Handler Factory</strong><p>As it was said before, the all *.asmx calls will be handled by us. Because we also want to maintain the normal functionality of the webservices, we need to create a handler factory. This factory will managed the return of the specific handler based on the following assumptions:</p><ol><li>If the context.Request.PathInfo ends with "/js", we need to generate the proxy; 
</li><li>If the context.Request.ContentType is "application/json;" or we have a context.Request.Headers["x-request"] with "JSON" value, we need to execute a method and return its value; 
</li><li>otherwise, we let the webservice run normally.</li></ol><p>So lets build our factory:</p><div class="precollapse" id="premain3" style="WIDTH: 100%"><img id="preimg3" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="3" /><span id="precollapse3" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="3"> Collapse</span></div><pre lang="cs" id="pre3" style="MARGIN-TOP: 0px">using System;
using System.Web;
using System.Web.Services.Protocols;

namespace CreativeMinds.Web.Proxy
{
    public class RestFactoryHandler:IHttpHandlerFactory
    {
<span class="cs-preprocessor">        #region IHttpHandlerFactory Members</span>

        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            if (string.Equals(context.Request.PathInfo, <span class="cpp-string">"/js"</span>, StringComparison.OrdinalIgnoreCase))
            {
                return new RestClientProxyHandler();
            }
            else
            {
                if (context.Request.ContentType.StartsWith(<span class="cpp-string">"application/json;"</span>, StringComparison.OrdinalIgnoreCase) || 
                    (context.Request.Headers[<span class="cpp-string">"x-request"</span>] != null &amp;&amp; 
                    context.Request.Headers[<span class="cpp-string">"x-request"</span>].Equals(<span class="cpp-string">"json"</span>, StringComparison.OrdinalIgnoreCase)))
                {
                    return new RestClientResponseHandler();
                }
            }
            return new WebServiceHandlerFactory().GetHandler(context, requestType, url, pathTranslated);
        }

        public void ReleaseHandler(IHttpHandler handler)
        {
            
        }

<span class="cs-preprocessor">        #endregion</span>
    }
}
</pre><p>Then we also need to let the application know about our factory:</p><pre lang="xml">&lt;httpHandlers&gt;
    &lt;remove verb="*" path="*.asmx"/&gt;
    &lt;add verb="*" path="*.asmx" validate="false" type="CreativeMinds.Web.Proxy.RestFactoryHandler"/&gt;
&lt;/httpHandlers&gt;
</pre><strong>The client-side proxy generator handler</strong><p>When the context.Request.PathInfo equals "/js", we need to generate the client-side proxy. For this task the factory will return the <code>RestClientProxyHandler</code>. </p><div class="precollapse" id="premain5" style="WIDTH: 100%"><img id="preimg5" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="5" /><span id="precollapse5" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="5"> Collapse</span></div><pre lang="cs" id="pre5" style="MARGIN-TOP: 0px">using System.Web;

namespace CreativeMinds.Web.Proxy
{
    class RestClientProxyHandler : IHttpHandler
    {
        private bool isReusable = true;

<span class="cs-preprocessor">        #region IHttpHandler Members</span><span class="cs-comment">///&lt;summary&gt;</span><span class="cs-comment">///Enables processing of HTTP Web requests by a custom HttpHandler that implements the &lt;see cref="T:System.Web.IHttpHandler"&gt;&lt;/see&gt; interface.</span><span class="cs-comment">///&lt;/summary&gt;</span><span class="cs-comment">///</span><span class="cs-comment">///&lt;param name="context"&gt;An &lt;see cref="T:System.Web.HttpContext"&gt;&lt;/see&gt; object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests. &lt;/param&gt;</span>
        public void ProcessRequest(HttpContext context)
        {
            WebServiceData wsd = context.Cache[<span class="cpp-string">"WS_DATA:"</span> + context.Request.FilePath] as WebServiceData;
            if (wsd != null)
            {
                wsd.Render(context);
            }
        }

        <span class="cs-comment">///&lt;summary&gt;</span><span class="cs-comment">///Gets a value indicating whether another request can use the &lt;see cref="T:System.Web.IHttpHandler"&gt;&lt;/see&gt; instance.</span><span class="cs-comment">///&lt;/summary&gt;</span><span class="cs-comment">///</span><span class="cs-comment">///&lt;returns&gt;</span><span class="cs-comment">///true if the &lt;see cref="T:System.Web.IHttpHandler"&gt;&lt;/see&gt; instance is reusable; otherwise, false.</span><span class="cs-comment">///&lt;/returns&gt;</span><span class="cs-comment">///</span>
        public bool IsReusable
        {
            get { return isReusable; }
        }

<span class="cs-preprocessor">        #endregion</span>
    }
}
</pre><p>Notice two things:<br /></p><ol><li>the handler uses a <code>WebServiceData</code> object. This object contains the information about the webservice. So what we do where is get the WebServiceData object from the context.Cache and render it. 
</li><li>the <code>context.Cache[<span class="cpp-string">"WS_DATA:"</span> + ... ]</code> holds all the <code>WebServiceData</code> on all webservices that are proxified. This collection is filled also on the <code>WebServiceData</code> object. </li></ol><p><strong>WebServiceData object</strong></p><p>As said, the WebServiceData contains basic information about the webservice. It is also responsible for the render and execution of the webservice. </p><div class="precollapse" id="premain6" style="WIDTH: 100%"><img id="preimg6" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="6" /><span id="precollapse6" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="6"> Collapse</span></div><pre lang="cs" id="pre6" style="MARGIN-TOP: 0px">using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security;
using System.Text;
using System.Web;
using System.Web.Compilation;
using System.Web.Hosting;
using System.Web.Services;
using System.Web.UI;
using Newtonsoft.Json;

namespace CreativeMinds.Web.Proxy
{
    internal class WebServiceData
    {
        
<span class="cs-preprocessor">        #region Private Declarations</span>

        private List&lt;MethodInfo&gt; _methods;
        private Type _type;
        private string _wsPath;
        private object _typeInstance;

<span class="cs-preprocessor">        #endregion Private Declarations</span><span class="cs-preprocessor">        #region Constructor</span>

        public WebServiceData(string wsPath)
        {
            _wsPath = wsPath;
            _methods = new List&lt;MethodInfo&gt;();
            Process();
        }

<span class="cs-preprocessor">        #endregion Constructor</span><span class="cs-preprocessor">        #region Process</span><span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Processes this instance.</span><span class="cs-comment">/// &lt;/summary&gt;</span>
        private void Process()
        {
            <span class="cs-comment">//Verifies if the path to the webservice is valid</span>
            if (HostingEnvironment.VirtualPathProvider.FileExists(_wsPath))
            {
                Type type1 = null;
                try
                {
                    <span class="cs-comment">// Lets try and get the Type from the Virtual Path</span>
                    type1 = BuildManager.GetCompiledType(_wsPath);
                    if (type1 == null)
                    {
                        type1 = BuildManager.CreateInstanceFromVirtualPath(_wsPath, typeof (Page)).GetType();
                    }

                    if (type1 != null)
                    {
                        <span class="cs-comment">// Good. We have a Type. Now lets check if this is to Profixy.</span>
                        object[] objArray1 = type1.GetCustomAttributes(typeof (AjaxRemoteProxyAttribute), true);
                        if (objArray1.Length == 0)
                        {
                            throw new InvalidOperationException(<span class="cpp-string">"No AjaxRemoteProxyAttribute found on webservice"</span>);
                        }

                        <span class="cs-comment">// Well. So far so good.</span><span class="cs-comment">// Let's get all the methods.</span>
                        BindingFlags flags1 = BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance;
                        MethodInfo[] infoArray1 = type1.GetMethods(flags1);

                        foreach (MethodInfo info1 in infoArray1)
                        {
                            <span class="cs-comment">// we only need the WebMethods</span>
                            object[] metArray1 = info1.GetCustomAttributes(typeof (WebMethodAttribute), true);
                            if (metArray1.Length != 0)
                            {
                                _methods.Add(info1);
                            }
                        }
                        
                        <span class="cs-comment">// keep locally the Type</span>
                        _type = type1;

                        <span class="cs-comment">// Add this WS to the Cache, for later use.</span>
                        if (HttpContext.Current.Cache[<span class="cpp-string">"WS_DATA:"</span> + VirtualPathUtility.ToAbsolute(_wsPath)] == null)
                        {
                            HttpContext.Current.Cache[<span class="cpp-string">"WS_DATA:"</span> + VirtualPathUtility.ToAbsolute(_wsPath)] = this;
                        }
                    }
                    else
                    {
                        throw new ApplicationException(<span class="cpp-string">"Couldn't proxify webservice!!!!"</span>);
                    }
                }
                catch (SecurityException)
                {
                }
            }
        }

<span class="cs-preprocessor">        #endregion</span><span class="cs-preprocessor">        #region Render</span><span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Renders the Proxy to the specified &lt;see cref="HttpContext"/&gt;.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;param name="context"&gt;The &lt;see cref="HttpContext"/&gt;.&lt;/param&gt;</span>
        public void Render(HttpContext context)
        {
            <span class="cs-comment">// Set the ContentType to Javascript</span>
            context.Response.ContentType = <span class="cpp-string">"application/x-javascript"</span>;

            StringBuilder aux = new StringBuilder();
            if (_type == null) return;

            <span class="cs-comment">// Register the namespace</span>
            aux.AppendLine(string.Format(<span class="cpp-string">"RegisterNamespace(\"</span>{0}\<span class="cpp-string">");"</span>, _type.Namespace));

            <span class="cs-comment">// Create the Class for this Type</span>
            string nsClass = string.Format(<span class="cpp-string">"{0}.{1}"</span>, _type.Namespace, _type.Name);
            aux.AppendLine(string.Format(<span class="cpp-string">"{0} = function(){{}};"</span>, nsClass));

            _methods.ForEach(delegate (MethodInfo method)
                                 {
                                     <span class="cs-comment">// Create a static Method on the class</span>
                                     aux.AppendFormat(<span class="cpp-string">"{0}.{1} = function("</span>, nsClass, method.Name);

                                     <span class="cs-comment">// Set the method arguments</span>
                                     StringBuilder argumentsObject = new StringBuilder();
                                     foreach (ParameterInfo info2 in method.GetParameters())
                                     {
                                         aux.AppendFormat(<span class="cpp-string">"{0}, "</span>, info2.Name);
                                         argumentsObject.AppendFormat(<span class="cpp-string">"\"</span>{0}\<span class="cpp-string">":{0}, "</span>, info2.Name);
                                     }

                                     if (argumentsObject.Length &gt; 0)
                                     {
                                         argumentsObject = argumentsObject.Remove(argumentsObject.Length - 2, 2);
                                         argumentsObject.Insert(0, <span class="cpp-string">"{"</span>).Append(<span class="cpp-string">"}"</span>);
                                     }

                                     <span class="cs-comment">// Add the CompleteHandler argument in last</span>
                                     aux.Append(<span class="cpp-string">"onCompleteHandler){\n"</span>);

                                     <span class="cs-comment">// Render the method Body with the XHR call</span>
                                     aux.AppendLine(string.Format(<span class="cpp-string">"new Json.Remote(\"</span>{1}\<span class="cpp-string">", {{onComplete: onCompleteHandler, method:'post'}}).send({0});"</span>,                                      argumentsObject.ToString(), VirtualPathUtility.ToAbsolute(_wsPath + <span class="cpp-string">"/"</span> + method.Name)));
                                     aux.Append(<span class="cpp-string">"}\n"</span>);
                                 });
            context.Response.Write(aux.ToString());
        }

<span class="cs-preprocessor">        #endregion</span><span class="cs-preprocessor">        #region Invoke</span><span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Invokes the requested WebMethod specified in the &lt;see cref="HttpContext"/&gt;.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;param name="context"&gt;The &lt;see cref="HttpContext"/&gt;.&lt;/param&gt;</span>
        public void Invoke(HttpContext context)
        {
            <span class="cs-comment">// Method name to invoke</span>
            string methodName = context.Request.PathInfo.Substring(1);

            <span class="cs-comment">// We need an Instance of the Type</span>
            if (_typeInstance == null)
                _typeInstance = Activator.CreateInstance(_type);

            <span class="cs-comment">// Get the Posted arguments (format "json={JSON Object}")</span>
            string requestBody = new StreamReader(context.Request.InputStream).ReadToEnd();
            string[] param = requestBody.Split('=');
            <span class="cs-comment">// JSON Deserializer @ http://www.newtonsoft.com/products/json/</span>
            object a = JavaScriptConvert.DeserializeObject(param[1]);
            <span class="cs-comment">//object a = JavaScriptDeserializer.DeserializeFromJson&lt;object&gt;(param[1]);</span>
            Dictionary&lt;string, object&gt; dic = a as Dictionary&lt;string, object&gt;;
            int paramCount = 0;
            if (dic != null)
            {
                paramCount = dic.Count;
            }
            object[] parms = new object[paramCount];

            if (dic != null)
            {
                int count = 0;
                foreach (KeyValuePair&lt;string, object&gt; kvp in dic)
                {
                    Debug.WriteLine(string.Format(<span class="cpp-string">"Key = {0}, Value = {1}"</span>, kvp.Key, kvp.Value));
                    parms[count] = kvp.Value;
                    count++;
                }
            }

            <span class="cs-comment">// Get the method to invoke and invoke it</span>
            MethodInfo minfo = _type.GetMethod(methodName);
            object resp = minfo.Invoke(_typeInstance, parms);

            <span class="cs-comment">// Serialize the response</span><span class="cs-comment">// JSON Serializer @ http://www.newtonsoft.com/products/json/</span>
            string JSONResp = JavaScriptConvert.SerializeObject(new JsonResponse(resp));

            <span class="cs-comment">// Render the output to the context</span>
            context.Response.ContentType = <span class="cpp-string">"application/json"</span>;
            context.Response.AddHeader(<span class="cpp-string">"X-JSON"</span>, JSONResp);
            context.Response.Write(JSONResp);
        }

<span class="cs-preprocessor">        #endregion</span>
    }

    <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Wrapper for the JSON response</span><span class="cs-comment">/// &lt;/summary&gt;</span>
    public class JsonResponse
    {
        private object  _result = null;

        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Gets or sets the result output.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;value&gt;The result.&lt;/value&gt;</span>
        public object  Result
        {
            get { return _result; }
            set { _result = value; }
        }


        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Initializes a new instance of the &lt;see cref="JsonResponse"/&gt; class.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;param name="_result"&gt;The _result.&lt;/param&gt;</span>
        public JsonResponse(object _result)
        {
            this._result = _result;
        }
    }
}
</pre><p>When initialized, the WebServiceData object will try to get a <code>Type</code> from the webservice path. If successful, it will check if the webservice has the <code>AjaxRemoteProxyAttribute</code>, and if true, will extract the WebMethods list. </p><p>The <code>Invoke</code> method looks at the <code>context.Request.PathInfo</code> to see what method to execute. It also check if arguments are passed on the <code>context.Request.InputStream</code> and if so, adds them to the method call. In the end the response is serialized into a Json string and sent back to the client. </p><p>The Render method looks at all the WebMethods and creates the client-side code. </p><p>The <code>JsonResponse</code> class is used to simplify the serialization of the Json response.</p><p>With this we have completed the first big step: Build the necessary code to generate the proxy. </p><p>Now to help up "proxifing" the webservices, we will build a simple helper to use on the webforms: </p><div class="precollapse" id="premain7" style="WIDTH: 100%"><img id="preimg7" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="7" /><span id="precollapse7" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="7"> Collapse</span></div><pre lang="cs" id="pre7" style="MARGIN-TOP: 0px">using System.Collections.Generic;
using System.Web;
using System.Web.UI;

namespace CreativeMinds.Web.Proxy
{
    public static class ProxyBuilder
    {
<span class="cs-preprocessor">        #region Properties</span><span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Gets or sets the get WS proxy list.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;value&gt;The get WS proxy list.&lt;/value&gt;</span>
        public static List&lt;string&gt; WSProxyList
        {
            get
            {
                List&lt;string&gt; aux = HttpContext.Current.Cache[<span class="cpp-string">"WS_PROXIES_URL"</span>] as List&lt;string&gt;;
                HttpContext.Current.Cache[<span class="cpp-string">"WS_PROXIES_URL"</span>] = aux ?? new List&lt;string&gt;();
                return HttpContext.Current.Cache[<span class="cpp-string">"WS_PROXIES_URL"</span>] as List&lt;string&gt;;
            }
            set
            {
                HttpContext.Current.Cache[<span class="cpp-string">"WS_PROXIES_URL"</span>] = value;
            }
        }

<span class="cs-preprocessor">        #endregion Properties</span>


        public static void For(string wsPath)
        {
            if (!WSProxyList.Exists(delegate(string s) { return s == wsPath; }))
            {
                new WebServiceData(wsPath);
                WSProxyList.Add(wsPath);
            }
        }

        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Renders all Webservice Proxies in the &lt;see cref="Page"/&gt;.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;param name="page"&gt;The &lt;see cref="Page"/&gt; where the proxies will be generated and sused.&lt;/param&gt;</span>
        public static void RenderAllIn(Page page)
        {
            WSProxyList.ForEach(delegate(string virtualPath)
                                       {
                                           string FullPath = VirtualPathUtility.ToAbsolute(virtualPath + <span class="cpp-string">"/js"</span>);
                                           page.ClientScript.RegisterClientScriptInclude(string.Format(<span class="cpp-string">"WSPROXY:{0}"</span>, FullPath), FullPath);                               
                                       });
        }
    }
}
</pre><p>The <code>ProxyBuilder.For</code> method recieves a string with the virtual path to the webservice. With a valid path, this method will add a new <code>WebServiceData</code> object to the <code>WSProxyList</code> property. </p><p>When no more proxies are needed, the <code>ProxyBuilder.RenderAllIn</code> should be called. This will register all client script generated by our proxies. </p><pre lang="cs">protected void Page_Load(object sender, EventArgs e)
{
    ProxyBuilder.For(<span class="cpp-string">"~/teste.asmx"</span>);
    ProxyBuilder.RenderAllIn(this);
}
</pre><p>Browsing the page, we can now see the output for our webservice:</p><pre lang="jscript">RegisterNamespace(<span class="cpp-string">"CreativeMinds.Web.Services"</span>);
CreativeMinds.Web.Services.teste = function(){};
CreativeMinds.Web.Services.teste.HelloWorld = function(onCompleteHandler){
new Json.Remote(<span class="cpp-string">"/CreativeMindsWebSite/teste.asmx/HelloWorld"</span>, {onComplete: onCompleteHandler, method:'post'}).send();
}
CreativeMinds.Web.Services.teste.HelloYou = function(name, onCompleteHandler){
new Json.Remote(<span class="cpp-string">"/CreativeMindsWebSite/teste.asmx/HelloYou"</span>, {onComplete: onCompleteHandler, method:'post'}).send({<span class="cpp-string">"name"</span>:name});
}
</pre><p>Sweet! The generated javascript resembles our webservice class. We have the namespace <code>CreativeMinds.Web.Services</code> created, the class name <code>teste</code> its also there, and its webmethods. Notice that all method calls need a <code>onCompleteHandler</code>. This will handle all the successfully calls. </p><p>Only two step remaining: The Response Handler, and testing it all.</p><strong>Response Handler</strong><p>As you can see in the code generated by the proxy, the call to the webservice method doesn't change: </p><p><em>/CreativeMindsWebSite/teste.asmx/HelloWorld</em></p>So how can the know what to return - Json or XML?. Well, we will watch for the <code>context.Request.ContentType</code> and the <code>context.Request.Headers</code> on our <code>RestFactoryHandler</code> class. If one of thoose as Json on it we know what to do... :) 
<p>When a Json response is requested, the <code>RestFactoryHandler</code> will return the <code>RestClientResponseHandler</code>. </p><div class="precollapse" id="premain10" style="WIDTH: 100%"><img id="preimg10" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="10" /><span id="precollapse10" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="10"> Collapse</span></div><pre lang="cs" id="pre10" style="MARGIN-TOP: 0px">using System.Web;

namespace CreativeMinds.Web.Proxy
{
    public class RestClientResponseHandler : IHttpHandler
    {
<span class="cs-preprocessor">        #region IHttpHandler Members</span><span class="cs-comment">///&lt;summary&gt;</span><span class="cs-comment">///Enables processing of HTTP Web requests by a custom HttpHandler that implements the &lt;see cref="T:System.Web.IHttpHandler"&gt;&lt;/see&gt; interface.</span><span class="cs-comment">///&lt;/summary&gt;</span><span class="cs-comment">///</span><span class="cs-comment">///&lt;param name="context"&gt;An &lt;see cref="T:System.Web.HttpContext"&gt;&lt;/see&gt; object that         /// provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests. &lt;/param&gt;</span>
        public void ProcessRequest(HttpContext context)
        {
            WebServiceData wsd = context.Cache[<span class="cpp-string">"WS_DATA:"</span> + context.Request.FilePath] as WebServiceData;
            if (wsd != null)
            {
                wsd.Invoke(context);
            }
        }

        <span class="cs-comment">///&lt;summary&gt;</span><span class="cs-comment">///Gets a value indicating whether another request can use the &lt;see cref="T:System.Web.IHttpHandler"&gt;&lt;/see&gt; instance.</span><span class="cs-comment">///&lt;/summary&gt;</span><span class="cs-comment">///</span><span class="cs-comment">///&lt;returns&gt;</span><span class="cs-comment">///true if the &lt;see cref="T:System.Web.IHttpHandler"&gt;&lt;/see&gt; instance is reusable; otherwise, false.</span><span class="cs-comment">///&lt;/returns&gt;</span><span class="cs-comment">///</span>
        public bool IsReusable
        {
            get { return true; }
        }

<span class="cs-preprocessor">        #endregion</span>
    }
}
</pre><p>Again notice that it tries to get a <code>WebServiceData</code> object from the <code>context.Cache</code> and <code>Invoke</code> it passing the context as argument. The <code>Invoke</code> method of the <code>WebServiceData</code> will extract the method name form the PathInfo. Then it will create an instance from the Type, check for arguments passed on the post by checking the <code>Request.InputStream</code>. Using the Newtonsoft JavaScriptDeserializer we deserialize any arguments and add them to the object collection needed to invoke a method. Finally we invoke the method, serialize the response and send it back to the client. </p><div class="precollapse" id="premain11" style="WIDTH: 100%"><img id="preimg11" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="11" /><span id="precollapse11" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="11"> Collapse</span></div><pre lang="cs" id="pre11" style="MARGIN-TOP: 0px">...

namespace CreativeMinds.Web.Proxy
{
    internal class WebServiceData
    {

...

        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Invokes the requested WebMethod specified in the &lt;see cref="HttpContext"/&gt;.</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// &lt;param name="context"&gt;The &lt;see cref="HttpContext"/&gt;.&lt;/param&gt;</span>
        public void Invoke(HttpContext context)
        {
            <span class="cs-comment">// Method name to invoke</span>
            string methodName = context.Request.PathInfo.Substring(1);

            <span class="cs-comment">// We need an Instance of the Type</span>
            if (_typeInstance == null)
                _typeInstance = Activator.CreateInstance(_type);

            <span class="cs-comment">// Get the Posted arguments (format "json={JSON Object}")</span>
            string requestBody = new StreamReader(context.Request.InputStream).ReadToEnd();
            string[] param = requestBody.Split('=');
            <span class="cs-comment">// JSON Deserializer @ http://www.newtonsoft.com/products/json/</span>
            object a = JavaScriptConvert.DeserializeObject(param[1]);
            <span class="cs-comment">//object a = JavaScriptDeserializer.DeserializeFromJson&lt;object&gt;(param[1]);</span>
            Dictionary&lt;string, object&gt; dic = a as Dictionary&lt;string, object&gt;;
            int paramCount = 0;
            if (dic != null)
            {
                paramCount = dic.Count;
            }
            object[] parms = new object[paramCount];

            if (dic != null)
            {
                int count = 0;
                foreach (KeyValuePair&lt;string, object&gt; kvp in dic)
                {
                    Debug.WriteLine(string.Format(<span class="cpp-string">"Key = {0}, Value = {1}"</span>, kvp.Key, kvp.Value));
                    parms[count] = kvp.Value;
                    count++;
                }
            }

            <span class="cs-comment">// Get the method to invoke and invoke it</span>
            MethodInfo minfo = _type.GetMethod(methodName);
            object resp = minfo.Invoke(_typeInstance, parms);

            <span class="cs-comment">// Serialize the response</span><span class="cs-comment">// JSON Serializer @ http://www.newtonsoft.com/products/json/</span>
            string JSONResp = JavaScriptConvert.SerializeObject(new JsonResponse(resp));

            <span class="cs-comment">// Render the output to the context</span>
            context.Response.ContentType = <span class="cpp-string">"application/json"</span>;
            context.Response.AddHeader(<span class="cpp-string">"X-JSON"</span>, JSONResp);
            context.Response.Write(JSONResp);
        }
...
</pre><p>With this is are ready to test a call. So all we need to do is, first create the <code>onCompleteHandler</code> function to handle the response: </p><pre lang="jscript">    function completedHandler(json)
    {
        alert(json.Result);
    }
</pre>Then add a textbox to the page: <pre lang="html">    &lt;input type="textbox" id="txtName" /&gt;
</pre>Finally, a caller: <pre lang="html">    &lt;a href="#" onclick="CreativeMinds.Web.Services.teste.HelloYou($("textbox").value, complete)"&gt;call HelloYou&lt;/a&gt;
</pre><p>That's it. We have build a proxy generator. </p><p>Again this is a proof of concept, so its not tested for performance nor bug/error proof. </p><!-- Article Ends --><script src="http://www.codeproject.com/script/togglePre.js" type="text/javascript"></script></div></div>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/24545.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-03-23 23:24 <a href="http://www.cnitblog.com/seeyeah/archive/2007/03/23/24545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 用C#获取系统有关环境、属性 </title><link>http://www.cnitblog.com/seeyeah/archive/2007/03/22/24428.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 22 Mar 2007 12:07:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/03/22/24428.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/24428.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/03/22/24428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/24428.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/24428.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Copy From 执子之手的专栏如果利用C#获取系统有关环境和属性，这个也是在网上问得比较多的问题，不过大部分只有提问没有回答，最近正好想做有关方面的东西，整理了一下，提供给大家，希望能给大家提供参考意见：首先需要定义几个结构(struct) ，便于DllImport作为返回参数调用。以下是代码：CpuInfo.csusing System;using System.Configuration;...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2007/03/22/24428.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/24428.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-03-22 20:07 <a href="http://www.cnitblog.com/seeyeah/archive/2007/03/22/24428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Applying Robustness Analysis on the Model–View–Controller (MVC) Architecture in ASP.NET Framework, using UML</title><link>http://www.cnitblog.com/seeyeah/archive/2007/03/20/24312.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 19 Mar 2007 17:09:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/03/20/24312.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/24312.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/03/20/24312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/24312.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/24312.html</trackback:ping><description><![CDATA[
		<div style="FONT-WEIGHT: bold; FONT-SIZE: 16pt">
				<a href="/Files/seeyeah/ModelViewController_demo_src.zip">
						<font color="#002c99">ModelViewController_demo_src.zip</font>
				</a>
				<br />
				<hr />
				<br />Applying Robustness Analysis on the Model–View–Controller (MVC) Architecture in ASP.NET Framework, using UML</div>
		<b>By <a href="http://www.codeproject.com/script/Articles/list_articles.asp?userid=90779">Shams Mukhtar</a></b>. <br /><br /><div style="FONT-SIZE: 12px">This article will enhance your vision on the usage of Robustness Analysis in conjunction with Model View Controller, using UML with application in ASP.NET. This article is a sequel to my articles on Architecture and Design with ASP.NET.<br /><h2>Introduction</h2><p nd="1">Recently, I wrote <a href="http://www.codeproject.com/aspnet/Frame_Work_Design.asp"><font color="#002c99">an article</font></a> on the development of a master-page framework in ASP.NET. Master Page framework was an extension of the ASP.NET <code nd="2">UI.Page</code> framework, and most of it is related to the static appearance of the Page. Then, I started receiving emails about the dynamic behavior of pages, and controlling the interactions between user-controls on a page, and communication between different pages etc. So, I thought there is a need of discussion on this aspect of the .NET Framework, and this would not be possible without mentioning the Model-View-Controller Design Pattern, that is embedded everywhere in the ASP.NET Framework. This article is composed of two parts. In the first part, we will discuss in detail about the Model-View-Controller Design pattern in context to ASP.NET, using UML, and finish our discussion with writing an example <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/ModelViewController.asp#" target="_blank" itxtdid="3265760">application</a> as a bonus for its implementation. In the next part of the article, we’ll wrap up our discussion with dynamic aspects of pages by explaining different types of fine-grained controllers with their design and implementation, and we’ll discuss about the details of the HTTP pipeline too and what is the best approach to use it; so stay tuned, lot to come :).</p><h3>Model-View-Controller Design Pattern:</h3><p nd="3">This is the classical and most famous of all design patterns especially when we talk about User Interfaces. A user interface is basically a presentation layer of some sort of model-data. If the <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/ModelViewController.asp#" target="_blank" itxtdid="3265785">data</a> changes, the view is updated accordingly, or vice-versa. In this particular scenario, if you look closely, you can observe that there are two objects involved for performing this task, i.e., a <b>View</b> and a <b>Model</b>. There might be more than one view of a data model. Like, one view could be a Grid presentation, and other could be a Graphical Plot of some sort, like Bar chart or Pie chart, or so. Here is how it would look like:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image001_big.jpg" target="_blank"><img height="267" alt="image001.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image001.jpg" width="600" /></a></p><p nd="4">I know, you should have these questions now, like how the view object would talk with the model object and vice versa, and how we want to look at the model, which part of the model will go to which view and which part of the view and how. Now, we are talking about one other object, the controller object; this controller object acts as glue between model and view. Controller object is basically a business object, provides the answer how we want to view the data, what rules should be applied for its presentation or so, and what will happen if some one changes some parameters in the view, how to react to some key-board or mouse events if this is an interactive application, and some times you need to update the model and send messages to other views that the data is changed, so that they can postback a request for updating their own contents. You will get all these answers shortly!</p><h3>Robustness Analysis:</h3><p nd="5">This Model-View-Controller can be best described visually, using robustness analysis, first introduced by Ivar Jacobson, in his award winning book on Object Oriented Software Engineering (see reference below), and was further explained by Doug Rosenberg et al in his book, Use Case Driven Object Modeling with UML. Robustness Analysis involves analyzing the narrative text of use cases, identifying a first-guess set of objects that will participate in those use cases, and classifying these objects based on the roles they play, and it helps you partition objects within a Model-View-Controller paradigm. Robustness analysis enables the ongoing discovery of objects, and helps you ensure that you've identified most of the major domain classes before starting any additional design or development. Ivar has classified them as:</p><ol><li nd="6">«entity» objects depict long lived objects, deals mostly with the persisted states. 
</li><li nd="7">«boundary» objects depict links between the system and environment, communicating. 
</li><li nd="8">«control» objects depict use-case-specific behavior. </li></ol><p nd="9"><b>Entity objects</b> are no more than the information or data your boundary objects are looking for. These might be <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/ModelViewController.asp#" target="_blank" itxtdid="3265794">database</a> tables, Excel files, or might be "transient" session or cached data or so.</p><p nd="10"><b>Boundary objects</b> are the objects with which the actors (for instance, the users) will be communicating in your software system. These might be any windows, screens, dialogs and menus, or other UIs in your system. You can easily identify them while analyzing your use cases.</p><p nd="11"><b>Control objects</b> (controllers) are the business objects or your business web-services. This is where you capture your business rules that are used to filter out the data to be presented to the user he has requested for or something. So, the controllers are actually controlling the businesses needs or the business itself.</p><p nd="12">Here are the visual icons of these three UML stereotypes:</p><p><img height="200" alt="image003.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image003.jpg" width="534" /></p><h3>Rules of the game:</h3><p nd="13">Here are the four basic rules you should enforce when extracting these objects while analyzing your use cases and making interaction diagrams among these objects:</p><ul><li nd="14">Actors can only talk to the boundary objects. 
</li><li nd="15">Boundary objects can only talk to controllers and actors. 
</li><li nd="16">Entity objects can only talk to controllers. 
</li><li nd="17">Controllers can talk to boundary objects and entity objects, and to other controllers, but not to actors. </li></ul><p><img height="360" alt="image005.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image005.jpg" width="537" /></p><p nd="18">If you look at the above figure, you can see the only access point for an actor to reach any object is through the Boundary objects. Boundary objects can’t talk with each other. While Control objects can talk freely with all of the objects except that it has no access to the actor or the user of the system. And the Entity objects can’t talk with each other too; they can access each other but through the Control object. Also, an Entity object can only reach Boundary object through the Control object. So the Control object is really a media of communication between each layer, and that’s why it is suited for business rules.</p><h3>Robustness Analysis and Model-View-Controller:</h3><p nd="19">Now, we have all the rules in place, let’s see how these objects are related to Model-View-Controller paradigm. Well, good news is this, that they have one-to-one mapping with the objects, derived from this analysis:</p><ul><li nd="20">Entity object maps to Model object, 
</li><li nd="21">Boundary object maps to View object, and 
</li><li nd="22">Controller is same in both. </li></ul><p nd="23">And the other good news is that the same rules are applied to these objects too. It means, when we are doing Robustness Analysis, we can use Model-View-Controller objects in place of Entity-Boundary-Controller objects. Here is how our objects would look like now:</p><p><img height="200" alt="image007.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image007.jpg" width="503" /></p><p nd="24">And here is the simplistic and hypothetical sequence diagram for MVC. What you see in this diagram, a web-user initiated a query and an event is generated that is handled by the controller and gets information that is needed from the model, validates the information and passes back the result set to the view.</p><p><img height="484" alt="image009.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image009.jpg" width="600" /></p><p nd="25">Model-View-Controller is an approach for segregating different layers, in such a manner that it can be easy to maintain for a moderate to very complex application. It would be best suitable when you are making something for the web, where the business rules change frequently with time. Also, it’s the best way of writing applications in a service oriented architecture, where you write/encapsulate your business rules in a separate web-service than the Data-Access Layer, where the service is only dealing with Model/Data related stuff. Since the user interfaces are also separate, you can build powerful Custom Controls, and put them in the User-Controls for deploying as Pagelets. And finally, what is left, you need just to build proper interactions for them, enforcing rules mentioned above, while designing any solution.</p><h3>Examples:</h3><p nd="26">So, let’s see where we stand now: we now know what these model-view-controller objects are, how they look like, and what are the rules we should enforce when we do analysis of a particular use case scenario and making interaction diagrams out of them. Let’s take an example scenario and explain it using this technique!</p><h4>Use case (UC.1.001):</h4><p nd="27"><u nd="27">User shall be able to logon to the web-application.</u></p><p nd="28">Here is the UML diagram for this use case; it shows an actor (web-user) and logon use-case relationship, it would more be elaborated when we go into the analysis phase of it. I am taking a very simple case, of login and deferring the registration use-case for our example, for making it simple and understandable at the first go.</p><p><img height="216" alt="image011.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image011.jpg" width="379" /></p><p nd="29">Before going into any analysis, it would be better, or I call it, it’s a must, that you should have the visual prototype in front of you. Here is how our prototype would look like:</p><p><img height="150" alt="image013.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image013.jpg" width="282" /></p><p nd="30">What it means, that the user is presented with a logon screen, where he can enter his identity and press the Login button for access to the system. The user can also turn on the check-mark on the check box for remembering him; in that case, a cookie is needed on his system, to be enabled. Also, when he logs in, a new session is created on the server side for keeping his activities alive while using the web-application. With all these, let’s elaborate this scenario using the Robustness Analysis diagrams:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image015_big.jpg" target="_blank"><img height="371" alt="image015.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image015.jpg" width="600" /></a></p><p nd="31">Let’s take a closer look at the above diagram. User interacts with Logon Screen (the view) that has one submit button for login (has-a relationship in UML is shown with a diamond shaped line at one end), and has a checkbox for enabling the cookie storage or so. What happens when the user clicks on any of these two buttons, the request goes to the <code nd="32">MainController</code> object, which then decides what to do with these actions, since it has all the logic built for handling those events, and then does some validations from security control object that in turn takes data from the Data Access object? <code nd="33">MainController</code> then creates a session for this user, it also stores user's info like encrypted passwords, in somewhere in the cookie store or so. With this analysis, we are now very much clear that, apart from the logon screen, there would be four other objects involved in this scenario; <code nd="34">MainController</code>, <code nd="35">SessionState</code> object, the <code nd="36">CookieStore</code> object and the Database Access objects. It does have given you an idea what are the objects required to do a particular job, but it does not tell you what functionality is needed for accomplishing this task. For that, we need a sequence diagram, here is how the sequence diagram should look like:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image017_big.jpg" target="_blank"><img height="468" alt="image017.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image017.jpg" width="600" /></a></p><p nd="37">After careful study of the above sequence diagram, we can safely classify our objects as there should be a <code nd="38">MainController</code>, that takes care the business logic for the page, and a <code nd="39">BusinessService</code> object that takes care of all the validation, Session Management and cookie setup stuff. There would be a <code nd="40">DataAccessGateWay</code> (model) object that encapsulates all the details of talking with the back end database. Here is how the class diagram looks like:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image019_big.jpg" target="_blank"><img height="302" alt="image019.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image019.jpg" width="600" /></a></p><p nd="41">Isn’t it beautiful that all of this robustness analysis leads us to a design where we can define our first set of detailed class diagrams? I know you’ll love it.</p><p nd="42">The most important of all of the objects above, are the business objects that are the controller objects. Now, let’s have a closer look at how ASP.NET framework facilitates us in defining these Controller classes.</p><h3>ASP.NET and Model-View-Controller (MVC)</h3><p nd="43">Basic idea of MVC is to segregate the presentation layer from the business layer and the Data Access Layer, or the model. Let’s see how it is done in ASP.NET.</p><p><img height="263" alt="image021.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image021.jpg" width="413" /></p><p nd="44">Let’s have a closer look at this picture, <code nd="45">Controller</code> is bound to some model, and updates the <code nd="46">View</code> when the data changes or vice-versa. So, the view depends on the model, passively. We achieve this goal, with the code-behind feature of ASP.NET, the page/user-controls logic is separate from that of the view, that is presented either in “*.aspx” files or in “*.ascx” files. And the controls you add to the page-controller, i.e. <code nd="47">System.UI.Page</code>, you try to make them data-bounded as much as possible for consistency and synchronization. And also, you embed your event handler’s logic in the page controller using the code-behind feature. And if your architecture is service-oriented architecture, then you can introduce another controller as a business service (might be security service) that talks to the back-end model as needed and returns secured data to the Page Controller. Here is how it would look like:</p><p><img height="600" alt="image023.jpg" src="http://www.codeproject.com/aspnet/ModelViewController/image023.jpg" width="597" /></p><h3>It's Showtime (bonus++):</h3><p nd="48">As a bonus, we would be developing a full fledged master-details web application that will give you enough details about model-view-controller (MVC) and its inner working, as well as a way of communication between different user-controls without even knowing each other. Also, with it you’ll get a reusable library that is composed of classes <code nd="49">OleDataLinkAdapter</code> and <code nd="50">MsSqlDataLinkAdapter</code>. These objects are wrappers around ADO.NET Connection and Command objects.</p><h4>Master-Details ASP.NET Application</h4><p nd="51">The application is a web-application that has a master-page composed of a company logo, a banner, main contents, and footer. Main contents should display a parent-child relationship in the form of grid-view. There shall be two grids, the top one would be the master grid and the bottom would be the details one. When the user clicks on any item in the master view, the details/child view changes accordingly and should display the related child data.</p><p nd="52">Use-Case001: User shall be able to view/manipulate the master-details for Northwind Customer/Orders tables.</p><p><img height="240" alt="image025.png" src="http://www.codeproject.com/aspnet/ModelViewController/image025.png" width="351" /></p><p nd="53">We would be applying the same technique as in my previous article, that is Pattern Oriented Architecture and Design (POAD). For this, we need the prototypic pattern of our system we are planning to design. And here is how the prototype would look like:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image027_big.png" target="_blank"><img height="431" alt="image027.png" src="http://www.codeproject.com/aspnet/ModelViewController/image027.png" width="600" /></a></p><p nd="54">So, what we see is what we get, that is, our application would be composed of a <code nd="55">MasterPage</code>, an HTML frame container, then HTML Table, and this table would contain further the two controls, Master-User-Control and the Details-User-Control. These user controls in turn would contain the <code nd="56">MasterDataGrid</code> and <code nd="57">DetailsDataGrid</code> Views. Here is the static inventory of the objects, needed to fulfill this job:</p><p><img height="288" alt="image029.png" src="http://www.codeproject.com/aspnet/ModelViewController/image029.png" width="549" /></p><h4>Robustness Analysis of the Use-Case001</h4><p nd="58">We now have some understandings of the objects needed to fulfill this job, but before going into the detailed design, we need to analyze the use cases, to find-out the proper interactions and relationships among them. This would be done using the Robustness Analysis, while keeping into our mind the MVC concept. Let's draw the conceptual Robustness Diagram for this scenario:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image031_big.png" target="_blank"><img height="332" alt="image031.png" src="http://www.codeproject.com/aspnet/ModelViewController/image031.png" width="600" /></a></p><p nd="59">What it means, that the user is presented with a master-details view. The upper Master-Grid-view is used to select the master table items. So, whenever the user selects master item, the child view is updated accordingly. Let's see how we achieve these interactions between objects. Look at the above diagram closely and you will see that when the user selects an item from the master-grid-view, the <code nd="60">MasterUserControl</code> would be notified, and that in turn notifies this event to the listener, that is the <code nd="61">MainController</code> object. <code nd="62">MainController</code> object would notify about this event to the other listener, the <code nd="63">DetailsUserControl</code>.</p><p nd="64">These user-controls have direct access to the Model (<code nd="65">DataAccessGateway</code>) that uses <code nd="66">MsSqlDataLinkAdapter</code> to establish MS-SQL database connections (for OLEDB connections, use the other adapter, <code nd="67">OleDataLinkAdapter</code>). This is a classic example of the MVC and its inner working. Here is the object interaction diagram for this particular scenario:</p><p><img height="432" alt="image033.png" src="http://www.codeproject.com/aspnet/ModelViewController/image033.png" width="600" /></p><p nd="68">The <code nd="69">MasterController</code> and the <code nd="70">DetailsController</code> are differential Controllers, that they are responsible of controlling one User-Control at a time and fine tune them while the <code nd="71">MainController</code> object acts as an integrator, or a channel for these two controllers to pass information to and fro between them. Let's see how we are planned for them to work. For an object being a Notifying object, needs to implement the <code nd="72">INotifier</code> interface, while a Listener object needs to implement the <code nd="73">IListner</code> interface. Also, a listener object needs to attach itself with the relevant notifier in-order for being notified. In our case, we have the Master-Controller and, the Details-Controller is the listener. <code nd="74">MainController</code> is both listener and notifier, and acts as glue between them.</p><p nd="75">Now, at this point, we have all the information about the objects, responsible for doing the job, how they would look like, and about their behavior and functionality. Let's now design them and develop the complete class design. And here is the detailed class diagram for this application:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image035_big.png" target="_blank"><img height="455" alt="image035.png" src="http://www.codeproject.com/aspnet/ModelViewController/image035.png" width="600" /></a></p><h2>Implementation using C# and ASP.NET</h2><p nd="76">Code hierarchy is shown in the following figure, where you will find DataAccess adapters in <i>Shams.Data.dll</i>, updated MasterPage Framework library in <i>Shams.Web.UI.MasterPages.dll</i>, and I have collected some libraries from different sources on the web, you’ll find them under <i>Shams.Web.UI.WebControls.dll</i>. The sample application is in <code nd="77">Shams.MVC.WebApp</code> namespace. All you need is to open <i>Shams.MVC.WebApp</i> solution and you are ready to go. And verify the virtual path in the file “<i>Shams.MVC.WebApp.csproj.webinfo</i>” to be created in the IIS. Here is the one for it:</p><pre lang="text" nd="78">&lt;VisualStudioUNCWeb&gt;

&lt;Web URLPath = "http://localhost/shams/MVC/WebApp/Shams.MVC.WebApp.csproj" /&gt;

&lt;/VisualStudioUNCWeb&gt;</pre><p><img height="595" alt="image037.png" src="http://www.codeproject.com/aspnet/ModelViewController/image037.png" width="530" /></p><p nd="79">Here are some code snippets, from the application, starting with the <i>web.config</i>. The <code nd="80">AppSettings</code> section in the <i>web.config</i> file would contain two things for this application, the connection string for the NorthWind <code nd="81">DataTable</code>, and the path to the <code nd="82">MasterPageUserControl</code>.</p><p nd="83">Here is how it does look like:</p><pre lang="xml" nd="84">&lt;appSettings&gt;
  &lt;add key="MasterPageUserControl" value="MasterPageUserControl.ascx"/&gt;
  &lt;add key="ConnectString001" 
       value="server=localhost;database=northwind;Integrated Security=true;"/&gt;
  &lt;add key="ConnectString002" 
       value="Provider=SQLOLEDB;server=localhost;database=northwind;
                                        Integrated Security=true;"/&gt;
&lt;/appSettings&gt;</pre><p nd="85">The model is the <code nd="86">DataAccessGateway</code> class and it returns the <code nd="87">DataSet</code> that’s been used in the Master-Details data grid controls. Here is how it looks like:</p><p><img height="597" alt="image039.png" src="http://www.codeproject.com/aspnet/ModelViewController/image039.png" width="600" /></p><p nd="88">It uses the <code nd="89">MsSqlDataLinkAdapter</code> that is a wrapper around <b>ADO.NET</b> connection and command objects. This is a singleton class, with all of its functions being static. Here is the skeleton of this class:</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image041_big.png" target="_blank"><img height="500" alt="image041.png" src="http://www.codeproject.com/aspnet/ModelViewController/image041.png" width="600" /></a></p><p nd="90">In our particular scenario, <code nd="91">DataAccessGateway</code> uses this class, to connect to the MS-SQL NorthWind database, by calling the <code nd="92">Connect(.)</code> function of it. Once you have this connection object, you call another function <code nd="93">FilldataSet(.)</code> to return you a brand-new dataset being used for data-binding. Once it is done, you call <code nd="94">Disconnect(.)</code> to close the connection object.</p><p nd="95">Other notable classes are the controller classes, <code nd="96">UcMasterDetails</code> (Main-Controller) and two other classes, <code nd="97">UcMainContentsMaster</code> (Master Controller) and <code nd="98">UcMainContentsDetails</code> (Details Controller). Here is how we connected these two classes with each other using <code nd="99">UcMasterDetails</code> as a mediator.</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image043_big.png" target="_blank"><img height="443" alt="image043.png" src="http://www.codeproject.com/aspnet/ModelViewController/image043.png" width="600" /></a></p><p nd="100">And finally! Here is how the application would look like when you run it. :)</p><p><a href="http://www.codeproject.com/aspnet/ModelViewController/image045_big.png" target="_blank"><img height="347" alt="image045.png" src="http://www.codeproject.com/aspnet/ModelViewController/image045.png" width="600" /></a></p><p nd="101">The MVC pattern I used in the application is the minimal use of it, but it’s the best pattern being used in all the navigations between pages and between controls. It also depends on how you plot a plan for your application in making a prototype application. So folks, that’s it for now, I have tried to un-cover everything about the MVC design pattern, with some useful applications for its implementation. This is one of the most commonly used and misunderstood pattern. I tried to make it simple and give you all the details it carries, along with the robustness analysis, that’s the key in analyzing such applications.</p><h4>Improvement:</h4><p nd="102">There is always a point of improvement in any system, and the same here is applicable too. I haven’t talked about any efficiency related stuff, because that itself needs a full article. So, I am putting this responsibility on you to go through the documentation for improving efficiency of ASP.NET applications, like Caching, View-State Management and Session Management, and How to avoid round-trips to the server, like post-backs etc. And I would appreciate if you involve me in your findings, thank you very much.</p><h2>Question-Answers Session:</h2></div><img src ="http://www.cnitblog.com/seeyeah/aggbug/24312.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-03-20 01:09 <a href="http://www.cnitblog.com/seeyeah/archive/2007/03/20/24312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NHibernate Best Practices with ASP.NET, Generics, and Unit Tests</title><link>http://www.cnitblog.com/seeyeah/archive/2007/03/20/24310.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 19 Mar 2007 17:04:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/03/20/24310.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/24310.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/03/20/24310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/24310.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/24310.html</trackback:ping><description><![CDATA[
		<div style="FONT-WEIGHT: bold; FONT-SIZE: 16pt">
				<a href="/Files/seeyeah/NHibernateBestPractices_src.zip">
						<font color="#002c99">NHibernateBestPractices_src.zip</font>
				</a>
				<br />
				<hr />
				<br />NHibernate Best Practices with ASP.NET, Generics, and Unit Tests</div>
		<b>By <a href="http://www.codeproject.com/script/Articles/list_articles.asp?userid=2797038">Billy McCafferty</a></b>. <br /><br /><div style="FONT-SIZE: 12px">This article describes best practices for leveraging the benefits of NHibernate, ASP.NET, Generics, and unit testing together.<br /><br /><h2>Introduction</h2><p nd="1">NHibernate, like other ORM tools, has alleviated the maintenance of thousands of lines of code and stored procedures, thus allowing developers to focus more attention on the core of a project: its domain model and business logic. Even if you automatically generate your ADO.NET data-access layer using a tool such as CodeSmith or LLBLGen Pro (both great tools), NHibernate provides the flexibility in decoupling your business model from your relational model. Your database should be an implementation detail that is defined to support your domain model, not the other way around. As forums quickly fill with heated debates concerning these points, this article will not focus on proving the benefits of using an ORM tool over ADO.NET, or NHibernate over another ORM tool, but on describing best practices for integrating NHibernate into ASP.NET using well established design patterns and "lessons learned from the field".</p><p nd="2">This article assumes a good understanding of C# and NHibernate, experience with the <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#" target="_blank" itxtdid="3265785">Data</a> Access Object pattern, and at least a basic familiarity with Generics. If you're just getting acquainted with NHibernate, I'd recommend reading these two great introductions at TheServerSide.net: <a href="http://www.theserverside.net/articles/showarticle.tss?id=NHibernate" target="_blank">Part 1</a> and <a href="http://www.theserverside.net/articles/showarticle.tss?id=NHibernateP2" target="_blank">Part 2</a>. For an extensive overview of the <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#" target="_blank" itxtdid="3265786">Data Access</a> Object (DAO) design pattern, go to <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html" target="_blank">J2EE's BluePrints catalog</a>.</p><p nd="3">In building solid data integration within an ASP.NET 2.0 <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp#" target="_blank" itxtdid="3265760">application</a>, we aim to achieve the following objectives:</p><ul><li nd="4">Presentation and business logic layers should be in blissful ignorance of how they communicate with the database. You should be able to modify your means of data communication with minimal modification to these layers. 
</li><li nd="5">Business logic should be easily testable without depending on a live database. 
</li><li nd="6">NHibernate features, such as lazy-loading, should be available throughout the entire page life-cycle. 
</li><li nd="7">.NET 2.0 Generics should be leveraged to alleviate duplicated code. </li></ul><p nd="8">A sample application has been included that demonstrates the merging of NHibernate, ASP.NET, and .NET Generics while meeting the above objectives. What follows is a description of how each of the aforementioned objectives has been tackled in the application. But before getting into the implementation details, let's skip right to the chase and get the sample up and running.</p><h2>The Sample Application</h2><p nd="9">The sample application, at the risk of being terribly cliché, utilizes the Northwind database within SQL Server 2000 to view and update a listing of Northwind customers. To demonstrate the use of lazy-loading, the application also displays the orders that each customer has made. All you need to run the sample locally is IIS with the .NET 2.0 Framework installed, and SQL Server 2000 containing the Northwind database.</p><p nd="10">To get the application up and running:</p><ol><li nd="11">Unzip the sample application to the folder of your choice. 
</li><li nd="12">Open <i>NHibernateSample.Web/web.config</i> and <i>NHibernateSample.Tests/App.config</i> to modify the database connection strings to connect to a Northwind database on SQL Server 2000. 
</li><li nd="13">Create a new virtual directory within IIS. The alias should be <i>NHibernateSample</i>, and the directory should point to the <i>NHibernateSample.Web</i> folder created after unzipping the application. 
</li><li nd="14">Open your web browser to <i>http://localhost/NHibernateSample/ViewCustomers.aspx</i>, and you're off and running! </li></ol><p nd="15">Now that you're able to follow along with the example in front of you, we'll examine how the application was developed to meet our design objectives...</p><h2>Meeting the Design Objectives</h2><p nd="16">When writing an ASP.NET application, my primary goals are:</p><ul><li nd="17">Write code once and only once. (Hey, doesn't that sound like XP?) 
</li><li nd="18">Focus on simplicity and readability. 
</li><li nd="19">Keep coupling and dependencies to a minimum. </li></ul><p nd="20">To assist with keeping logical tiers loosely coupled, the included sample application is split into four projects: Web, Core, Data, and Tests. In peeling the layers of the onion, let's begin with the simple presentation/controller layer and work our way down.</p><h3>NHibernateSample.Web</h3><p nd="21">As expected, the <i>NHibernateSample.Web</i> project contains application configuration and web pages. In this sample, the code-behind pages act as controllers, communicating with the business and data access layers accordingly. Arguably, this is not best-practice MVC separation, but it's simple, and serves well for the demonstration. (I'll leave the thoroughly debated MVC-and-ASP.NET discussion for another day.)</p><p nd="22">Here's a closer look at some of the more interesting bits...</p><h4>Open Session in View</h4><p nd="23">If you want to leverage NHibernate's lazy-loading (which you most definitely will), then the <a href="http://www.hibernate.org/43.html" target="_blank">Open-Session-in-View</a> pattern is the way to go. ("Session" in this context is the NHibernate session...not the ASP.NET "<code nd="24">Session</code>" object.) Essentially, this pattern suggests that one NHibernate session be opened per HTTP request. Although session management within the ASP.NET page life-cycle is clear in theory, it varies widely in available implementation approaches. The approach I've taken is to create a dedicated HTTPModule to handle the details of the pattern. Aside from centralizing session management responsibilities, this approach provides the additional benefit that we may implement the Open-Session-in-View pattern without putting any session management code into our code-behind pages.</p><p nd="25">To see how this has been implemented, take a look at the class <code nd="26">NHibernateSessionModule</code> under the <i>App_Code</i> directory. The following section is included in the <i>web.config</i> to activate the HTTPModule:</p><pre lang="xml" nd="27">&lt;httpModules&gt;
  &lt;add name="NHibernateSessionModule" 
       type="NHibernateSample.Web.NHibernateSessionModule" /&gt;
&lt;/httpModules&gt;</pre><p nd="28">The HTTPModule included in the sample application begins a transaction at the beginning of the web request, and commits/closes it at the end of the request. There's very little overhead associated with this as NHibernate doesn't actually open a database connection until needed. As we'll see, you may switch out this strategy with others exposed by the session manager. Other strategies that you may want to consider are opening a session <i>not</i> associated with a transaction and/or registering an <code nd="29">IInterceptor</code> with the NHibernate session. (Using an <code nd="30">IInterceptor</code> is great for auditing purposes. See <a href="http://www.amazon.com/gp/product/193239415X/102-1170069-1054529?v=glance&amp;n=283155" target="_blank">Hibernate in Action</a>, section 8.3.2 - Audit Logging, for more details.)</p><h4>NHibernate Settings Within web.config</h4><p nd="31">There are two key settings within <i>web.config</i> to optimize NHibernate: <code nd="32">hibernate.connection.isolation</code> and <code nd="33">hibernate.default_schema</code>. By default, NHibernate uses <code nd="34">IsolationLevel.Unspecified</code> as its database isolation level. In other words, NHibernate leaves it up to the ADO.NET provider to determine what the isolation level is by default. If the provider you're using has a default isolation level of <code nd="35">Serializable</code>, this is a very strict level of isolation that can be overkill for most application scenarios. A more reasonable setting to start with is <code nd="36">ReadCommitted</code>. With this setting, "reading transactions" don't block other transactions from accessing a row. However, an uncommitted "writing transaction" blocks all other transactions from accessing the row. Other provider defaults include (note that they are subject to change by version):</p><ul><li nd="37">SQL Server 2000 - Read Committed 
</li><li nd="38">SQL Server 2005 - Read Committed 
</li><li nd="39">Firebird - Read Committed 
</li><li nd="40">MySQL's InnoDB - Repeatable Read 
</li><li nd="41">PostgreSQL - Read Committed 
</li><li nd="42">Oracle - Read Committed </li></ul><p nd="43">The other optional setting not to be ignored, <code nd="44">hibernate.default_schema</code>, is easily overlooked, but can have a significant impact on the querying performance. By default, table names within prepared NHibernate queries - such as those from <code nd="45">CreateCriteria</code> - are not fully qualified; e.g., <i>Customers</i> vs. <i>Northwind.dbo.Customers</i>. The crux of the problem is that <i>sp_execsql</i>, the stored procedure used to execute NHibernate queries, does not efficiently optimize queries unless the table names are fully qualified. Although this is a small syntactic difference, it can slow query speeds by as much as an order of magnitude in some cases. Explicitly setting <code nd="46">hibernate.default_schema</code> can provide as much as a 33% overall performance gain on data intensive pages. The following is an example of declaring these settings in <i>web.config</i>:</p><pre lang="xml" nd="47">&lt;add key="hibernate.connection.isolation" value="ReadCommitted" /&gt;
&lt;add key="hibernate.default_schema" value="Northwind.dbo" /&gt;</pre><p nd="48">In order to decouple the implementation details of data access from the <i>NHibernateSample.Web</i> project, NHibernate session management has been completely separated into the <i>NHibernateSample.Data</i> project. To inform NHibernate where the <i>embedded</i> HBM mapping files reside, define a <i>web.config</i> setting named <code nd="49">HBM_ASSEMBLY</code>. NHibernate will review this assembly for embedded HBM files to load object mappings. (This is not a setting used directly by NHibernate, but by a custom class we'll be reviewing soon.)</p><h4>A Simple List and Update Form</h4><p nd="50">The web project contains two web pages: <i>ViewCustomers.aspx</i> and <i>EditCustomer.aspx</i>. (I'll give you three guesses to figure out what they do.) The important thing to note is that the code-behind pages work with a DAO factory to talk to the database; i.e., the code isn't bound to a concrete implementation of a data access object. This makes it much easier to swap DAO implementations and unit test your code without depending on a live database. With everything in place, the following is an example of how easy it is to retrieve all the customers in the database:</p><pre lang="cs" nd="51">IDaoFactory daoFactory = <span class="cs-keyword" nd="52">new</span> NHibernateDaoFactory();
ICustomerDao customerDao = daoFactory.GetCustomerDao();
IList&lt;Customer&gt; allCustomers = customerDao.GetAll();</pre><p nd="53">In the above example, a concrete reference to <code nd="54">NHibernateDaoFactory</code> is retrieved via <code lang="cs"><span class="cs-keyword" nd="55">new</span></code>. In production code, this reference may (should?) be "injected" at runtime using a technique called Inversion of Control (IoC), or "Dependency Injection". Martin Fowler has written <a href="http://www.martinfowler.com/articles/injection.html" target="_blank">a great introduction to this pattern</a>. Think of it as code decoupling on steroids. With IoC, it's possible to remove many direct instantiations of concrete objects along with the inflexibility that comes along with these dependencies. The many benefits of IoC include a flexible framework, an emphasis on coding-to-interface, and extreme ease of unit testing. The drawback is another layer of complexity within the application. Here are two great tools for putting IoC into practice:</p><ul><li nd="56"><b><a href="http://www.springframework.net/" target="_blank">Spring .NET</a></b>: This framework provides IoC declared via XML configuration files. Spring .NET also has a number of other powerful modules, making it an attractive option if you're looking for more than just IoC. This is the framework I'm currently using for IoC, but it's not the only good choice out there. 
</li><li nd="57"><b><a href="http://www.castleproject.org/index.php/Windsor_Container" target="_blank">Castle Windsor</a></b>: The Castle Windsor Container project provides good IoC support with a combination of configuration and strongly typed declarations. Some of the advantages Castle Windsor brings to the table are less XML and more compile-time error catching. Like Spring .NET, the Castle project also provides a wide assortment of additional development utilities. </li></ul><p nd="58">While it is acceptable to use the <code lang="cs"><span class="cs-keyword" nd="59">new</span></code> keyword to create <code nd="60">NHiberanteDaoFactory</code> within your code-behind, or controller, your business objects should never create this dependency directly. Instead, their DAO dependency should be provided via a public setter or via a constructor. (IoC can help here as well.) This greatly enhances your ability to unit test with "mock" DAO classes. For example, the following code, found within <code nd="61">NHibernateSample.Tests.Data.CustomerDaoTests</code>, retrieves a customer and gives it its DAO dependency:</p><pre lang="cs" nd="62">IDaoFactory daoFactory = <span class="cs-keyword" nd="63">new</span> NHibernateDaoFactory();
ICustomerDao customerDao = daoFactory.GetCustomerDao();

Customer customer = customerDao.GetById(<span class="cpp-string" nd="64">"CHOPS"</span>, <span class="cs-keyword" nd="65">false</span>);
<span class="cs-comment" nd="66">// Give the customer its DAO dependency via a public setter</span>
customer.OrderDao = daoFactory.GetOrderDao();</pre><p nd="67">Using this technique, the business layer never needs to depend directly on the data layer. Instead, it depends on interfaces defined within the same layer, as we'll see next within the <i>NHibernateSample.Core</i> project.</p><h3>NHibernateSample.Core</h3><p nd="68">The <i>NHibernateSample.Core</i> project contains the domain model and NHibernate HBM files. This project also contains interfaces to data access objects in the <code nd="69">NHibernateSample.Core.Data</code> namespace. (Arguably, the HBM files belong in the <i>NHibernateSample.Data</i> project, but the maintenance convenience of having the HBM files physically close to the domain objects they describe far outweighs this break in encapsulation.)</p><h4>Data Dependency Inversion</h4><p nd="70">You'll notice that the <i>NHibernateSample.Core</i> project does not contain implementation details of data access objects, only interfaces describing the services it needs. The concrete DAO classes which implement these interfaces are found within <i>NHibernateSample.Data</i>. This is a technique called <a href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html" target="_blank">Separated Interface</a> by Martin Fowler or "Dependency Inversion" by Robert Martin in <a href="http://www.amazon.com/gp/product/0135974445/ref=pd_lpo_k2a_1_img/102-1170069-1054529?%5Fencoding=UTF8" target="_blank">Agile Software Development</a>. Considering <i>NHibernateSample.Core</i> as an "upper-level layer" and <i>NHibernateSample.Data</i> as a "lower-level layer", then, as Martin describes, "each of the upper-level layers declares an abstract interface for the services that it needs. The lower-level layers are then realized from these abstract interfaces. ... Thus, the upper layers do not depend on the lower layers. Instead, the lower layers depend on abstract service interfaces <i>declared</i> in the upper layers". Dependency inversion is the perfect technique for breaking a bi-directional dependency between domain and data layers.</p><p nd="71">To see this in action, the data interfaces are described in <code nd="72">NHibernateSample.Core.DataInterfaces</code>. <code nd="73">IGenericDao</code> is a generic interface for providing typical data access functionality. <code nd="74">IDaoFactory</code> then acts as an interface for one or more DAO factory classes. Coding to the <code nd="75">IDaoFactory</code> interface allows you to create one concrete DAO factory for production code, and another concrete DAO factory for returning "mock" DAO objects for unit testing purposes. (This is described by the <a href="http://www.dofactory.com/Patterns/PatternAbstract.aspx" target="_blank">abstract factory pattern</a>.) Leveraging <a href="http://www.connextra.com/aboutUs/mockobjects.pdf" target="_blank">mock objects in unit tests</a> provides a means for testing a single responsibility at a time.</p><h4>Generics with NHibernate</h4><p nd="76">By far, one of the greatest benefits that C# 2.0 has brought to the table is the inclusion of generics. With generics, more code reuse can be effectively realized while still enforcing strongly typed coding "contracts". But while the benefits are great, NHibernate has not yet been upgraded to take advantage of this new language feature. (I know they're busy at work doing just that, though.) In the meantime, a solution can be found <a href="http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx" target="_blank">here</a> called - quick, take a guess - <i>NHibernate.Generics</i>. <i>NHibernate.Generics</i> provides generic-typed wrappers for the <code nd="77">IList</code> and <code nd="78">ISet</code> collections that NHibernate currently binds to. I won't spend much time describing the approach, as <a href="http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx" target="_blank">Oren Eini's website</a> will do a much more thorough job of this, but there is one particular note of interest in the code. Within the constructors of the <code nd="79">NHibernateSample.Core.Domain</code> objects, <code nd="80">Customer</code> and <code nd="81">Order</code> are "wire up" code for handling relational scaffolding. The collection wrappers accept two anonymous methods for handling add/remove events from either end of the relationship. So if you remove a child from a parent, the parent automatically gets removed from the child, and vice versa. (Look at <i>NHibernateSample.Tests.CustomerTests</i> to see it work.)</p><pre lang="cs" nd="83"><span class="cs-keyword" nd="82">public</span> Customer() {
    <span class="cs-comment" nd="84">// Implement parent/child relationship add/remove scaffolding</span>
    _orders = <span class="cs-keyword" nd="85">new</span> EntityList&lt;Order&gt;(
        <span class="cs-keyword" nd="86">delegate</span>(Order order) { order.ParentCustomer = <span class="cs-keyword" nd="87">this</span>; },
        <span class="cs-keyword" nd="88">delegate</span>(Order order) { order.ParentCustomer = <span class="cs-keyword" nd="89">null</span>; }
        );
}</pre><p nd="90">In the above example, note that private members encapsulating these relationships must be in the following format: <code nd="91">_camelCase</code>. There are a couple other caveats on the <i>NHiberante.Generics</i> website, but, overall, they're a small price to pay for having support for NHibernate generics. But be sure to keep an eye on <a href="http://www.hibernate.org/343.html" target="_blank">NHibernate's website</a> as an upgrade supporting generics is in the works.</p><h3>NHibernateSample.Data</h3><p nd="92">The <i>NHibernateSample.Data</i> project contains the implementation details for communicating with the database and managing NHibernate sessions.</p><h4>The DAO Factory and Generic DAO</h4><p nd="93">The DAO factory and generic DAO objects I've implemented as <code nd="94">NHibernateDaoFactory</code> and <code nd="95">GenericNHibernateDAO</code>, respectively, are C# ports of the Java versions <a href="http://www.hibernate.org/328.html" target="_blank">described in detail at NHibernate's website</a>. I highly recommend reviewing this article in detail. The most impressive thing to note is that it takes just a few lines of code to create a full-blown DAO object ready for use:</p><ol><li nd="96">Add a new inline implementation and retrieval method for the DAO, to <code nd="97">NHibernateSample.Data.NHibernateDaoFactory</code>. 
</li><li nd="98">Add a new inline interface and retrieval method to <code nd="99">NHibernateSample.Core.DataInterfaces.IDaoFactory</code>. </li></ol><p nd="100">Looking at the <code nd="101">ICustomerDao</code> example already in the sample application, that took about five lines of code...not too bad.</p><h4>Handling the NHibernate Session</h4><p nd="102">Finally, the only remaining question is how are NHibernate sessions managed? Details answering this question may be found in the class <code nd="103">NHibernateSessionManager</code>. Within this class, the basic flow for retrieving a session is as follows:</p><ol><li nd="104">The client code calls <code nd="105">NHibernateSessionManager.Instance.GetSession()</code>. 
</li><li nd="106">If not already instantiated, this singleton object builds the session factory, loading HBM mapping files from the <code nd="107">HBM_ASSEMBLY</code> declared in <i>web.config</i>. (<code nd="108">NHibernateSessionManager</code> is a singleton since building the session factory is very expensive.) 
</li><li nd="110"><code nd="109">GetSession</code> looks to see if a session is already bound to <code nd="111">System.Runtime.Remoting.Messaging.CallContext[<span class="cpp-string" nd="112">"THREAD_SESSION"</span>]</code>. 
</li><li nd="113">If an open NHibernate session is not found, then a new one is opened (and bound to an optional <code nd="114">IInterceptor</code>) and then set to <code nd="115">CallContext[<span class="cpp-string" nd="116">"THREAD_SESSION"</span>]</code>. 
</li><li nd="118"><code nd="117">GetSession</code> then returns the session assigned to <code nd="119">CallContext[<span class="cpp-string" nd="120">"THREAD_SESSION"</span>]</code>. </li></ol><p nd="121">This flow, as well as the rest of <code nd="122">NHibernateSessionManager</code>, follows that closely described in <a href="http://www.amazon.com/gp/product/193239415X/102-1170069-1054529?v=glance&amp;n=283155" target="_blank">Hibernate in Action</a>, chapter 8 - Writing Hibernate Applications.</p><p nd="123">The HTTPModule described in the <i>NHibernateSample.Web</i> project opens a transaction at the beginning of a web request, and commits/closes it at the end of the request. The following is an example of modifying the HTTPModule so that an <code nd="124">IInterceptor</code> gets bound to the session as well as being contained within a transaction:</p><pre lang="cs" nd="127"><span class="cs-keyword" nd="125">public</span><span class="cs-keyword" nd="126">void</span> Init(HttpApplication context) {
    context.BeginRequest += 
          <span class="cs-keyword" nd="128">new</span> EventHandler(InitNHibernateSession);
    ...
}

<span class="cs-keyword" nd="129">private</span><span class="cs-keyword" nd="130">void</span> InitNHibernateSession(<span class="cs-keyword" nd="131">object</span> sender, EventArgs e) {
    IInterceptor myNHibernateInterceptor = ...

    <span class="cs-comment" nd="132">// Bind the interceptor to the session.</span><span class="cs-comment" nd="133">// Using open-session-in-view, an interceptor </span><span class="cs-comment" nd="134">// cannot be bound to an already opened session,</span><span class="cs-comment" nd="135">// so this must be our very first step.</span>
    NHibernateSessionManager.Instance.RegisterInterceptor(myNHibernateInterceptor);

    <span class="cs-comment" nd="136">// Encapsulate the already opened session within a transaction</span>
    NHibernateSessionManager.Instance.BeginTransaction();
}</pre><h3>NHibernateSample.Tests</h3><p>I'll assume you can probably guess what this project is for.</p><h4>Unit Test Performance</h4><p>It's imperative for unit tests to be blazing fast. If a suite of unit tests takes too long to run, developers stop running them - and we want them running unit tests all the time! In fact, if a test takes more than 0.1 second to run, the test is probably too slow. Now, if you've done unit testing in the past, you know that any unit test requiring access to a live database takes much longer than this to run. With <a href="http://www.nunit.org/" target="_blank">NUnit</a>, you can put tests into categories, making it easy to run different groups of tests at a time, thus excluding the tests that connect to a database most of the time. Here's a quick example:</p><pre lang="cs">[TestFixture]
[Category(<span class="cpp-string">"NHibernate Tests"</span>)]
<span class="cs-keyword">public</span><span class="cs-keyword">class</span> SomeTests
{
    [Test]
    <span class="cs-keyword">public</span><span class="cs-keyword">void</span> TestSomethingThatDependsOnDb() { ... }
}</pre><h4>Testing with NHibernate</h4><p>In a previous version of this article, the <code>ISession</code> was stored and retrieved via <code>HttpContext.Current.Items.</code> The problem with this is that it forced you to simulate an HTTP context when running unit tests. It also prevented the framework from being easily ported to a Windows application. Instead, it is recommended that the <code>ISession</code> be stored and retrieved via <code>System.Runtime.Remoting.Messaging.CallContext.</code> (Thanks to Tadeu Camargo da Silva, on the NHibernate forums, and the feedback below for recommending this solution.) Using <code>CallContext</code> provides proper storage of the <code>ISession</code> for Web apps, Windows apps, and unit tests, alike. Take a look at <code>NHibernateSample.Tests.Data.CustomerDaoTests</code> for a unit test that is now "HTTP agnostic." Additionally, as you'll see in the unit test, unless you want data changes made within your tests to be committed to the database, it's a good idea to rollback the transaction.</p><h4>Testing with NHibernate "Mocked"</h4><p>Unless you're specifically testing DAO classes, you usually don't want to run unit tests that are dependent on a live database. They're slow and volatile by nature; i.e., if the data changes, the tests break. When testing business logic, unit tests shouldn't break if data changes. But the major obstacle is that business objects themselves may depend on DAOs. Using the abstract factory pattern that we've put into place, we can inject mock DAOs into the business objects, thereby simulating communications with the database. An example is included in <i>NHibernateSample.Tests.Domain.CustomerTests</i>. The following snippet creates the mock DAO and gives it to the <code>Customer</code> object via a public setter. Since the setter only expects an object implementing the <code>IOrderDao</code> interface, the mock object can easily replace all of the live-database behavior.</p><pre lang="cs">Customer customer = <span class="cs-keyword">new</span> Customer(<span class="cpp-string">"Acme Anvils"</span>);
customer.ID = <span class="cpp-string">"ACME"</span>;
customer.OrderDao = <span class="cs-keyword">new</span> MockOrderDao();</pre><p>Unfortunately, more often than not, you're maintaining legacy code that has no semblance of the ideal "code-to-interface" that allows for such flexibility. Usually, there are many explicit dependencies to concrete objects, and it is difficult to replace data-access objects with mock objects to simulate database communications. In these situations, your options are to either refactor the legacy code to fit within a test harness, or to use an object mocking tool such as <a href="http://www.typemock.com/" target="_blank">TypeMock</a>. With TypeMock, it is even possible to mock sealed and singleton classes - an impressive feat to pull off without such a tool. Albeit powerful, TypeMock is best left alone unless absolutely needed; using TypeMock prematurely makes it tempting to not always code to interface. The more appropriate course to take when working with legacy code - time and budget permitting - is to refactor the code for greater flexibility. <a href="http://www.amazon.com/gp/product/0131177052/102-1170069-1054529?v=glance&amp;n=283155" target="_blank">Working Effectively with Legacy Code</a> by Michael Feathers is full of great ideas for refactoring legacy code into a test harness.</p><h2>Putting it into Practice</h2><p>The sample application provides a strong data-layer foundation for building scalable web applications up to the enterprise level. (Almost all of the techniques also fit well for building Windows Forms applications.) But before using it within your own environment, I would recommend the following:</p><ul><li>Place <code>NHibernateSample.Core.DataInterfaces.IGenericDAO</code>, <code>NHibernateSample.Data.GenericNHibernateDAO</code>, and <code>NHibernateSample.Data.NHibernateSessionManager</code> into a reusable class library as they would be transferable between applications with no code modifications whatsoever. 
</li><li>Select an IoC provider to inject DAO dependencies into your page controllers. 
</li><li>Finally, I would ignore how I've setup my ASPX code-behind logic - it can quickly create monolithic code-behind pages; instead, I would consider using patterns such as <a href="http://www.martinfowler.com/eaaDev/ModelViewPresenter.html" target="_blank">Model-View-Presenter</a> (my personal favorite), <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesPageController.asp" target="_blank">Page Controller</a>, <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesFrontController.asp" target="_blank">Front Controller</a>, or other MVC-like approaches. But again, that's for a completely different discussion altogether! </li></ul><p>I hope this article has helped with putting best practices into place for leveraging the benefits of ASP.NET, NHibernate, and Generics. I'm currently having great success with this approach on my projects, and look forward to hearing your experiences as well. Please let me know if you have any questions or suggestions.<br /><br /></p></div><img src ="http://www.cnitblog.com/seeyeah/aggbug/24310.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-03-20 01:04 <a href="http://www.cnitblog.com/seeyeah/archive/2007/03/20/24310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Paging of Large Resultsets in ASP.NET</title><link>http://www.cnitblog.com/seeyeah/archive/2007/01/11/21754.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 10 Jan 2007 16:24:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/01/11/21754.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/21754.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/01/11/21754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/21754.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/21754.html</trackback:ping><description><![CDATA[
		<div style="FONT-SIZE: 12px">
				<strong>By </strong>
				<a href="http://www.codeproject.com/script/Articles/list_articles.asp?userid=1071675">
						<strong>Jasmin Muharemovic</strong>
				</a>. <br /><br />An article about optimization and performance testing of MS SQL Server 2000 stored procedures used for paging of large resultsets in ASP.NET<br /><br /><ul class="download"><li><a href="http://www.codeproject.com/aspnet/PagingLarge/PagingTest.zip">Download PagingTest Solution (C#) - 55.8 Kb </a></li><li><a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_Procedures.zip">Download Paging_Procedures SQL script - 2.48 Kb </a></li><li><a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_LargeTable.zip">Download Paging_LargeTable SQL script - 0.6 Kb </a></li></ul><h2>Introduction</h2><p nd="1">The paging of a large database resultset in Web applications is a well known problem. In short, you don't want all the results from your query to be displayed on a single Web page, so some sort of paged display is more appropriate. While it was not an easy task in the old ASP, the <code nd="2">DataGrid</code> control in the ASP.NET simplifies this to a few lines of code. So, the paging is easy in ASP.NET, but the default behavior of the <code nd="3">DataGrid</code> is that all resulting records from your query will be fetched from SQL server to the ASP.NET application. If your query returns a million records this will cause some serious <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/PagingLarge.asp#" target="_blank" itxtdid="3162690">performance</a> issues (if you need convincing, try executing such a query in your web application and see the memory consumption of the aspnet_wp.exe in the task manager). That's why a custom paging solution is required where desired behavior is to fetch only the rows from the current page. </p><p nd="4">There are numerous articles and posts concerning this problem and several proposed solutions. My goal here is not to present you with an amazing solves-it-all procedure, but to optimize all the existing methods and provide you with a testing application so you can do evaluation on your own. Here is a good starting point article which describes many different approaches and provides some performance test results: <br /><br /><a href="http://www.aspfaq.com/show.asp?id=2120">How do I page through a recordset?</a><br /><br />I was not satisfied with the most of them. First, half of the methods use old ADO and are clearly written for the "old" ASP. The rest of the methods are SQL server stored procedures. Some of them yield poor response times as you can see from the author’s performance results at the bottom of the page, but several have caught my attention. </p><h2>Generalization</h2><p nd="5">The three methods I decided to closely look into are the ones the author calls <code nd="6">TempTable</code>, <code nd="7">DynamicSQL</code> and <code nd="8">Rowcount</code>. I'll refer to the second method as the <code nd="9">Asc-Desc</code> method in the rest of this text. I don't think <i>DynamicSQL</i> was a good name, because you can apply dynamic SQL logic to the other methods too. The general problem with all these stored procedures is that you have to assess which columns you'll allow sorting for and that won't probably be just the PK column(s). This leads to a new set of problems – for each query you want to display via paging you must have as many different paging queries as you have different sorting columns. This means that you will either have a different stored procedure (regardless of the paging method applied) for each sorting column or you'll try to generalize this to only one stored procedure with the help of dynamic SQL. This has a slight performance impact, but increases maintainability if you need to display many different queries using this approach. Thus, I’ll try to generalize all of the stored procedures in this text with dynamic SQL, but in some cases it will be possible to achieve only a certain level of generalization, so you’ll still have to write separate stored procedures for some complex queries. </p><p nd="10">The second problem with allowing other sorting columns beside the PK column(s) is that if those columns are not indexed in some way, none of these methods will help. In all of them a paged source must be sorted first and the cost of using ordering by non-indexed column is immense for large tables. The response times are so high that all the procedures are practically unusable in this case (the response varies from couple of seconds to couple of minutes depending on the size of the tables and the starting record being fetched). The indexing of other columns brings more performance issues and may be undesirable, for example it might significantly slow you down in a situation where you have a lot of daily imports. </p><h2>TempTable</h2><p nd="11">The first one I would comment on is the <code nd="12">TempTable</code> method. This is actually a widely proposed solution and I encountered it several times. Here is another article that describes it along with the explanation and a sample how to use custom paging with the <code nd="13">DataGrid</code>: <br /><br /><a href="http://www.dotnetjunkies.com/Tutorial/EA868776-D71E-448A-BC23-B64B871F967F.dcik">ASP.NET DataGrid Paging Part 2 - Custom Paging</a><br /><br />The methods in both articles could be optimized with just the Primary Key data copied to the temp table and then doing the join with the main query. Therefore, the essence of this method would be the following </p><pre lang="sql" nd="16"><span class="vb-function" nd="14">CREATE</span><span class="vb-function" nd="15">TABLE</span> #Temp (
    ID <span class="cpp-keyword">int</span><span class="vb-function" nd="17">IDENTITY</span><span class="vb-function" nd="18">PRIMARY</span><span class="vb-function" nd="19">KEY</span>,
    PK  /* here goes PK type */
)

<span class="vb-function" nd="20">INSERT</span><span class="vb-function" nd="21">INTO</span> #Temp <span class="vb-function" nd="22">SELECT</span> PK <span class="vb-function" nd="23">FROM</span> Table <span class="vb-function" nd="24">ORDER</span><span class="vb-function" nd="25">BY</span> SortColumn

<span class="vb-function" nd="26">SELECT</span> ... <span class="vb-function" nd="27">FROM</span> Table <span class="vb-function" nd="28">JOIN</span> #Temp temp <span class="vb-function" nd="29">ON</span> Table.PK = temp.PK <span class="vb-function" nd="30">ORDER</span><span class="vb-function" nd="31">BY</span> temp.ID <br /><span class="vb-function" nd="32">WHERE</span> ID &gt; @StartRow <span class="vb-function" nd="33">AND</span> ID &lt; @EndRow
</pre>The method can be optimized further by copying the rows to the temp table until the end paging row is reached (<code nd="35">SELECT TOP EndRow...</code>), but the point is that in the worst case – for a table with 1 million records you end up with 1 million records in a temp table as well.  Considering all this and having looked upon the results in the article above, I decided to discard this method from my tests. 
<h2>Asc-Desc</h2><p nd="36">This method uses default ordering in a subquery and then applies the reverse ordering. The principle goes like this </p><pre lang="sql" nd="38"><span class="vb-function" nd="37">DECLARE</span> @temp <span class="vb-function" nd="39">TABLE</span> (
    PK  /* PK Type */ <span class="vb-function" nd="40">NOT</span><span class="vb-function" nd="41">NULL</span><span class="vb-function" nd="42">PRIMARY</span> 
)

<span class="vb-function" nd="43">INSERT</span><span class="vb-function" nd="44">INTO</span> @temp 
<span class="vb-function" nd="45">SELECT</span> TOP @PageSize PK <span class="vb-function" nd="46">FROM</span> (
    <span class="vb-function" nd="47">SELECT</span> TOP (@StartRow + @PageSize) 
    PK, 
    SortColumn /*If sorting column <span class="vb-function" nd="48">is</span> defferent <span class="vb-function" nd="49">from</span> the PK, SortColumn must <br />                 be fetched as well, otherwise just the PK <span class="vb-function" nd="50">is</span> necessary */ 
    <span class="vb-function" nd="51">ORDER</span><span class="vb-function" nd="52">BY</span> SortColumn /* default <span class="vb-function" nd="53">order</span> – typically ASC */) 
<span class="vb-function" nd="54">ORDER</span><span class="vb-function" nd="55">BY</span> SortColumn /* reversed default <span class="vb-function" nd="56">order</span> – typically DESC */

<span class="vb-function" nd="57">SELECT</span> ... <span class="vb-function" nd="58">FROM</span> Table <span class="vb-function" nd="59">JOIN</span> @Temp temp <span class="vb-function" nd="60">ON</span> Table.PK = temp.PK <br /><span class="vb-function" nd="61">ORDER</span><span class="vb-function" nd="62">BY</span> SortColumn /* default <span class="vb-function" nd="63">order</span> */</pre>Full Code – <a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_Asc_Desc.zip">Paging_Asc_Desc</a><br /><h2>RowCount</h2><p nd="64">The base logic of this method relies on the SQL <code nd="65">SET ROWCOUNT</code> expression to both skip the unwanted rows and fetch the desired ones: </p><pre lang="sql" nd="67"><span class="vb-function" nd="66">DECLARE</span> @Sort /* the type of the sorting column */
<span class="vb-function" nd="68">SET</span> ROWCOUNT @StartRow
<span class="vb-function" nd="69">SELECT</span> @Sort = SortColumn <span class="vb-function" nd="70">FROM</span> Table <span class="vb-function" nd="71">ORDER</span><span class="vb-function" nd="72">BY</span> SortColumn
<span class="vb-function" nd="73">SET</span> ROWCOUNT @PageSize
<span class="vb-function" nd="74">SELECT</span> ... <span class="vb-function" nd="75">FROM</span> Table <span class="vb-function" nd="76">WHERE</span> SortColumn &gt;= @Sort <span class="vb-function" nd="77">ORDER</span><span class="vb-function" nd="78">BY</span> SortColumn</pre>Full Code – <a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_RowCount.zip">Paging_RowCount</a><br /><h2>SubQuery</h2><p nd="79">There are 2 more methods I’ve taken into consideration, and they come from different resources. The first one is well known triple query or the <code nd="80">SubQuery</code> method. The most thorough approach is the one I’ve found in the following article <br /><br /><a href="http://www.winnetmag.com/Article/ArticleID/40505/40505.html">Server-Side Paging with SQL Server</a><br /><br />Although you'll need to be subscribed, a .zip file with the <code nd="81">SubQuery</code> stored procedure variations is available. The <i>Listing_04.SELECT_WITH_PAGINGStoredProcedure.txt</i> file contains the complete generalized dynamic SQL. I used a similar generalization logic with all other stored procedures in this text. Here is the principle followed by the link to the whole procedure (I shortened the original code a bit, because a recordcount portion was unnecessary for my testing purposes). </p><pre lang="sql" nd="83"><span class="vb-function" nd="82">SELECT</span> ... <span class="vb-function" nd="84">FROM</span> Table <span class="vb-function" nd="85">WHERE</span> PK IN 
    (<span class="vb-function" nd="86">SELECT</span> TOP @PageSize PK <span class="vb-function" nd="87">FROM</span> Table <span class="vb-function" nd="88">WHERE</span> PK <span class="vb-function" nd="89">NOT</span> IN
        (<span class="vb-function" nd="90">SELECT</span> TOP @StartRow PK <span class="vb-function" nd="91">FROM</span> Table <span class="vb-function" nd="92">ORDER</span><span class="vb-function" nd="93">BY</span> SortColumn)
    <span class="vb-function" nd="94">ORDER</span><span class="vb-function" nd="95">BY</span> SortColumn)
<span class="vb-function" nd="96">ORDER</span><span class="vb-function" nd="97">BY</span> SortColumn</pre>Full Code – <a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_SubQuery.zip">Paging_SubQuery</a><br /><h2>Cursor</h2><p nd="98">I’ve found the last method while browsing through the Google groups, you can find the original thread <a href="http://groups.google.com/groups?hl=en&amp;lr=&amp;ie=UTF-8&amp;oe=UTF-8&amp;threadm=OzkQuI9%24CHA.2328%40TK2MSFTNGP10.phx.gbl&amp;rnum=5&amp;prev=/groups%3Fhl%3Dbg%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26selm%3DOzkQuI9%2524CHA.2328%2540TK2MSFTNGP10.phx.gbl%26rnum%3D5">here</a>. This method uses a server-side dynamic cursor. A lot of people tend to avoid cursors, they usually have poor performance because of their non-relational, sequential nature. The thing is that paging IS a sequential task and whatever method you use you have to somehow reach the starting row. In all the previous methods this is done by selecting all rows preceding the starting row plus the desired rows and then discarding all the preceding rows. Dynamic cursor has the <code nd="99">FETCH RELATIVE</code> option which does the “magic” jump. The base logic goes like this </p><pre lang="sql" nd="101"><span class="vb-function" nd="100">DECLARE</span> @PK /* PK Type */
<span class="vb-function" nd="102">DECLARE</span> @tblPK <span class="vb-function" nd="103">TABLE</span> (
    PK /* PK Type */ <span class="vb-function" nd="104">NOT</span><span class="vb-function" nd="105">NULL</span><span class="vb-function" nd="106">PRIMARY</span><span class="vb-function" nd="107">KEY</span>
)

<span class="vb-function" nd="108">DECLARE</span> PagingCursor CURSOR DYNAMIC READ_ONLY FOR
<span class="vb-function" nd="109">SELECT</span> @PK <span class="vb-function" nd="110">FROM</span> Table <span class="vb-function" nd="111">ORDER</span><span class="vb-function" nd="112">BY</span> SortColumn

OPEN PagingCursor
FETCH RELATIVE @StartRow <span class="vb-function" nd="113">FROM</span> PagingCursor <span class="vb-function" nd="114">INTO</span> @PK

<span class="vb-function" nd="115">WHILE</span> @PageSize &gt; <span class="vb-literal" nd="116">0</span><span class="vb-function" nd="117">AND</span> @@FETCH_STATUS = <span class="vb-literal" nd="118">0</span><span class="vb-function" nd="119">BEGIN</span><span class="vb-function" nd="120">INSERT</span> @tblPK(PK) VALUES(@PK)
    FETCH NEXT <span class="vb-function" nd="121">FROM</span> PagingCursor <span class="vb-function" nd="122">INTO</span> @PK
    <span class="vb-function" nd="123">SET</span> @PageSize = @PageSize - <span class="vb-literal" nd="124">1</span><span class="vb-function" nd="125">END</span>

CLOSE PagingCursor
DEALLOCATE PagingCursor

<span class="vb-function" nd="126">SELECT</span> ... <span class="vb-function" nd="127">FROM</span> Table <span class="vb-function" nd="128">JOIN</span> @tblPK temp <span class="vb-function" nd="129">ON</span> Table.PK = temp.PK <br /><span class="vb-function" nd="130">ORDER</span><span class="vb-function" nd="131">BY</span> SortColumn</pre>Full Code – <a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_Cursor.zip">Paging_Cursor</a><br /><h2>Generalization of Complex Queries</h2><p nd="132">As pointed out before, all the procedures are generalized with dynamic SQL, thus, in theory, they can work with any kind of complex query. Here is a complex query sample that works with <code nd="133">Northwind</code> database. </p><div class="precollapse" id="premain5" style="WIDTH: 100%"><img id="preimg5" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="5" /><span id="precollapse5" style="MARGIN-BOTTOM: 0px; CURSOR: hand" nd="134" preid="5"> Collapse</span></div><pre lang="sql" id="pre5" style="MARGIN-TOP: 0px"><span class="vb-function">SELECT</span> Customers.ContactName <span class="vb-function">AS</span> Customer, 
       Customers.Address + ', ' + Customers.City + ', ' + <br />                                                Customers.Country <span class="vb-function">AS</span> Address, 
       SUM([Order Details].UnitPrice*[Order Details].Quantity) <span class="vb-function">AS</span><br />                                                          [Total <span class="cpp-keyword">money</span> spent] 
<span class="vb-function">FROM</span> Customers
<span class="vb-function">INNER</span><span class="vb-function">JOIN</span> Orders <span class="vb-function">ON</span> Customers.CustomerID = Orders.CustomerID
<span class="vb-function">INNER</span><span class="vb-function">JOIN</span> [Order Details] <span class="vb-function">ON</span> Orders.OrderID = [Order Details].OrderID
<span class="vb-function">WHERE</span> Customers.Country &lt;&gt; 'USA' <span class="vb-function">AND</span> Customers.Country &lt;&gt; 'Mexico'
<span class="vb-function">GROUP</span><span class="vb-function">BY</span> Customers.ContactName, Customers.Address, Customers.City, <br />         Customers.Country 
<span class="vb-function">HAVING</span> (SUM([Order Details].UnitPrice*[Order Details].Quantity))&gt;<span class="vb-literal">1000</span><span class="vb-function">ORDER</span><span class="vb-function">BY</span> Customer DESC, Address DESC</pre>The paging stored procedure call that returns the second page looks like this 
<div class="precollapse" id="premain6" style="WIDTH: 100%"><img id="preimg6" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="6" /><span id="precollapse6" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="6"> Collapse</span></div><pre lang="sql" id="pre6" style="MARGIN-TOP: 0px">EXEC ProcedureName
/* Tables */
'Customers
<span class="vb-function">INNER</span><span class="vb-function">JOIN</span> Orders <span class="vb-function">ON</span> Customers.CustomerID = Orders.CustomerID
<span class="vb-function">INNER</span><span class="vb-function">JOIN</span> [Order Details] <span class="vb-function">ON</span> Orders.OrderID = [Order Details].OrderID',
/* PK */
'Customers.CustomerID',
/* <span class="vb-function">ORDER</span><span class="vb-function">BY</span> */
'Customers.ContactName DESC, Customers.Address DESC',
/* PageNumber */
<span class="vb-literal">2</span>,
/* Page Size */
<span class="vb-literal">10</span>,
/* Fields */
'Customers.ContactName <span class="vb-function">AS</span> Customer,
Customers.Address + '', '' + Customers.City + '', '' + Customers.Country <br /><span class="vb-function">AS</span> Address, 
SUM([Order Details].UnitPrice*[Order Details].Quantity) <span class="vb-function">AS</span> [Total <span class="cpp-keyword">money</span> spent]',
/* Filter */
'Customers.Country &lt;&gt; ''USA'' <span class="vb-function">AND</span> Customers.Country &lt;&gt; ''Mexico''',
/*Group By*/
'Customers.CustomerID, Customers.ContactName, Customers.Address, <br /> Customers.City, Customers.Country 
<span class="vb-function">HAVING</span> (SUM([Order Details].UnitPrice*[Order Details].Quantity))&gt;<span class="vb-literal">1000</span>'</pre><p>Note that in the original query, aliases are used in the <code>ORDER BY</code> clause. You can't do that in paging procedures, because the most time-consuming task in all of them is skipping rows preceding the starting row. This is done in various ways, but the principle is not to fetch all the required fields at first, but only the PK column(s) (in case of <code>RowCount</code> method the sorting column), which speeds up this task. All required fields are fetched only for the rows that belong to the requested page. Therefore, field aliases don't exist until the final query, and sorting columns have to be used earlier (in row skipping queries). </p><p>The <code>RowCount</code> procedure has another problem, it is generalized to work with only one column in the <code>ORDER BY</code> clause. The same goes for <code>Asc-Desc</code> and <code>Cursor</code> methods, though they can work with several ordering columns, but require that only one column is included in the PK. I guess this could be solved with more dynamic SQL, but in my opinion it is not worth the fuss. Although these situations are highly possible, they are not that frequent. Even if they are, you can always write a separate paging procedure following the principles above. </p><h2>Performance Testing</h2><p>I used these 4 methods in my tests, if you have a better one, I’d be glad to know about it. Nevertheless, I wanted to compare these methods and measure their performance. The first thought was to write an ASP.NET test application with paged DataGrid and then measure page response. Still, this wouldn’t reflect the true response time of the stored procedures, so the console application seemed more appropriate. I also included a web application, not for performance testing, but rather as an example of how DataGrid custom paging works with these stored procedures. They are both incorporated in the <a href="http://www.codeproject.com/aspnet/PagingLarge/PagingTest.zip">PagingTest Solution</a>.</p><p>I used the auto generated large table for my tests and inserted around 500 000 records in it. If you don’t have a large table to experiment on, you can download the script for a table design and stored procedure for data generation <a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_LargeTable.zip">here</a>. I didn't want an identity column for my PK, I used the <code>uniqueidentifier</code> instead. If you'll use this script, you may consider to add an identity after you generate the table. It will add numbers sorted by PK and you'll have an indication that correct page is fetched when you call a paging procedure with PK sorting. </p><p>The idea behind performance testing was to call a specific stored procedure many times through a loop and then measure the average response time. Also, in order to remove caching deviations and to model the real situation more accurately – multiple calls to a stored proc with the same page fetched each time seemed inappropriate. Thus, a random sequence of the same stored procedure with a set of different page numbers was required. Of course, a set of different page numbers assumes fixed number of pages (10 – 20) where each page would be fetched many times, but in a random sequence.</p><p>It’s not hard to notice that response times depend on the distance of the fetched page from the beginning of the resultset. The further the starting record is, more records need to be skipped. This is the reason I didn’t include first 20 pages in my random sequence. Instead I used the set of 2<sup>N</sup> pages. A loop was set to a (number of different pages)*1000. So, every page was fetched around 1000 times (more or less because of a random distribution). </p><h2>Results</h2>Here are the results I've got - <a href="http://www.codeproject.com/aspnet/PagingLarge/Paging_Results.zip">Paging_Results (MS Excell file)</a><br /><img alt="" src="http://www.codeproject.com/aspnet/PagingLarge/Paging_pk.gif" /><br /><img alt="" src="http://www.codeproject.com/aspnet/PagingLarge/Paging_pk-lower.gif" /><br /><img alt="" src="http://www.codeproject.com/aspnet/PagingLarge/Paging_indexed.gif" /><br /><img alt="" src="http://www.codeproject.com/aspnet/PagingLarge/Paging_indexed-lower.gif" /><br /><img alt="" src="http://www.codeproject.com/aspnet/PagingLarge/Paging_overall.gif" /><h2>Conclusion</h2><p>The methods performed in the following order, starting from the best one - <code>RowCount</code>, <code>Cursor</code>, <code>Asc-Desc</code> and <code>Subquery</code>. The behavior in the lower portion was especially interesting, because in many real situations you'll browse beyond the first five pages rarely, so the <code>Subquery</code> method might satisfy your needs in those cases. It all depends on the size of your resultset and the prediction how frequently will the distant pages be fetched. You might use the combination of methods as well. As for myself, I decided to use the <code>RowCount</code> method wherever possible. It beaves quite nice, even for the first page. The <i>"wherever possible"</i> part stands for some cases where it's hard to generalize this method, then I would use the <code>Cursor</code> (possibly combined with the <code>SubQuery</code> for the first couple of pages). </p><h2>Update 2004-05-05</h2><p>The main reason I wrote this article was the feedback from the vast programming community. In a couple of weeks I'll be starting work on a new project. The preliminary analysis showed that there's going to be a couple of very large tables involved. These tables will be used in many complex joined queries and their results will be displayed in the ASP.NET application (with sorting and paging enabled). That's why I invested some time in research and pursue for the best paging method. It wasn't just the performance that interested me, but also the usability and maintainability. 
</p><p>Now the invested time has started to pay off already. You can find a post by C. v. Berkel below (many thanks) in which he found a flaw in the <code>RowCount</code> method. It won't work correctly if the sorting column is not unique. The <code>RowCount</code> method performed the best in my tests, but now I am seriously considering not using it at all. In most cases sorting columns (besides the PK) won't be unique. This leaves me with the <code>Cursor</code> method as the fastest and applicable to most situations. It can be combined with the <code>SubQuery</code> method for the first couple of pages and possibly with the <code>RowCount</code> method for unique sorting columns. 
</p><p>Another thing which may be worth mentioning is that there's a tiny flaw in the <code>Asc-Desc</code> method as well. It always returns the <code>PageSize</code> number of records for the last page and not the actual number (which may be lower than the <code>PageSize</code>). The correct number can be calculated but since I don't intend to use this procedure (because of how it performed), I didn't want to improve it any further. </p><!-- Article Ends --><script src="/script/togglePre.js" type="text/javascript"></script></div>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/21754.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-01-11 00:24 <a href="http://www.cnitblog.com/seeyeah/archive/2007/01/11/21754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Office编程在dot Net环境中总结(Excel篇) </title><link>http://www.cnitblog.com/seeyeah/archive/2007/01/11/21753.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 10 Jan 2007 16:23:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/01/11/21753.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/21753.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/01/11/21753.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/21753.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/21753.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 文章的使用范围																										   												运行环境						 .net Framework 1.1 ,Excel 2003																										   												开发语言：						C#												...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2007/01/11/21753.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/21753.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-01-11 00:23 <a href="http://www.cnitblog.com/seeyeah/archive/2007/01/11/21753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#封装的DES与MD5加密示例代码</title><link>http://www.cnitblog.com/seeyeah/archive/2007/01/04/21472.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 03 Jan 2007 16:10:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2007/01/04/21472.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/21472.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2007/01/04/21472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/21472.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/21472.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: using				 System;				using				 System.IO;				using				 System.Text;				using				 System.Security.Cryptography;				namespace				 TestWeb.App_Code																								{   ...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2007/01/04/21472.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/21472.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-01-04 00:10 <a href="http://www.cnitblog.com/seeyeah/archive/2007/01/04/21472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#中的接口 </title><link>http://www.cnitblog.com/seeyeah/archive/2006/12/03/19872.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 02 Dec 2006 16:54:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2006/12/03/19872.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/19872.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2006/12/03/19872.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/19872.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/19872.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#ff0000">From <a href="http://zhenyulu.cnblogs.com">http://zhenyulu.cnblogs.com</a><br /><hr /><br />本文中所有图示纯为个人理解（参考了Assembly中元数据的存储方式），与真实情况可能有所出入。 图中绿色表示公有方法，红色表示私有方法。</font>
		</p>
		<p>本文将通过以下四个案例来分析C#中的接口究竟是如何工作的。</p>
		<h3>1、公有方法实现接口方法</h3>
		<p>尽管C#在定义接口时不用指明接口方法的访问控制方式，但默认接口方法均为public型（这可以从反编译的IL代码中看到）。下面是使用Reflector查看的接口IL代码</p>
		<pre>.class private interface abstract auto ansi IControl
{
   .method <b>public</b> hidebysig newslot abstract virtual instance void Paint() cil managed
   {
   }
}
</pre>
		<p>实现接口的类需要实现所有接口方法。通常情况下，接口的实现方法也为public型。如下案例：</p>
		<pre>using System ;
interface IControl 
{
   void Paint();
}
public class EditBox: IControl 
{
   <b>public</b> void Paint() 
   {
      Console.WriteLine("Pain method is called!");
   }
}
class Test 
{
   static void Main() 
   {
      EditBox editbox = new EditBox(); 
      <b>editbox.Paint();</b>
      <b>((IControl)editbox).Paint();</b>
   }
}</pre>
		<p>程序的执行结果为：</p>
		<pre>Pain method is called!
Pain method is called!</pre>
		<p>接口就好像是关系型数据库中的一对多表，一个接口对应多个接口方法，每个接口方法又对应虚拟方法表（VMT）中的某个公有或私有方法。上面代码在内存中的镜像可由下图描述：</p>
		<p>
				<img height="103" src="http://zhenyulu.cnblogs.com/images/cnblogs_com/zhenyulu/200508/Pic034.gif" width="507" border="0" />
		</p>
		<p>从图中我们可以看到直接对Paint方法的调用以及通过接口对Paint方法的调用。可见通过接口对方法进行调用需要多出一道转换工作，因此执行效率不如直接调用。</p>
		<h3>2、私有方法不能实现接口方法</h3>
		<p>如果想将接口方法直接实现为私有方法是办不到的。下面的EditBox的代码中Paint方法没有特殊说明，默认为private，导致代码无法执行：</p>
		<pre>using System ;
interface IControl 
{
   void Paint();
}
public class EditBox: IControl 
{
   <b>void Paint()</b> 
   {
      Console.WriteLine("Pain method is called!");
   }
   <b>public void ShowPaint()</b>
   {
      this.Paint();
      <b>((IControl)this).Paint();</b>
   }
}
class Test 
{
   static void Main() 
   {
      EditBox editbox = new EditBox(); 
      editbox.ShowPaint();
   }
}</pre>
		<p>程序在编译时将显示如下编译错误：““EditBox”不会实现接口成员“IControl.Paint()”。“EditBox.Paint()”或者是静态、非公共的，或者有错误的返回类型。”</p>
		<p>为什么会这样呢？如图：</p>
		<p>
				<img height="156" src="http://zhenyulu.cnblogs.com/images/cnblogs_com/zhenyulu/200508/Pic035.gif" width="493" border="0" />
		</p>
		<p>这是由于接口规范中的方法默认的访问权限是public，而类中的默认访问权限是default，也就是说private，因此导致权限范围收缩，两者权限并不相同，所以必须将类的权限调整为public才可以使上面的代码得以执行。 </p>
		<h3>3、实现专门的接口方法（1）</h3>
		<p>代码如下：</p>
		<pre>using System ;
interface IControl 
{
   void Paint();
}
public class EditBox: IControl 
{
   <b>void Paint() </b>
   {
      Console.WriteLine("Pain method is called!");
   }
   <b>void IControl.Paint()</b> 
   {
      Console.WriteLine("IControl.Pain method is called!");
   }
   public void ShowPaint()
   {
      this.Paint();
      ((IControl)this).Paint();
   }
}
class Test 
{
   static void Main() 
   {
      EditBox editbox = new EditBox(); 
      editbox.ShowPaint();
      <b>//editbox.Paint();</b>
      <b>((IControl)editbox).Paint();</b>
   }
}</pre>
		<p>EditBox类拥有一私有Paint方法，但这并不是接口方法的实现（上例已经分析过）。EditBox类中还包含了一“void IControl.Paint()”方法， 是该方法复写了接口的Paint方法，该方法是私有的（通过IL代码可以看出）。</p>
		<p>注意：“void IControl.Paint()”前不能加任何的修饰限定符号，诸如public、private等，这在C#的语法中是不允许的。该方法反编译得到的IL代码如下：</p>
		<pre>.class public auto ansi beforefieldinit EditBox
      extends object
      implements IControl
{
      .......
      .method <b>private</b> hidebysig newslot virtual final instance void IControl.Paint() cil managed
      {
            <b>.override IControl::Paint</b>
      }
}</pre>
		<p>程序运行时内存中的镜像可简化表示为：</p>
		<p>
				<img height="215" src="http://zhenyulu.cnblogs.com/images/cnblogs_com/zhenyulu/200508/Pic036.gif" width="518" border="0" />
		</p>
		<p>程序执行结果如下：</p>
		<pre>Pain method is called!
IControl.Pain method is called!
IControl.Pain method is called!</pre>
		<p>我们之所以可以通过<code><font color="#000099">((IControl)editbox).Paint()</font></code>方法访问到代码是因为接口方法Paint是公有的。但是我们不能通过<code><font color="#000099">editbox.Paint()</font></code>方法访问到代码是因为EditBox的Paint方法是私有的。 在EditBox内部，通过ShowPaint方法可以同时访问私有的Paint方法与接口<code><font color="#000099">IControl.Paint</font></code>方法。</p>
		<h3>4、实现专门的接口方法（2）</h3>
		<p>如果EditBox中的Pait方法为公有并且同时提供了IControl.Paint方法，程序将是如何运行的呢？代码如下：</p>
		<pre>using System ;
interface IControl 
{
   void Paint();
}
public class EditBox: IControl 
{
   <b>public void Paint() </b>
   {
      Console.WriteLine("Pain method is called!");
   }
   <b>void IControl.Paint() </b>
   {
      Console.WriteLine("IControl.Pain method is called!");
   }
}
class Test 
{
   static void Main() 
   {
      EditBox editbox = new EditBox(); 
      <b>editbox.Paint();</b>
      <b>((IControl)editbox).Paint();</b>
   }
}</pre>
		<p>程序执行结果如下：</p>
		<pre>Pain method is called!
IControl.Pain method is called!</pre>
		<p>程序执行时内存布局如下：</p>
		<p>
				<img height="119" src="http://zhenyulu.cnblogs.com/images/cnblogs_com/zhenyulu/200508/Pic037.gif" width="513" border="0" />
		</p>
		<p>可见，EditBox中公有的Paint方法并不是接口实现方法，真正的接口实现方法是IControl.Paint，这将导致<code><font color="#000099">editbox.Paint()</font></code>方法与<code><font color="#000099">((IControl)editbox).Paint()</font></code>的执行结果并不一样。</p>
		<h3>5、结论</h3>
		<p>接口方法的实现通常是通过类中的公有方法实现的；</p>
		<p>在一些特殊情况下（代码隐藏、一个类实现的两个接口具有相同的接口方法等），需要专门实现某个接口的方法。</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/19872.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> 2006-12-03 00:54 <a href="http://www.cnitblog.com/seeyeah/archive/2006/12/03/19872.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Working with Data in ASP.NET 2.0 :: Efficiently Paging Through Large Amounts of Data</title><link>http://www.cnitblog.com/seeyeah/archive/2006/11/26/19602.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 25 Nov 2006 17:20:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2006/11/26/19602.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/19602.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2006/11/26/19602.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/19602.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/19602.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Download the code for this sample | Download this tutorial in PDF format						Introduction				As we discussed in the preceding tutorial, paging can be implemented in one of two ways:						...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2006/11/26/19602.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/19602.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> 2006-11-26 01:20 <a href="http://www.cnitblog.com/seeyeah/archive/2006/11/26/19602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Working with Data in ASP.NET 2.0 :: Creating a Data Access Layer</title><link>http://www.cnitblog.com/seeyeah/archive/2006/11/26/19601.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 25 Nov 2006 17:13:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2006/11/26/19601.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/19601.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2006/11/26/19601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/19601.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/19601.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Download the code for this sample				 | Download this tutorial in PDF format		Introduction		As web developers, our lives revolve around working with data. We create databases to store the data, ...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2006/11/26/19601.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/19601.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> 2006-11-26 01:13 <a href="http://www.cnitblog.com/seeyeah/archive/2006/11/26/19601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>