<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_道法自然</title><subtitle type="text">为程序员提供免费开放的插件仓库和规范的OSGi.NET插件框架！欢迎访问开放工厂http://www.iOpenWorks.com。</subtitle><id>http://feed.cnblogs.com/blog/u/24881/rss</id><updated>2012-05-24T09:34:29Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/24881/rss"/><entry><id>http://www.cnblogs.com/baihmpgy/archive/2012/05/24/2516697.html</id><title type="text">发布一个免费漂亮的仿Outlook风格、支持换肤的通用界面框架</title><summary type="text">这个通用界面框架是基于OSGi.NET插件框架来做的，先看一下运行效果。 换个皮肤试试看！ 这个界面框架是OSGi.NET面向服务插件平台的一个通用的界面插件，OSGi.NET面向服务插件框架是一个支持WinForm、Web、WPF、Silverlight，甚至是移动应用的插件平台，提供动态插件化与模块化、面向服务和插件扩展三大功能。这个界面框架插件利用OSGi.NET的扩展功能暴露了左边的导航栏和右边显示区域的扩展点，允许新开发的插件通过注册扩展的方式将自定义的界面功能注册到这个节目框架。我们来看一个使用示例，在这个示例里，我们新建了一个联系人插件。这个联系人插件通过Manife...</summary><published>2012-05-24T08:21:00Z</published><updated>2012-05-24T08:21:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2012/05/24/2516697.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2012/05/24/2516697.html"/><content type="html">&lt;p&gt;这个通用界面框架是基于OSGi.NET插件框架来做的，先看一下运行效果。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201205/201205241621097316.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Restart" border="0" alt="Restart" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201205/20120524162109871.png" width="416" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;换个皮肤试试看！&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201205/201205241621103281.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201205/20120524162111150.png" width="427" height="297" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;这个界面框架是OSGi.NET面向服务插件平台的一个通用的界面插件，OSGi.NET面向服务插件框架是一个支持WinForm、Web、WPF、Silverlight，甚至是移动应用的插件平台，提供动态插件化与模块化、面向服务和插件扩展三大功能。这个界面框架插件利用OSGi.NET的扩展功能暴露了左边的导航栏和右边显示区域的扩展点，允许新开发的插件通过注册扩展的方式将自定义的界面功能注册到这个节目框架。我们来看一个使用示例，在这个示例里，我们新建了一个联系人插件。这个联系人插件通过Manifest.xml这个插件配置文件的Extension节点定义了对界面框架的扩展。如下所示。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #FF00FF;"&gt;xml&amp;nbsp;version="1.0"&amp;nbsp;encoding="utf-8"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;?&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Bundle&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="urn:uiosp-bundle-manifest-2.0"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Name&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;SymbolicName&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Version&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="1.0.0.0"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;InitializedState&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Active"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Activator&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Type&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin.Activator"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Policy&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Immediate"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Runtime&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Assembly&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Path&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="bin\ContactsPlugin.dll"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Share&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="false"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Dependency&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;BundleSymbolicName&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="UIShell.DbManagerService"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Resolution&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Mandatory"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Runtime&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;定义界面功能的扩展，将自定义的两个窗体注册到界面框架&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;--&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Extension&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Point&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="UIShell.Applications"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Application&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Title&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;ToolTip&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Icon&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin.Resources.shell.png"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Menu&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Text&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Create&amp;nbsp;Contact"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;ToolTip&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Create&amp;nbsp;a&amp;nbsp;contact"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Icon&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin.Resources.shell.png"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Class&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin.CreateContactForm"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Menu&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Text&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="View&amp;nbsp;Contacts"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;ToolTip&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="View&amp;nbsp;all&amp;nbsp;contacts"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Icon&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin.Resources.shell.png"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;Class&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="ContactsPlugin.ContactsForm"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Application&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Extension&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color: #008000; "&gt;&amp;nbsp;定义一个数据源，从而来使用轻量级ORM数据访问服务&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;--&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Extension&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Point&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="UIShell.DataSources"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;DataSource&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Default"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ConnectionString&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="data&amp;nbsp;source='{BundleLocation}\App_Data\Contact.sdf';"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProviderName&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Microsoft.SqlServerCe.Client.3.5"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Description&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Contact&amp;nbsp;data&amp;nbsp;source."&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Extension&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Bundle&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;运行插件项目后，你可以发现这个联系人管理应用便显示在左边的导航区域，一旦点击导航菜单，便在右边显示了注册的窗体。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201205/201205241621118481.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201205/201205241621121413.png" width="568" height="394" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;有关界面框架的使用，你可以访问：&lt;a href="http://www.iopenworks.com/Products/ProductDetails/Introduction?proID=8"&gt;http://www.iopenworks.com/Products/ProductDetails/Introduction?proID=8&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;有关联系人插件的介绍、开发教程、源码和部署文件，你可以访问：&lt;a href="http://www.iopenworks.com/Products/ProductDetails/Introduction?proID=20"&gt;http://www.iopenworks.com/Products/ProductDetails/Introduction?proID=20&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;如果有更多疑问，可以加入QQ交流群：121369588。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2516697.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2012/05/24/2516697.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html</id><title type="text">分享Web应用运行的细节问题：预编译提高网站性能、跟踪用户习惯和解决线程同步</title><summary type="text">在这个文章里，我将分享一下在iOpenWorks.com这个网站试运行中碰到的若干问题和解决方案，这些问题包含了：（1）如何通过ASP.NET MVC预编译提高性能；（2）如何知道网站在运行中，用户响应速度、网站异常信息、用户操作习惯；（3）解决与DiscuzToolkit集成的线程同步问题。1 ASP.NET MVC 3预编译支持提高网站性能，除了我们常见的压缩、CDN、缓存之外，还有一个就是使用预编译。不管是ASP.NET WebForm，或者是ASP.NET MVC，这些页面在网站运行过程中，都是要先经过编译处理的。因此，如果能在网站运行前对其进行编译，那无疑能更好的提高网站的响应速度。</summary><published>2012-04-09T04:08:00Z</published><updated>2012-04-09T04:08:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html"/><content type="html">&lt;p&gt;在这个文章里，我将分享一下在iOpenWorks.com这个网站试运行中碰到的若干问题和解决方案，这些问题包含了：（1）如何通过ASP.NET MVC预编译提高性能；（2）如何知道网站在运行中，用户响应速度、网站异常信息、用户操作习惯；（3）解决与DiscuzToolkit集成的线程同步问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="First"&gt;1 ASP.NET MVC 3预编译支持&lt;/p&gt;&lt;p&gt;提高网站性能，除了我们常见的压缩、CDN、缓存之外，还有一个就是使用预编译。不管是ASP.NET WebForm，或者是ASP.NET MVC，这些页面在网站运行过程中，都是要先经过编译处理的。因此，如果能在网站运行前对其进行编译，那无疑能更好的提高网站的响应速度。因此，我们选择了一个RazorGenerator来对所有的ASP.NET MVC 3的视图进行编译，这样，在部署时仅需要将dll文件拷贝过去，而不再需要cshtml文件了。下面介绍如何使用它来实现预编译。&lt;/p&gt;&lt;p class="Second"&gt;1.1 下载安装RazorGenerator&lt;/p&gt;&lt;p&gt;你可以在&lt;a href="http://razorgenerator.codeplex.com/"&gt;http://razorgenerator.codeplex.com/&lt;/a&gt;下载到RazorGenerator，这是一个VS 2010的扩展。下载完成后，就可以直接安装了。接着你还需要下载源代码，然后编译一下，获取编译的RazorGenerator.Mvc.dll程序集。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="Second"&gt;1.2 改变视图文件的生成方式&lt;/p&gt;&lt;p&gt;将所有的视图的BuildAction改成None，并且将CustomTool改成RazorGenerator，这时候，你可以看到一个关联的.generated.cs文件，这个文件就是预编译的源码文件了。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207387599.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207391579.png" width="484" height="286" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p class="Second"&gt;1.3 处理Helper&lt;/p&gt;&lt;p&gt;对于Helpr文件，处理方式有所不同。Helper文件一般放在App_Code文件夹里面。首先，你需要在Helper文件的第一行添加 @* Generator: MvcHelper *@ 来声明一下，接着将BuildAction改成None，并且将CustomTool改成RazorGenerator&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207441366.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/20120409120746329.png" width="501" height="296" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;下面，还需要额外一个步骤，这个非常重要，否则编译无法通过，那就是需要将.generated.cs文件的BuildAction由Content改为Compile。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207517292.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/20120409120753126.png" width="496" height="293" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="Second"&gt;1.4 注册PrecompiledMvcEngine&lt;/p&gt;&lt;p&gt;下面我们在ASP.NET MVC 3项目中引用RazorGenerator.Mvc.dll这个程序集，然后定义一个PreApplicationStartCode，并在AssemblyInfo.cs文件中注册这个PreApplicationStartCode。这样，我们就注册了PrecompiledMvcEngine了。&lt;/p&gt;&lt;p&gt;（1）在AssemblyInfo.cs注册&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;[assembly:&amp;nbsp;PreApplicationStartMethod(&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;(UIShell.iOpenWorks.PreApplicationStartCode),&amp;nbsp;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;PreStart&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)]&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;（2）PreApplicationStartCode定义&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;namespace&lt;/span&gt;&amp;nbsp;UIShell.iOpenWorks&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&amp;nbsp;PreApplicationStartCode&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&amp;nbsp;_isStarting;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;PreStart()&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(!_isStarting)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_isStarting&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;true&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;engine&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;PrecompiledMvcEngine(&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;(PreApplicationStartCode).Assembly);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ViewEngines.Engines.Add(engine);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="Second"&gt;1.5 部署&lt;/p&gt;&lt;p&gt;这时候，部署网站就不再需要将视图文件部署过去了，只需要拷贝dll文件和网站资源。注意，在Views下面已经没有.cshtml文件了，也没有App_Code文件，因为它们都被预编译到了UIShell.iOpenWorks.dll这个程序集了。接下来，你就可以测试一下网站，享受一下预编译带来的性能提升了。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/20120409120753965.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207533440.png" width="244" height="151" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207542818.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207551356.png" width="244" height="163" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="First"&gt;2 跟踪网站运行情况&lt;/p&gt;&lt;p&gt;网站在内测期间，会碰到较多的问题。但是，这时候，用户已经进来测试，你怎么能够及时发现用户响应速度、用户访问过程中网站异常信息以及用户是如何来使用你的网站。这里，我们使用了log4net这个日志组件，它用于记录：（1）用户访问了哪些页面；（2）用户在访问页面过程中，碰到了哪些异常；（3）每一个页面的响应速度。下面，我来介绍如何记录这些信息的。&lt;/p&gt;&lt;p class="Second"&gt;2.1 在Global中，跟踪每个用户访问的页面，并且要记录用户响应的速度&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;[ThreadStatic]&amp;nbsp;&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;Stopwatch&amp;nbsp;_stopwatch;&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;Application_BeginRequest()&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_stopwatch&amp;nbsp;=&amp;nbsp;Stopwatch.StartNew();&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;计时开始&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(DiscuzHelper.IsLoggedIn())&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;记录当前用户&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&amp;nbsp;user&amp;nbsp;=&amp;nbsp;DiscuzHelper.LoggedUser();&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;(user&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ThreadContext.Properties[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;user&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;user.UserName;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;&amp;nbsp;(Exception&amp;nbsp;ex)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.Error(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Failed&amp;nbsp;to&amp;nbsp;get&amp;nbsp;the&amp;nbsp;user&amp;nbsp;name&amp;nbsp;though&amp;nbsp;the&amp;nbsp;user&amp;nbsp;is&amp;nbsp;logged&amp;nbsp;in.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;ex);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ThreadContext.Properties[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;user&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(Request&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;记录当前用户的IP&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ThreadContext.Properties[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ipaddress&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;Request.ServerVariables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;REMOTE_ADDR&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;];&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ThreadContext.Properties[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ipaddress&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;]&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.Empty;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;Application_EndRequest()&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(Request&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;_stopwatch&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;_logger&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;)&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;计时结束，就用户响应时间和访问页面&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_stopwatch.Stop();&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.Debug(&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accessed&amp;nbsp;page&amp;nbsp;'Response&amp;nbsp;time:&amp;nbsp;{0}&amp;nbsp;ms,&amp;nbsp;Url:&amp;nbsp;{1}'.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;_stopwatch.ElapsedMilliseconds,&amp;nbsp;Request.Url));&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="Second"&gt;2.2 在Global中，记录系统的异常&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;Application_Error(Object&amp;nbsp;sender,&amp;nbsp;EventArgs&amp;nbsp;ea)&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(Server&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Exception&amp;nbsp;e;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;for&lt;/span&gt;&amp;nbsp;(e&amp;nbsp;=&amp;nbsp;Server.GetLastError();&amp;nbsp;e&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;;&amp;nbsp;e&amp;nbsp;=&amp;nbsp;e.InnerException)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_logger.Error(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Unhandled&amp;nbsp;server&amp;nbsp;exception&amp;nbsp;thrown.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;e);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="Second"&gt;2.3 处理关键方法&lt;/p&gt;&lt;p&gt;下面，我还在关键方法记录了用户的操作异常信息、响应速度。比如我必须记录了：（1）用户注册时响应速度、注册时发生的异常、用户登录时响应速度、用户登录时发生的异常；（2）用户在什么情况下尝试下载iOpenWorksSDK这个免费插件框架；（3）尝试下载时，会转到注册页面，这时候用户是否继续注册并下载，还是放弃。&lt;/p&gt;&lt;p&gt;对这些关键方法的记录，有助于提高应用系统的易用性。通过日志，我们修复了与Discuz集成的很多问题，并且提高了用户响应速度。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="Second"&gt;2.4 日志分析&lt;/p&gt;&lt;p&gt;下面，我们需要来看一下日志分析，这里我们在一个开源的LogViewer自定义了一下。通过对日志的分析，你就可以知道系统发生了什么异常、系统性能如何、用户操作习惯、关键方法的信息。当然，你也可以打开日志文件直接查看，只是，那样比较费劲。对了，在这里我们绝不记录用户的密码，这太不职业道德了，此外，所有密码都是加密的，避免&amp;#8220;CSDN&amp;#8221;！&lt;/p&gt;&lt;p&gt;（1）查看异常信息&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091207591974.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091208009649.png" width="414" height="235" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;（2）查看关键方法信息：用户访问习惯、响应性能等&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091208049494.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201204/201204091208058315.png" width="414" height="238" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="First"&gt;3 解决DiscuzToolkit线程同步&lt;/p&gt;&lt;p&gt;网站的社区是与Discuz集成的，我们就用了DiscuzToolkit来集成。这是官方发布的类库，但是依然问题一堆。最严重的2个问题就是线程同步引起的，可见Discuz这帮人对ASP.NET多线程模型压根没有当一回事，或者连线程安全都没有注意到。下面就说一下碰到的2个线程安全问题。&lt;/p&gt;&lt;p&gt;（1）在注册用户时，碰到以下异常：当前会话所提交的call_id没有大于前一次的call_id&lt;/p&gt;Failed to get the user name though the user is logged in.&lt;br/&gt;Discuz.Toolkit.DiscuzException: Code: 103, Message: 当前会话所提交的call_id没有大于前一次的call_id&lt;br/&gt;at Discuz.Toolkit.Util.GetResponse[T](String method_name, DiscuzParam[] parameters) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\Util.cs:line 97&lt;br/&gt;at Discuz.Toolkit.DiscuzSession.GetUserInfo(Int64[] uids, String[] fields) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\DiscuzSession.cs:line 224&lt;br/&gt;at Discuz.Toolkit.DiscuzSession.GetUserInfo(Int64 uid) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\DiscuzSession.cs:line 255&lt;p&gt;这个问题是由Discuz.Toolkit.Util的Sign方法引起的，在这里，它为每一个API请求生成一个call_id。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;list.Add(DiscuzParam.Create(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;call_id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;DateTime.Now.Ticks));&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果你在当前线程API调用太勤快的话，DateTime.Now.Ticks会生成一样的值，从而引发异常。因此，官方提议可以Sleep一下。因此，我们就需要改成如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;list.Add(DiscuzParam.Create(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;call_id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;DateTime.Now.Ticks));&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Avoid&amp;nbsp;to&amp;nbsp;generate&amp;nbsp;same&amp;nbsp;'call_id'&amp;nbsp;and&amp;nbsp;throws&amp;nbsp;an&amp;nbsp;exception&amp;nbsp;on&amp;nbsp;'当前会话所提交的call_id没有大于前一次的call_id'.&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Thread.Sleep(&lt;span style="color: #800080;"&gt;50&lt;/span&gt;);&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;但是这样，依然是不行的，这个异常只是变得更加诡异了，让你碰到机会少一点而已。你别忘了ASP.NET应用程序是多线程的，当两个线程同时访问时，依然可能获得同一个call_id，于是，在碰到若干次这个问题后，我用以下方法来修复。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;lock&lt;/span&gt;&amp;nbsp;(_syncRoot)&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list.Add(DiscuzParam.Create(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;call_id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;DateTime.Now.Ticks));&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Avoid&amp;nbsp;to&amp;nbsp;generate&amp;nbsp;same&amp;nbsp;'call_id'&amp;nbsp;and&amp;nbsp;throws&amp;nbsp;an&amp;nbsp;exception&amp;nbsp;on&amp;nbsp;'当前会话所提交的call_id没有大于前一次的call_id'.&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Thread.Sleep(&lt;span style="color: #800080;"&gt;50&lt;/span&gt;);&amp;nbsp;&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;（2）注册用户时，碰到以下异常：An item with the same key has already been added. &lt;/p&gt;[2012-04-07 17:11:30,818] [7] [ERROR] [AccountController] [49.72.46.135] []: System.ArgumentException: An item with the same key has already been added.&lt;br/&gt;at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)&lt;br/&gt;at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)&lt;br/&gt;at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)&lt;br/&gt;at Discuz.Toolkit.Util.GetSerializer(Type t) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\Util.cs:line 157&lt;br/&gt;at Discuz.Toolkit.Util.GetResponse[T](String method_name, DiscuzParam[] parameters) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\Util.cs:line 88&lt;br/&gt;at Discuz.Toolkit.DiscuzSession.GetUserID(String username) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\DiscuzToolkit\DiscuzSession.cs:line 243&lt;br/&gt;at UIShell.iOpenWorks.Controllers.AccountController.Register(DiscuzNewUser newUser, String returnUrl) in E:\Work\Design\Core\milestore 1\osgi\m10\uishell.iopenworks\UIShell.iOpenWorks\Controllers\AccountController.cs:line 53&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;你想想，要是用户注册时，动不动碰到注册不成功，是多么窝火！！所以，我根据日志再次调查发现，DiscuzToolkit在使用静态变量保存数据时，竟然不加锁，太不拿Thread-Safe当回事了。这会异常也发生在Util类里，代码如下，其中serializer_dict是静态全局变量。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;serializer_dict.Add(type_hash,&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;XmlSerializer(t));&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;于是，我修改如下。这样，彻底解决了和Discuz的集成了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;,&amp;nbsp;XmlSerializer&amp;gt;&amp;nbsp;serializer_dict&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;Dictionary&amp;lt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;,&amp;nbsp;XmlSerializer&amp;gt;();&amp;nbsp;&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;ReaderWriterLock&amp;nbsp;_lock&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;ReaderWriterLock();&amp;nbsp;&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;XmlSerializer&amp;nbsp;GetSerializer(Type&amp;nbsp;t)&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&amp;nbsp;type_hash&amp;nbsp;=&amp;nbsp;t.GetHashCode();&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&amp;nbsp;timeout&amp;nbsp;=&amp;nbsp;&lt;span style="color: #800080;"&gt;5000&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_lock.AcquireReaderLock(timeout);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(!serializer_dict.ContainsKey(type_hash))&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_lock.UpgradeToWriterLock(timeout);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(!serializer_dict.ContainsKey(type_hash))&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;serializer_dict.Add(type_hash,&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;XmlSerializer(t));&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&amp;nbsp;serializer_dict[type_hash];&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;&amp;nbsp;(ApplicationException&amp;nbsp;ex)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;Exception(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accquire&amp;nbsp;lock&amp;nbsp;failed.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&amp;nbsp;ex);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;finally&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(_lock.IsReaderLockHeld)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_lock.ReleaseReaderLock();&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(_lock.IsWriterLockHeld)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_lock.ReleaseWriterLock();&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;OK，关于网站试运行中，最重要的几点分享描述完了。顺道介绍一下什么是iOpenWorks.com。iOpenWorks.com是一个免费开放的插件仓库，旨在向开发人员提供完全免费的标准化的OSGi.NET面向服务插件框架以及共享的插件仓库，这样，你既可以从插件仓库使用别人插件，也可以共享自己的插件，互利共赢！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;你也可以加入iOpenWorks交流群：121369588，Thanks。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2438720.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2012/03/20/2408040.html</id><title type="text">[代码健壮性] 学会同时关注代码的正面和反面情况，提高系统健壮性</title><summary type="text">健壮的程序并不是没有异常，而是能够处理异常和定位异常！去年给客户咨询的时候，客户提出一个非常有趣的问题：他们做的一个应用系统经常动不动就挂掉，而且最主要的是，挂掉后无法找出问题的原因。后面查看代码时，发现用户在编写代码中，出现了类似以下的代码。1IPageFlowServicepageFlowService=2bundleRuntime.GetFirstOrDefaultService&lt;IPageFlowService&gt;();3//Redirecttofirstnode.4Response.Redirect(pageFlowService.FirstPageNodeValue);这</summary><published>2012-03-20T07:47:00Z</published><updated>2012-03-20T07:47:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2012/03/20/2408040.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2012/03/20/2408040.html"/><content type="html">&lt;div&gt;&lt;strong&gt;健壮的程序并不是没有异常，而是能够处理异常和定位异常！&lt;/strong&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;去年给客户咨询的时候，客户提出一个非常有趣的问题：他们做的一个应用系统经常动不动就挂掉，而且最主要的是，挂掉后无法找出问题的原因。&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;后面查看代码时，发现用户在编写代码中，出现了类似以下的代码。&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;IPageFlowService&amp;nbsp;pageFlowService&amp;nbsp;=&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bundleRuntime.GetFirstOrDefaultService&amp;lt;IPageFlowService&amp;gt;();&lt;br /&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Redirect&amp;nbsp;to&amp;nbsp;first&amp;nbsp;node.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;Response.Redirect(pageFlowService.FirstPageNodeValue);&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;这段代码在正常情况下，没有任何问题，也一定能够通过正常的功能测试。但是，用户思维和程序员不同，因此，稀奇古怪的问题都是有可能的。可以这么说，在用户这里，&amp;#8220;Nothing is impossible！&amp;#8221;，：）。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;那我来说明一下，这段代码可能出现的问题。&lt;/div&gt;&lt;div&gt;（1）&lt;span style="white-space:pre"&gt;&lt;/span&gt;有可能pageFlowService没有获取到，这时程序会抛出NullReferenceException；&lt;/div&gt;&lt;div&gt;（2）&lt;span style="white-space:pre"&gt;&lt;/span&gt;pageFlowService.FirstPageNodeValue有可能为空，这时候程序也会抛出NullReferenceException。&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;当以上任意一种情况出现时，系统都将崩溃，或许有的程序员已经注意到可能出现NullReferenceException异常，于是将程序更改成如下。&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;IPageFlowService&amp;nbsp;pageFlowService&amp;nbsp;=&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bundleRuntime.GetFirstOrDefaultService&amp;lt;IPageFlowService&amp;gt;();&lt;br /&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Redirect&amp;nbsp;to&amp;nbsp;first&amp;nbsp;node.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;(pageFlowService&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.IsNullOrEmpty(pageFlowService.FirstPageNodeValue))&lt;br /&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;&amp;nbsp;Response.Redirect(pageFlowService.FirstPageNodeValue);&lt;br /&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;这段代码出现NullReferenceException的几率几乎为零了，也就意味着上面的程序在运行过程中不会再出现异常情况了。似乎是健壮很多了。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;不过，恰恰相反，这次更加悲剧了，因为一旦pageFlowService为null，或者pageFlowService.FirstPageNodeValue为空时，则上面的程序不会出现任何的异常，但是却使得系统出现问题时，我们很难定位出到底哪出错了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;因此，正确的做法，应该是对于反面情况，我们的程序也必须处理，并且需要抛出良好的异常信息，如下所示。&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Get&amp;nbsp;PageFlowService.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;IPageFlowService&amp;nbsp;pageFlowService&amp;nbsp;=&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BundleRuntime.Instance.GetFirstOrDefaultService&amp;lt;IPageFlowService&amp;gt;();&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(pageFlowService&amp;nbsp;==&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;ServiceNotAvailableException(&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;(IPageFlowService).FullName,&amp;nbsp;Properties.Resources.IOpenWorksWebShellName);&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.IsNullOrEmpty(pageFlowService.FirstPageNodeValue))&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;{&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;PageNodeException(Properties.Resources.CanNotFindAnAvailablePageNode);&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Redirect&amp;nbsp;to&amp;nbsp;first&amp;nbsp;node.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;Response.Redirect(pageFlowService.FirstPageNodeValue);&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;在上述代码中，如果pageFlowService为null，则抛出一个ServiceNotAvailableException，来描述服务不存在的异常，保证异常情况出现时，我们就可以快速判断问题的根源；在pageFlowService.FirstPageNodeValue为空时，抛出PageNodeException。这样，当异常出现时，我们就可以很快的定位出问题了。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;在上面的例子中，你也可以引入断言达到相同的效果。这里，我仅是做一个例子来描述而已。&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;为了提供系统的健壮性，我们在写程序时，必须同时关注提供的正面行为和反面行为，并给出不同的处理方法！ 要学会习惯性的处理异常情况！！&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;以下是一点点建议，欢迎补充。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;1 不要吞掉异常情况，要学会习惯处理异常情况，即要考虑正面和负面情况&lt;/div&gt;&lt;div&gt;绝对不要吞掉异常情况，虽然这样子写程序很省事，但是，一旦问题出现了，也让你很麻烦。吞掉异常的情况一般有：&lt;/div&gt;&lt;div&gt;（1）使用try&amp;#8230;catch&amp;#8230;，然后不做任何异常处理，这种情况下，所有异常都被忽视掉了，对于写代码来说是非常省事，但是问题出现后，压根无法找到那出错了。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Ignore&amp;nbsp;the&amp;nbsp;exceptions&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;（2）使用try&amp;#8230;catch，只是笼统处理，这里处理方式要好于第一种，但是程序并没有根据捕捉的不同异常类型而给出不同处理方法，虽然能够定位大概原因，但是无法精确，因此这个方法还是存在问题。&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;(Exception&amp;nbsp;ex)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Show&amp;nbsp;the&amp;nbsp;ex.Message&amp;nbsp;here.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;（3）只处理正面条件，这种方法和（1）情况类似，当然动机不一样，在这种情况下，写程序时是做了程序正常的假设，而不考虑异常。&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;(pageFlowService&amp;nbsp;!=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.IsNullOrEmpty(pageFlowService.FirstPageNodeValue))&lt;br /&gt;{&lt;br /&gt;Response.Redirect(pageFlowService.FirstPageNodeValue);&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;2 引入日志&lt;/div&gt;&lt;div&gt;这里日志，最好不要使用Log.Message/Error(sting message)的处理方法，因为这样的日志并没有办法准确描述是在那个线程、那个类、那个方法产生的结果。因此，我提倡直接使用log4net的日志。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;3 程序进行模块化分解&lt;/div&gt;&lt;div&gt;这种方法可以把依赖限制在一个功能模块里面，因此，异常的范围也可以进一步限制起来，从而有助于更好的定位问题的根源。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;欢迎大家多多补充。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2408040.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2012/03/20/2408040.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/09/27/2192437.html</id><title type="text">专业的程序员需要具备的思考能力：写一个程序需要注意多少细节问题</title><summary type="text">我曾经听过一个老师对一个做的不错的程序员的一句评论：“某某某做程序确实很快，但就是都不能用”。事实上，直到今日，我们中很多人仍然在写这样的程序。不能用的程序一般都有几个特征，比如当程序出现问题时，总是不知道该怎么处理，甚至是在正常情况下都会出现问题，但归根结底就是压根就没有认真从用户的角度来考虑用户到底怎么来使用。如果用户输入了程序接受的输入，那么必然该给出正确的结果，可悲剧的是，就是有那么多的意外，因为客户行为总是在很多程序员意料之外，因此，当用户执行了某个程序员认为是非常规的操作的话，运行结果可能是用户无法得到任何问题的解释，然后用户下定一个结论就是：“这是一个什么破软件，真没用！”。 .</summary><published>2011-09-26T16:07:00Z</published><updated>2011-09-26T16:07:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/09/27/2192437.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/09/27/2192437.html"/><content type="html">&lt;p&gt;我曾经听过一个老师对一个做的不错的程序员的一句评论：&amp;#8220;某某某做程序确实很快，但就是都不能用&amp;#8221;。事实上，直到今日，我们中很多人仍然在写这样的程序。不能用的程序一般都有几个特征，比如当程序出现问题时，总是不知道该怎么处理，甚至是在正常情况下都会出现问题，但归根结底就是压根就没有&lt;strong&gt;&lt;font size="5"&gt;认真&lt;/font&gt;&lt;/strong&gt;从&lt;strong&gt;&lt;font size="5"&gt;用户的角度&lt;/font&gt;&lt;/strong&gt;来考虑用户到底怎么来使用。如果用户输入了程序接受的输入，那么必然该给出正确的结果，可悲剧的是，就是有那么多的意外，因为客户行为总是在很多程序员意料之外，因此，当用户执行了某个程序员认为是非常规的操作的话，运行结果可能是用户无法得到任何问题的解释，然后用户下定一个结论就是：&amp;#8220;这是一个什么破软件，真没用！&amp;#8221;。&lt;/p&gt;  &lt;p&gt;举个例子，民生网银就是一个巨大的悲剧，我上网银想要做一个操作，就是查询我的信用卡本期该还多少钱，但是我始终找不到那个菜单，原因在于：1 菜单字体太小，找起来真费劲；2 前几项看起来像是查询账户的，但点击后，悲剧的结果是提示&amp;#8220;该卡为非储蓄卡&amp;#8221;，我就纳闷那你为什么不提示我信用卡该做那个操作呢。于是我就找了客服问她如何查询，并向她抱怨网银字体太小，无用菜单太多，于是客服MM告诉我可以自己设置菜单的现实。可是，我哪知道该显示/隐藏那些一级菜单呢？最后我费了很多力气总算找到菜单，然后点击查询后，竟然要让我输入日期，我就寻思，为什么不直接显示最近一期的呢？这么麻烦我干么呢？最后越想越气，因为：1 这个操作过程非常不爽；2 做网银软件的这帮人真是坏了我们程序员的名声，怎么搞出这么难用的软件呢？要是逼这帮程序员天天用民生网银软件，估计也让他们折寿不少； 3 民生银行好歹算不错的公司了，怎么会上这么难用的软件呢？于是，我就很自然的、&amp;#8220;邪恶&amp;#8221;的联想到&amp;#8220;特色&amp;#8221;的社会主义。后来，我觉得我做为一个社会主义合法公民，我该&amp;#8220;为中国的软件事业做点贡献&amp;#8221;，给民生银行提点建议，于是我就想注册民生论坛发表一下意见。不幸的是，悲剧又来了，需要填写的注册信息真多啊，但更悲剧的是，在我填写完所有详细信息后，IE 9 下无法注册，总提示验证码不对。还好，我是程序员，我机器上有3个浏览器，于是，换了Chrome，注册了，但修改帖子不成功；淡定，我还有Firefox，结果出现了乱码。于是，我再次发挥程序员的职业素质，清理了Cookie，用注册好的账户，换回Chrome来发帖子，告诉民生网银有哪些易用性问题。经过一个小时痛苦折腾，算是OK了。要不是为了出心里的这口气，我才不会半夜1点钟忙到2点钟给民生银行反应问题呢（需要说明一下，客户MM态度很好，另外，半夜还要伺候我这样的人，还真难为她了。在她给我道歉时，我就回复她，这不是你的问题，然后转到论坛抱怨来了）。在我印象中，我活到现在半夜发抱怨的帖子仅有2次，一次是在电影院看了&amp;#8220;要拍给下一代人看的&amp;#8221;田壮壮导演亲自执导的《狼灾记》电影，另一次就是使用了民生网银。你也可以看到，程序员不替用户考虑最终会给用户带来多大的麻烦，也可想而知，如果这事发生在作为程序员的你身上或者你所在公司身上，会给你带来多大的信誉损失。&lt;/p&gt;  &lt;p&gt;这类的悲剧也曾出现在我们团队身上，比如，我们的SaaS应用商店开放平台的应用让用户试用了应用之后，用户觉得不错后要继续使用，当用户购买以后却发现怎么也无法激活应用了。这对用户和我们来说，绝对是一个巨大的打击，先不说用户有多么恼火，就问你，你怎么给用户解释出现的问题呢。你总不能告诉用户，我们的程序员忽略了一个情况，&amp;#8220;当应用过期时，应用不能激活了，因为要防止用户重复使用试用的应用&amp;#8221;。这个问题让我思索了很久，因为我不能单纯的去怪罪我的程序员，因为毕竟在设计许可证授权这个模块时，由于我忙于别的任务，我没有去努力把好关，没有让他严格走我们的&amp;#8220;概念设计-&amp;gt;功能规范-&amp;gt;设计规范-&amp;gt;实现-&amp;gt;QA&amp;#8221;标准软件产品生产路线，但更重要的是，我没有把他们培养的和我一样，无论做什么东西，都必须以&amp;#8220;用户场景驱动&amp;#8221;来设计产品。因此，他们很容易忽视软件在非常规操作下的处理，以及一些很细节的问题。最后这件事情是在我用1个小时的时间给他解决好问题后，客户才最终释怀并表示理解和谢意。&lt;/p&gt;  &lt;p&gt;我这篇文章想以2个例子来解释程序需要注意的细节和非常规操作下的软件处理。关于&amp;#8220;用户场景驱动&amp;#8221;设计，我在本文不做详述，大家可以查看《Framework Design GuideLine》这本书。&lt;/p&gt;  &lt;p&gt;第一个实例：我们给一个客户提供尤埃开放服务平台（UIOSP） OEM版的激活工具。这个工具在正常运行下的界面如下：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/20110927000645632.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="initialized" border="0" alt="initialized" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/20110927000645533.png" width="403" height="338" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;（1）运行初始界面。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/20110927000646434.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="activating" border="0" alt="activating" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006472528.png" width="405" height="340" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;（2）输入序列号后，正在激活。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006486889.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="activated" border="0" alt="activated" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006492645.png" width="409" height="344" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;（3）激活成功，显示一些信息。&lt;/p&gt;  &lt;p&gt;在这个小程序里面，需要考虑一下的小细节：&lt;/p&gt;  &lt;p&gt;（1）界面不能被Resize，因为一旦Resize，将会变得非常丑陋；&lt;/p&gt;  &lt;p&gt;（2）背景图片不能随着分辨率的变更而出现一些空白或者遮挡，这也非常的丑陋；&lt;/p&gt;  &lt;p&gt;（3）可以支持&amp;#8220;ESC&amp;#8221;或者&amp;#8220;Enter&amp;#8221;按钮，从而避免用户使用鼠标操作；&lt;/p&gt;  &lt;p&gt;（4）支持使用&amp;#8220;Alt + &amp;lt;Key&amp;gt;&amp;#8221;的组合键，这样方便用户使用键盘操作；&lt;/p&gt;  &lt;p&gt;（5）当用户点击&amp;#8220;激活&amp;#8221;按钮时，要将所有的按钮变成Disabled，避免用户重复点击；&lt;/p&gt;  &lt;p&gt;（6）激活过程要避免界面假死，就是当此时点击界面，界面能及时刷新；&lt;/p&gt;  &lt;p&gt;（7）激活是要显示激活进程，提示用户，现在正在操作；&lt;/p&gt;  &lt;p&gt;（8）界面的字体，要让用户能看清楚；&lt;/p&gt;  &lt;p&gt;（9）异常处理：A）如果网络不畅通，用提示用户检查网络；B）如果许可证输入为空，提示用户输入；C）如果许可证无效，提示用户输入正确许可证；D）如果许可证已经超过使用限制，提示用户购买更多授权；E）如果激活成功，但不是使用管理员用户，则许可证在Win7下可能无法正确保存，那么必须提示用户设置权限或者使用管理员身份。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006504182.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="empty" border="0" alt="empty" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006511608.png" width="244" height="205" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006521509.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="errorkey" border="0" alt="errorkey" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006522523.png" width="244" height="205" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006535248.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="networkerror" border="0" alt="networkerror" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006546261.png" width="244" height="205" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;（10）如果用户点击取消或者关闭，要提示用户是否确定取消。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006557242.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="existconfirm" border="0" alt="existconfirm" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006563032.png" width="244" height="205" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;您或许还需要考虑国际化与本地化支持，此外还需要考虑是否遵循Section 508规范来支持更广泛的易用性规范，以及其它问题。不过，一个真正合格的软件需要考虑的细节确实非常的多，我也没有完全做到正确。下面，我用一个示例来介绍一下关于异常处理的实例。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;第二个实例：许可证辅助工具，这是一个控制台程序，支持对SaaS应用商店开放平台应用许可证的操作。目前它提供了&amp;#8220;-help&amp;#8221;、&amp;#8220;-alterlic&amp;#8221;、&amp;#8220;-alterconstraint&amp;#8221;、&amp;#8220;-listconstraint&amp;#8221;、&amp;#8220;-showmac&amp;#8221;、&amp;#8220;-listlicattr&amp;#8221;和&amp;#8220;-showlic&amp;#8221;命令，分别用于获取帮助信息、变更许可属性、变更许可约束、列出可用的许可约束、查看本地Mac、列出许可证属性和查看一个许可证的信息。默认的是，让你将一个许可证拖拽到这个程序，自动显示该许可证的信息。这个程序采用了&amp;#8220;管道-过滤器&amp;#8221;体系结构来设计，我仅以&amp;#8220;-alterlic&amp;#8221;命令来展示如何进行异常情况处理。&lt;/p&gt;            &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/20110927000657915.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109270006582244.png" width="555" height="363" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;namespace&lt;/span&gt;&amp;nbsp;UIShell.OSGi.LicenseUtility&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&amp;nbsp;Program&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&amp;nbsp;Main(&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;[]&amp;nbsp;args)&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CmdLinePipeLine&amp;nbsp;pipeLine&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;CmdLinePipeLine(); &amp;nbsp;&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="color: #008000; "&gt;// Pipeline-Filter Architecture。&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;showLicense&amp;nbsp;=&amp;nbsp;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;ShowLicenseDetailsFilter();&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.RegisterFilter(&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;AlterLicenseAttributesFilter());&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.RegisterFilter(&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;AlterConstraintFilter());&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.RegisterFilter(&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;ListConstraintsFilter());&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.RegisterFilter(&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;ShowMacFilter());&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.RegisterFilter(&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&amp;nbsp;ListLicenseAttributesFilter());&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.RegisterFilter(showLicense);&lt;br /&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&amp;nbsp;(args.Length&amp;nbsp;==&amp;nbsp;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;File.Exists(args[&lt;span style="color: #800080;"&gt;0&lt;/span&gt;])&amp;nbsp;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;amp;&amp;amp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Path.GetExtension(args[0]).ToLower().Equals(".lic")&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;)&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;showLicense.ShowLicenseDetails(args[&lt;span style="color: #800080;"&gt;0&lt;/span&gt;],&amp;nbsp;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;.Empty);&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;&amp;nbsp;(Exception&amp;nbsp;ex)&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;There&amp;nbsp;is&amp;nbsp;details&amp;nbsp;exception&amp;nbsp;in&amp;nbsp;ex.Message.&amp;nbsp;Thus,&amp;nbsp;just&amp;nbsp;show&amp;nbsp;it&amp;nbsp;directly.&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine(ex.Message);&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.WriteLine();&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.Write(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Press&amp;nbsp;any&amp;nbsp;key&amp;nbsp;to&amp;nbsp;exit.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Console.Read();&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pipeLine.Handle(args);&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt;&amp;nbsp;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;该命令的格式为&amp;#8220;-alterlic &amp;lt;File or Directory&amp;gt; [-deep true/false] [-lictype fx/bundle] &amp;lt;attribute&amp;gt;=&amp;lt;value&amp;gt;&amp;#8221;。&lt;/p&gt;  &lt;p&gt;用户输入异常可能为：&lt;/p&gt;  &lt;p&gt;（1）File or Directory没有指定；&lt;/p&gt;  &lt;p&gt;（2）File or Directory不存在，必须告诉用户输入正确的文件/文件夹；&lt;/p&gt;  &lt;p&gt;（3）File不可读取，必须告诉用户更改权限；&lt;/p&gt;  &lt;p&gt;（4）File格式不正确，必须告诉用户程序无法处理；&lt;/p&gt;  &lt;p&gt;（5）如果是Directory，则是遍历所有的License File，那么，如果其中一个LicenseFile处理失败，则不能影响其它LicenseFile，但必须记录失败的License；&lt;/p&gt;  &lt;p&gt;（6）如果用户输入的属性设置&amp;#8220;&amp;lt;attribute&amp;gt;=&amp;lt;value&amp;gt;&amp;#8221;是一个&amp;#8220;aaa&amp;#8221;格式的字符串，则必须提示用户，并且忽略掉；&lt;/p&gt;  &lt;p&gt;（7）如果用户输入的属性设置&amp;#8220;&amp;lt;attribute&amp;gt;=&amp;lt;value&amp;gt;&amp;#8221;中attribute不存在，则必须提示用户，并且抛出异常，终止变更；&lt;/p&gt;  &lt;p&gt;（8）如果用户输入的属性设置&amp;#8220;&amp;lt;attribute&amp;gt;=&amp;lt;value&amp;gt;&amp;#8221;中value与目标类型不匹配，则必须提示用户，并且抛出异常，终止更新；&lt;/p&gt;  &lt;p&gt;（9）对许可证变更之前必须备份，以做回滚操作。&lt;/p&gt;  &lt;p&gt;（10）其它细节或者异常处理。&lt;/p&gt;  &lt;p&gt;在这里面，我们需要考虑的细节问题和异常处理问题比较多，我无法一一细述，仅供参考，希望能给大家一些思考。关于异常，我想强调一下，异常处理就是你需要提前考虑用户的非常规操作，并对用户的这类操作给出错误提示，并告诉用户如何去纠正。不过，我想，你也应该发现了，做一个在正常情况下能够工作的软件和一个在任何情况下都能工作很好的软件是有非常大的区别的，后则需要我们付出更多的努力和更专业的技能。&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2192437.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/09/27/2192437.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/09/09/2172425.html</id><title type="text">强制执行像Facebook的代码审计</title><summary type="text">Facebook、Google这样的巨头IT公司都具备完善的代码库管理、代码审计（Code Review）制度。代码审计能够消除一些Bug，不过事实上，这不是代码审计最主要的目的，因为Reviewer很难通过审阅代码来发现深层次的Bug。代码审计更重要的是，它有助于维护代码的质量，因为Reviewer可以发现代码编写的是否规范，可以从审计过程中互相学习，也可以指出代码存在的问题。此外，开发人员也会有更多的意识来编写更高质量的代码，被别人指出太多问题或者低级问题，显示是很没有面子的，：）。因此，我认为代码审计对于产品的维护过程是非常重要的一环。Facebook采用谨慎的审计来防止代码出现一些问题</summary><published>2011-09-09T05:19:00Z</published><updated>2011-09-09T05:19:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/09/09/2172425.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/09/09/2172425.html"/><content type="html">&lt;p&gt;Facebook、Google这样的巨头IT公司都具备完善的代码库管理、代码审计（Code Review）制度。代码审计能够消除一些Bug，不过事实上，这不是代码审计最主要的目的，因为Reviewer很难通过审阅代码来发现深层次的Bug。代码审计更重要的是，它有助于维护代码的质量，因为Reviewer可以发现代码编写的是否规范，可以从审计过程中互相学习，也可以指出代码存在的问题。此外，开发人员也会有更多的意识来编写更高质量的代码，被别人指出太多问题或者低级问题，显示是很没有面子的，：）。因此，我认为代码审计对于产品的维护过程是非常重要的一环。Facebook采用谨慎的审计来防止代码出现一些问题。&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;Facebook 有非常牢靠的安全保障，以免有人（你可以想象内部有人有这个权限的）不小心/故意做了些糟糕的的事。如果你已经"成为"了需要别人支持的人，事由将被记录，并且有谨慎的审计。这里不允许钻空子。 &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;你也可以查看&amp;#8220;&lt;a href="http://www.bccn.net/Article/kfyy/rjgc/200708/5062.html"&gt;http://www.bccn.net/Article/kfyy/rjgc/200708/5062.html&lt;/a&gt;&amp;#8221;来了解更多关于代码审计的细节。下面我来介绍一下，我如何通过VisualSVN + BugTracker.NET + TotoiseSVN/AnkhSVN这些工具，在产品实现和维护过程中确保代码审计的实施。VisualSVN是产品代码的配置管理工具；BugTracker.NET是缺陷跟踪系统，也是在代码审计过程中，开发者和审计者的协作平台，它能够与VisualSVN实现无缝整合；TotoiseSVN/AnkhSVN是代码Check in/Check out等操作的辅助工具。&lt;/p&gt;  &lt;p&gt;首先，确保代码审计严格实施基于我们产品开发过程中对Check in的两个限制，如下：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;没有一个BugID，那么任何东西都不可以Check in到代码库；&lt;/li&gt;    &lt;li&gt;如果代码对应的Bug所处的状态不是&amp;#8220;Review Passed&amp;#8221;，那么任何东西都不可以Check in到代码库。&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;这两个限制能够来避免开发人员不经过审查就将代码非法的Check in到仓库。因此，当没有指定Bug/BugId不存在/Bug不处于Review Passed状态时，将阻止开发者Check in代码，向其提示错误消息。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091216565825.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091216576447.png" width="238" height="166" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091216582369.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091216584071.png" width="238" height="165" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091216598597.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217005632.png" width="238" height="165" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;要实现Check in之前的限制，我们需要通过向VisualSVN的代码仓库中注册一个Pre-Commit的Hook，通过这个Hook来检查要Check in的代码是否处于正确的状态。以下是执行这个操作的Hook。这个Hook会获取当前BugId，然后传递给BugTracker.NET中的svn_hook.aspx执行对Bug状态的查询，如果允许签入，则返回包含&amp;#8220;OK:&amp;#8221;的响应码，否则，返回&amp;#8220;ERROR:&amp;#8221;。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008000;"&gt;#&lt;/span&gt;&lt;span style="color: #008000;"&gt;!/usr/local/bin/python&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sys&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;subprocess&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;re&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;urllib&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;os&lt;br /&gt;svnlook&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;C://Progra~1//Visual~1//bin//svnlook.exe&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;this_repository_url&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://LADANFKING:8443/svn/monoaddins&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;btnet_url&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://ladanfking/btnet/svn_hook.aspx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;btnet_username&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;admin&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;btnet_password&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;admin&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;repos&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;sys.argv[&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;]&amp;nbsp;&lt;br /&gt;txn&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;sys.argv[&lt;/span&gt;&lt;span style="color: #000000;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;#&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Pre-commit&amp;nbsp;tag&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;status&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;bDebug&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;False&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;debug_out(s):&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(bDebug):&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;open(&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;d:\\btnet_svn_hook_log.txt&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f.write(s)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f.write(&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;\n&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f.close&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;print&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;s&lt;br /&gt;log_cmd&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;svnlook&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;nbsp;log&amp;nbsp;-t&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;txn&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;repos&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;process&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;subprocess.Popen(log_cmd,&amp;nbsp;stdout&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;subprocess.PIPE,&amp;nbsp;stderr&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;subprocess.PIPE)&amp;nbsp;&lt;br /&gt;log_string&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;process.stdout.read()&lt;br /&gt;debug_out(log_string)&lt;br /&gt;params&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;urllib.urlencode({&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;svn_log&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;log_string,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;repo&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;this_repository_url,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;username&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;btnet_username,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;password&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;btnet_password,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;status&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;:status})&lt;br /&gt;response&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;urllib.urlopen(btnet_url,&amp;nbsp;params)&amp;nbsp;&lt;br /&gt;data&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;response.read()&amp;nbsp;&lt;br /&gt;debug_out(data)&lt;br /&gt;nPos&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;data.find(&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;OK:&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;print&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;data&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;nPos&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;0&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;and&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;nPos&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(len(data)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;):&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sys.exit(0)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sys.exit(&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;因此，开发者想要Check in之前，必须创建一个Bug，并将这个Bug赋给某个人进行Review。这个步骤如下：&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1 Create Bug：这一步骤一般是由QA来完成的，开发者也可以自己来创建Bug。如下所示。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217005141.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217017367.png" width="445" height="289" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2 Assign Review&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;（1）创建一个Patch：进入到你的代码工作目录，然后右键，使用TotoiseSVN的&amp;#8220;Create Patch&amp;#8221;来创建一个补丁。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217018829.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217026386.png" width="402" height="200" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;这个补丁打开后就是前后代码的变更情况。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/20110909121706371.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217062389.png" width="406" height="235" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;（2）Assign Review：这一步就是将这个Patch文件通过BugTracker.NET作为附件上传给指定Bug，并将这个Bug赋给某个人来审计。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217079390.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217085062.png" width="396" height="370" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3 Review：审计人员进入BugTracker.NET，查看Patch文件，如果审计通过，则将状态改为&amp;#8220;Review Passed&amp;#8221;，否则更改为&amp;#8220;Review Failed&amp;#8221;，这样开发人员需要重新进行代码变更并申请新的审计。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;当要Check in的代码对应的Bug通过了审计之后，开发者就可以Check in了。以下是代码Check in之后的情况了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217091639.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217119819.png" width="520" height="322" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;另外，其他人可以通过点击&amp;#8220;svn revisions&amp;#8221;来查看本次的更新，如下。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091217122427.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201109/201109091318582940.png" width="540" height="328" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;这样，引入强制的代码审计就可以约束了开发者不可以随意Check in代码，不可以Check in不符合质量要求的代码，而且，其他开发人员可以查询BugTracker.NET仓库来看看相似的Bug是如何修复的。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2172425.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/09/09/2172425.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/08/27/2155493.html</id><title type="text">TDD美不美，TDD有多美，到底为什么TDD用起来不太美？</title><summary type="text">昨天晚上看了CoolShell陈皓同学对TDD的描述《TDD并不是看上去的那么美》和InfoQ上的虚拟座谈会《TDD有多美》，以及陈皓同学写的《再谈敏捷和ThoughtWorks中国咨询师》。陈皓同学首先用自己的实战经验例举了TDD的各种使用缺陷，从而来描述了TDD并不是看上去的那么美。接着InfoQ举行了一个虚拟座谈会，邀请了ThoughtWorks的熊节同学和其他几位同学，来描述什么是TDD，...</summary><published>2011-08-27T06:12:00Z</published><updated>2011-08-27T06:12:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/08/27/2155493.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/08/27/2155493.html"/><content type="html">&lt;p&gt;昨天晚上看了CoolShell陈皓同学对TDD的描述《&lt;a title="TDD并不是看上去的那么美" href="http://coolshell.cn/articles/3649.html"&gt;TDD并不是看上去的那么美&lt;/a&gt;》和InfoQ上的虚拟座谈会《&lt;a title="TDD有多美" href="http://www.infoq.com/cn/articles/virtual-panel-tdd"&gt;TDD有多美&lt;/a&gt;》，以及陈皓同学写的《再谈敏捷和ThoughtWorks中国咨询师》。陈皓同学首先用自己的实战经验例举了TDD的各种使用缺陷，从而来描述了TDD并不是看上去的那么美。接着InfoQ举行了一个虚拟座谈会，邀请了ThoughtWorks的熊节同学和其他几位同学，来描述什么是TDD，TDD实施的难点，TDD的“美”以及我们多久才能这么“美”。最后，陈皓同学又在《TDD有多美》之后写了一篇文章《&lt;a title="再谈敏捷和ThoughtWorks中国咨询师" href="http://coolshell.cn/articles/3745.html/"&gt;再谈敏捷和ThoughtWorks中国咨询师&lt;/a&gt;》，在这里谈了一下自己针对敏捷的观点和对于ThoughtWorks咨询师的批评观点。这些文章挺有意思，在这里我根据自己的经验并在综合各位大师的基础上谈一下对TDD的看法。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;首先，我并不追求敏捷，我只追求“1 如果采用正确的方法来寻求我做的事情是正确的； 2 如果采用正确的方法来确保正确的实现这件认为是正确的事情”。这也是我座右铭“道法自然”所提倡的，即寻找正确的规律。不过，这个完美的座右铭，实施起来却相当的困难，因为我永远也无法下定一个绝对的结论，对自己说我这样做绝对正确。引用我在Sybase的Manager的话，就是“有些事情，等你死的那天你都无法明白是对还是错”。所以，对于敏捷和TDD，我并没有去刻意的追求什么，崇拜什么，但我想正确的来设计我的产品，正确的实现我的产品，这是最关键的。我追求的方法论，就是“合适的方法”的方法论。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;其次，对于TDD，我认同陈皓同学的很多观点，也认同ThoughtWorks的熊节的很多观点，在这里我引用熊节的一句话来说明TDD，并在后面的篇幅根据我自身的经验来谈一谈我为什么这样想的。引用TW熊节观点并不是为了捧TW，虽然我对TW非常有好感，在这里，我更想来探究我们该怎样使用正确的方法来做正确的事情。&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;“&lt;strong&gt;熊节：……&lt;/strong&gt;TDD的前提是要使用一种设计方法，你就必须（1）会做设计；（2）做设计。它难在有些项目不做设计，有些人不会做设计。……”“熊节：……关键在于，TDD的T，是什么测试都无所谓。它就是设计。……”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;我个人认为，TDD的精髓在于提倡所谓的“设计驱动开发”，即我们必须先清楚我们要干什么，然后我们需要用Code写下来最终提供给用户的使用方法（即TestCase）。随着产品研发/项目的推进，我们需要根据自身的认知来迭代的更新给用户提供的功能，即TestCase，然后更新我们的代码并进行适当的重构。以我的个人经验，我非常的认同这样的方法学。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;我先简单描述一下我过去的经历：不到30岁，经验显然是不足的；2000年上本科，2004年上研究生，2007年进入Sybase工作，后来辞职创办西安尤埃信息技术有限公司。我的软件开发始于2003年，在本科期间的后2年，给学校/单位/个人开发了6个项目，自己也做一些类似党员管理/成绩管理的实验品，这阶段，做的最好的项目就是基于微软Exchange Server 2003开发的工作流审批系统了。从2004年到2007年上研期间，做的项目有十几个，上十万的项目有3个，身兼数职。为了满足项目中无休止的需求变更，我自己设计了控件关系映射组件、通用窗体框架组件（满足团队并行开发协作的模块化框架原型）、对象映射组件等通用组件，并在毕业时将自己的成果写成一篇《企业MIS体系结构研究及应用》的论文，里面用自己设计的框架和组件来支撑个人设计的软件体系结构。在这一阶段，我对自己说的就是，我受够了需求不确定性/无休止变更给我们带来的痛苦，于是我从此思索该如何降低这样的痛苦与折磨，并开发了OSGi.NET产品——尤埃开放服务平台（UIOSP）。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;研究生毕业后，我加入了Sybase，在Sybase工作过程中，我工作性质最大的变化就是，在这里，我做的是一个产品。产品的首要条件就是设计，设计的内容就是我们非常强调的《××××功能规范》。当时，我们团队有一条铁律，凡是对某个Bug的修复/对某个功能的改进/添加了新的功能，如果这些功能会改变/影响用户的使用习惯，那么，我们就必须严格写下功能规范。在功能规范里面，我们必须清楚的描述我们到底要提供什么功能，这些功能让用户如何使用，描述内容甚至要精细到每一个文本框允许用户输入多少文字，如果输入不正确或者文字超过了规定，该给用户什么样的提示。然后，我们团队里的人会对功能规范进行Review，当团队Review差不多了，我们的Manager会邀请其它相关Team的人和QA的人来一起做Review，当这个功能规范通过所有的Review后，QA会给我们发送一份TestPlan，寻求我们对测试规范的意见。我们所做的所有的事情，目标只有一个，就是给用户提供易用性很强的产品。经过上面的过程，产品最终还要经过一个Section 508的测试，这份测试是针对残障人士使用我们产品的易用性测试，估计很多人如果是第一次看到的话，可能都会说“天啊！”。没错，我当时就是那种感觉。功能规范设计评审仅是软件产品设计的一个小小的环节，我们还需要构建完善的质量保证体系，包括缺陷跟踪/持续集成等等，使用各种手段来保证我们做的事情是正确的且我们能够正确的实施。可以这么说，这里所采取的各种复杂的措施、手段和策略都是为了降低我们在软件开发/交付/持续改进的过程中所受的痛苦与折磨，从而保证正确性。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;后来，我从Sybase辞职，创办了一家小公司，主要做OSGi.NET产品和SaaS应用商店开放平台产品。因为当初创业设定的目标是以产品为目标。从自己的工作中以及从微软的《Framework Design Guideline》我学到了很多的东西。在产品实施中，我必须确保能够正确的开发一个让用户喜欢的产品，并且能够在后续的更新升级中保持一个较为平滑的渐进过程。在这里，我所处的角色比较复杂，首先是公司的创始人，其次我是产品的设计师，我还要负责产品架构并为产品构建一个质量保证体系。通俗的讲，我需要来采取各种手段来保证产品的正确性。因此，我非常注重产品的功能设计和质量保证。功能设计主要面向用户，它包括：1 概念设计，通过在白板上描绘出我们要给用户带来什么，然后做一个讨论。 2 功能设计，用文档来描述我到底要给用户提供什么样的功能，用户怎么来使用这些功能的，这样的设计文档可能是功能规范也可能是用户场景设计规范。用户场景规范是源自于微软《Framework Design Guideline》中描述的一种针对微软.NET类库所有API的设计方法，而功能规范更倾向于类似于通过UI来体现的交互性功能。对于OSGi.NET产品，我们的用户场景设计规范多于功能规范。产品实施的其它的环节我在这里不描述了，你可以查看《&lt;a title="[产品开发经验总结] 软件产品背后的冰山一角" href="http://www.cnblogs.com/baihmpgy/archive/2010/08/18/1801963.html"&gt;[产品开发经验总结] 软件产品背后的冰山一角&lt;/a&gt;》这一文章来了解更多的环节。下面我们就来看一下其中关于《ShortCut功能》的场景设计。在这里，我们为用户设计了各种使用场景，这些场景的设计遵循2/8原则，从简单到复杂来设计。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/baihmpgy/201108/201108271411582063.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/baihmpgy/201108/201108271412007372.png" width="651" height="542" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;你有没有发现上面的用户场景就像TDD里面所说的“TestCase”呢？没错，这是一致的，当用户场景设计经过讨论定稿后，它其实就是一个测试用例了。我们以用户为中心，来驱动整个软件的开发，首先要做的就是设计好我们到底要给用户提供什么样的功能和怎样来提供。这些经过讨论的文档也就自然而然的变成了TDD中的“T”。这样的TDD，其好处就不言而喻了，那就是一旦我们把目标设计好之后，即有了“T”作为保障，那么我们的软件产品一定程度上就能够保证软件的实现与软件的设计上的一致性，并能够保留我们的设计现场和讨论现场，这估计也是为什么TDD提倡不需要文档的原因了。因此，我赞同熊节观点“TDD的前提是：首先要学会设计，其次要会做设计”。没有设计的话，“T”就不知道该从何而来了。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;这么说来，TDD应该是美的了？没错，TDD确实美，而且是完美的美。问题来了，有多少产品/项目/人真正能够做到像Sybase那样的设计呢？有多少的程序员能够掌握这种“设计”呢？个人认为这正是为什么“TDD用起来不太美”的根源。因为这东西的初衷看起来太完美了，当你想在不完美的现实来实现完美的目标，最终的结果就是这玩意太不美了。陈皓同学也谈了TDD的各种缺陷了。这里我也谈一下我的。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;从上述的言语中，你可能认为我们就应该是TDD的完美实现者了，NO！我们并没有细到为所有的实现都做这样的设计，就连Sybase也是仅对给用户提供的那部分做完美设计而已，何况我们还仅是创业的小团队而已。我们所采取的TDD，确切的讲，应该是BDD，即行为驱动开发。BDD描述的开发方法是以用户场景来驱动的，它能够更准确的来描绘我们的整个软件系统要实现的功能，更能够准确的保持设计与实现的一致性。我们为BDD还搭配了持续集成，即确保软件产品在持续更新改进的过程中，不会对提供给用户的功能产生破坏，一旦某一个Bug的代码Checkin，持续集成系统将自动构建所有的程序、跑完所有的测试并可根据需要生成产品的安装包，这样，我可以不同太担心产品的这部分核心功能遭到破坏。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;最后，我来总结一下我个人的观点：1 TDD重在有设计，我非常喜欢这种理念； 2 TDD很完美不过实施困难，但不是没有价值或者忽悠，对于我们而言，在于吸取其中的理念并适当应用。不过，说真的，这比TDD的理论要更难了，需要你根据需要去探索一条适合自己“国情”的路子，特别是当我们面对的情况还处在“发展中且一百年不动摇”的阶段！&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2155493.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/08/27/2155493.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/08/23/2151072.html</id><title type="text">应用程序该如何拥抱变化</title><summary type="text">拥抱变化是极限编程非常重要的一个理念，OOP原则中的OCP原则（Open Close Principle，开放原则）也是拥抱变化的体现。不过，在写程序过程中，我们总是会遇到各种各样的变化，我们也尝过了“变化”的各种苦头，甚至都厌倦了再去迎接任何的变化，这并不是因为原则错误，而是我们一开始就没有准备好“变化”。这个文章对“拥抱变化”不再累述，我们直接来看一个使用面向服务架构的应用程序，体会一下拥抱变化。我先说一下这个实例的内容，它非常的常见，就是设计一个权限控制服务，基本在我们的每一个业务系统中存在。不过，我有必要描述一下这个实例的背景，从而展现出为什么我需要做好变化的准备。目前我们有一个“插件</summary><published>2011-08-23T09:47:00Z</published><updated>2011-08-23T09:47:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/08/23/2151072.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/08/23/2151072.html"/><content type="html">&lt;div&gt;&lt;div&gt;拥抱变化是极限编程非常重要的一个理念，OOP原则中的OCP原则（Open Close Principle，开放原则）也是拥抱变化的体现。不过，在写程序过程中，我们总是会遇到各种各样的变化，我们也尝过了&amp;#8220;变化&amp;#8221;的各种苦头，甚至都厌倦了再去迎接任何的变化，这并不是因为原则错误，而是我们一开始就没有准备好&amp;#8220;变化&amp;#8221;。这个文章对&amp;#8220;拥抱变化&amp;#8221;不再累述，我们直接来看一个使用面向服务架构的应用程序，体会一下拥抱变化。&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;我先说一下这个实例的内容，它非常的常见，就是设计一个权限控制服务，基本在我们的每一个业务系统中存在。不过，我有必要描述一下这个实例的背景，从而展现出为什么我需要做好变化的准备。目前我们有一个&amp;#8220;插件工厂&amp;#8221;，在这个插件工厂里面，我们希望向软件开发人员提供免费的界面插件、服务插件和业务插件，这样开发人员可以使用现有的插件来轻松/高效的构建自己需要的应用系统。换句话说，插件工厂的目标就是使用大众的力量帮助我们构建积木块的应用程序，插件工厂本身是一个最大的积木块仓库。&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;在插件工厂中，服务插件包括最基本的权限控制服务。这个权限控制服务向开发者提供非常简单易用的权限控制服务，并且开发者可以选择不同的权限控制服务提供商来构建自己的应用系统。打个比方，如果开发者构建的应用系统非常简单，他可以从插件工厂下载权限服务插件和一个&amp;#8220;基于用户&amp;#8212;权限的&amp;#8221;权限控制服务提供商，它允许直接对用户授权；如果开发者构建的应用系统比较复杂，那么他可以下载权限服务插件和一个&amp;#8220;基于角色的访问控制&amp;#8221;权限控制服务；用户还可以利用现有的MemberShip实现自定义的权限控制服务。也就是说，开发者可以根据需要获取权限服务及相应的服务提供商来满足需求。经过思考，我在白板上画出了这个服务的实现原型。&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/1.png" width="591" height="345" alt="" /&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在这个原型上，&amp;#8220;Business Addin&amp;#8221;即业务插件，是开发者需要设计的业务模块，这个业务模块将使用权限控制服务来实现权限的控制；权限服务分为契约和不同的提供商两部分，服务提供商对于业务插件来说是透明的，这些服务提供商可能是：（1）简单的权限控制服务提供商；（2）基于MemberShip的权限控制服务提供商；（3）基于角色的访问控制权限服务提供商；（4）其它服务提供商。不管开发者从插件工厂获得了哪个服务提供商，他都能够使用一致的模型来使用权限控制服务，并且这些权限控制服务能够与.NET现有的安全机制兼容。&amp;#8220;Business Addin&amp;#8221;使用权限服务的场景如下，我们希望尽可能使权限控制服务与开发者无关并且简单可重用。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/2.png" width="557" height="335" alt="" /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/3.png" width="589" height="192" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;#8220;Business Addin&amp;#8221;业务插件使用一般场景如下：&lt;/p&gt;&lt;div&gt;&lt;div&gt;（1）首先通过[assembly: AddinPermission(&amp;#8220;PermissionId&amp;#8221;, &amp;#8220;Name&amp;#8221;)]来定义这个业务插件中需要检查的权限；&lt;/div&gt;&lt;div&gt;（2）然后在需要做权限检查的代码中调用权限服务的Demand方法实现检查。&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(PermissionService.Demand(&amp;#8220;PermissonId&amp;#8221;))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;当前用户拥有Id为&amp;#8220;PermissionId&amp;#8221;的权限，因此允许执行以下操作&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;向用户提示，您没有此操作的权限，请联系管理员给予分配&amp;#8220;PermissionName&amp;#8221;权限&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;这样对于开发者的好处是显而易见的：（1）开发者也开发业务系统过程中不再需要设计任何的用户-角色-权限管理的应用模块；（2）开发者可以根据需要任意定义/扩展业务插件所需的权限，这些权限的管理最终由插件工厂里的权限服务提供商来实现。&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;那下面我们来看一下怎么来设计这个能够拥抱各种变化的权限服务。这个设计方案如下：&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/4.png" width="554" height="282" alt="" /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;（1）&lt;span style="white-space:pre"&gt;&lt;/span&gt;业务插件通过AddinPermission特性来定义一个权限，定义的权限会注册到权限服务的注册表中；&lt;/div&gt;&lt;div&gt;（2）&lt;span style="white-space:pre"&gt;&lt;/span&gt;当业务插件请求一个权限时，它调用IPermissionService.Demand(&amp;#8220;PermissionId&amp;#8221;)来判断当前用户是否拥有该权限；&lt;/div&gt;&lt;div&gt;（3）&lt;span style="white-space:pre"&gt;&lt;/span&gt;业务插件不依赖于权限服务提供商；&lt;/div&gt;&lt;div&gt;（4）&lt;span style="white-space:pre"&gt;&lt;/span&gt;权限服务提供商在实现权限服务时使用权限服务的权限注册表来获取业务插件注册的权限实例，然后调用该实例来检查权限；&lt;/div&gt;&lt;div&gt;（5）&lt;span style="white-space:pre"&gt;&lt;/span&gt;权限服务提供商默认权限的权限检查依赖于权限服务当前的用户/角色信息，然后对当前用户信息是否拥有该权限做出判断；&lt;/div&gt;&lt;div&gt;（6）&lt;span style="white-space:pre"&gt;&lt;/span&gt;权限服务基于.NET的安全标识、实体、权限来设计，能够兼容.NET的安全机制。&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;下面我们看一下相关的项目及服务定义。&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/5.png" width="721" height="236" alt="" /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;运行效果图如下。在这里，我们为应用系统安装了SimplePermissionService，那么IPermissionService的提供商就是SimplePermissionService。如果用户需要其它的实现，比如ASP.NET MemberShipe实现的权限控制，就可以下载相应的插件来提供权限服务，但这对业务插件来说是透明的，它不需要做任何的代码变更。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/6.png" width="600" height="232" alt="" /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;权限服务定义如下。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;PermissionService&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;权限服务契约，需要兼容.NET安全机制，即兼容IIdentity/IPrincipal/IPermission模型。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;interface&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPermissionService&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;默认权限类型。如果用户使用AddinPermission没有指定权限类型，则使用该权限。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Type&amp;nbsp;DefaultPermissionType&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;当前安全实体。由用户标识和角色集合组成。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IPrincipal&amp;nbsp;User&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;创建默认的权限实例。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;font class="Apple-style-span" color="#008000"&gt;每次返回一个新的权限实例。&lt;/font&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IPermission&amp;nbsp;CreateDefaultPermission();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class="Apple-style-span" style="color: #008000; "&gt;// 判断当前用户是否拥有指定的权限。&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Demand(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;permissionId);&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Demand(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;addinId,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;permissionId);&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Demand(Addin&amp;nbsp;addin,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;permissionId);&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Demand(RuntimeAddin&amp;nbsp;addin,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;permissionId);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;}&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;在业务插件中使用权限服务，这里它没有对实际的权限服务提供商产生任何的依赖，只是通过SOA中的服务注册表来绑定一个IPermissionService服务，然后使用它来验证权限。&lt;/div&gt;&lt;div&gt;（1）权限定义&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;[assembly:&amp;nbsp;AddinPermission(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;MyPermissionId&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;My&amp;nbsp;Permission&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;[assembly:&amp;nbsp;AddinPermission(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Guest&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Guest&amp;nbsp;Permission&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(CustomizedPermission))]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;（2）获取权限服务并请求验证权限&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;IPermissionService&amp;nbsp;permissionService&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Context.GetFirstOrDefaultService&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;IPermissionService&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(permissionService&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(permissionService.Demand(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;MyPermissionId&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Response.Write(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Permission&amp;nbsp;demanded&amp;nbsp;successfully.&amp;nbsp;&amp;lt;br&amp;nbsp;/&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Response.Write(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Permission&amp;nbsp;demanded&amp;nbsp;failed.&amp;nbsp;&amp;lt;br&amp;nbsp;/&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Response.Write(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Please&amp;nbsp;install&amp;nbsp;a&amp;nbsp;Permission&amp;nbsp;Service&amp;nbsp;Provider&amp;nbsp;first.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;p&gt;}&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这个拥抱变化的思想是基于面向服务架构思想来实现的，在这里，&amp;#8220;服务=契约 + 实现，契约=面向对象中的接口，实现=实现接口的类型&amp;#8221;。业务插件依赖的是服务的契约，并不依赖服务的实现，服务的实现针对契约的不同提供商。我们可以根据应用系统的需要，在不更改业务插件的情况下，变更服务提供商来满足实际系统的需求。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;关于权限服务提供商的实现会稍微复杂一点点，一个典型的提供商一般包括：（1）相关实体管理界面，如用户/部分/角色/权限分配；（2）权限服务实现。以下是一个典型的权限管理界面了。&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/Permission.png" width="600" height="333" alt="" /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;在这里，权限服务提供商实现时，一般需要实现：（1）定义一个默认的权限；（2）实现IPermissionService；（3）在登录时设置IPermissionService.User。&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/impl1.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/baihmpgy/Impl2.png" width="591" height="237" alt="" /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;示例服务的实现如下。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimplePermissionService&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Service(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(IPermissionService))]&amp;nbsp;&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #008000; "&gt;// 注册为IPermissionService服务契约的实现。&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;WebPermissionService&amp;nbsp;:&amp;nbsp;IPermissionService&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Type&amp;nbsp;DefaultPermissionType&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(DefaultPermission);&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPermission&amp;nbsp;CreateDefaultPermission()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;DefaultPermission();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPrincipal&amp;nbsp;User &amp;nbsp;&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #008000; "&gt;// 绑定HttpContext.User安全主体。&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(HttpContext.Current&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;HttpContext.Current.User;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(HttpContext.Current&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HttpContext.Current.User&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #008000; "&gt;// 判断当前用户是否拥有指定权限。其它重载方法省略。&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Demand(&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;/span&gt;&lt;span style="color: #0000ff; "&gt;string&lt;/span&gt;&lt;span style="color: #000000; "&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;addin,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;permissionId)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IPermission&amp;nbsp;permission&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;PermissionRegistry.GetPermission(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;addin,&amp;nbsp;permissionId);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(permission&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;permission.Demand();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;todo:&amp;nbsp;Log&amp;nbsp;here.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #008000; "&gt;// 其它重载方法......&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;}&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2151072.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/08/23/2151072.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/07/25/2116478.html</id><title type="text">[视频]如何构建一个插件化的Web应用程序</title><summary type="text">这个视频介绍了如何构建一个插件化的ASP.NET应用程序。该应用程序由一个主程序和3个插件构成，演示了如何基于插件化方式构建应用程序、UIOSP的模块化特性、模块间基于SOA的通讯和如何使用模块扩展特性。在这个应用程序，主程序、插件以及插件提供的服务都可以完全的重用，体现了使用UIOSP基于软件生产线方式来构建应用程序的新思维。[hjp2=600,480,true]http://www.eguanli.cn/UIOSP_Demo.wmv[/hjp2] 你可以从尤埃开放服务平台免费下载下载到UIOSP平台的安装包，从UIOSP构建插件化Web应用程序Demo视频下载该视频，从Web插件应用程序实</summary><published>2011-07-25T09:41:00Z</published><updated>2011-07-25T09:41:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/07/25/2116478.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/07/25/2116478.html"/><content type="html">&lt;p&gt;这个视频介绍了如何构建一个插件化的ASP.NET应用程序。该应用程序由一个主程序和3个插件构成，演示了如何基于插件化方式构建应用程序、UIOSP的模块化特性、模块间基于SOA的通讯和如何使用模块扩展特性。在这个应用程序，主程序、插件以及插件提供的服务都可以完全的重用，体现了使用UIOSP基于软件生产线方式来构建应用程序的新思维。&lt;/p&gt;&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&amp;nbsp;[hjp2=600,480,true]http://www.eguanli.cn/UIOSP_Demo.wmv[/hjp2]&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;你可以从&lt;a href="http://www.uishell.com/uploadfiles/UIOSP_Trial.msi"&gt;尤埃开放服务平台免费下载&lt;/a&gt;下载到UIOSP平台的安装包，从&lt;a href="http://www.eguanli.cn/UIOSP_Demo.wmv"&gt;UIOSP构建插件化Web应用程序Demo视频&lt;/a&gt;下载该视频，从&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;a title="Web插件应用程序实例下载" href="http://files.cnblogs.com/baihmpgy/MovieStore.zip"&gt;Web插件应用程序实例下载&lt;/a&gt;下载视频创建的插件程序。&lt;/p&gt;  &lt;p&gt;UIOSP平台交流群： 121369588。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2116478.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/07/25/2116478.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/07/24/2115270.html</id><title type="text">如何写健壮的代码</title><summary type="text">不管是在面向过程时代，还是在面向对象时代，任何一个功能都是由若干函数协作来实现的。一个函数由输入、处理和输出组成。实现这个函数的代码段都假定了输入的参数已经满足了若干规则，在执行这个函数时，函数的代码会拿到输入的参数然后执行代理逻辑。下面我们就来看一个函数的代码。 1privatestaticvoidParseArgs(string[]arguments)2{3if(_parsedArgs)4{5return;6}7if(arguments==null)8{9arguments=CommandLineArgs;10}11//命令行格式：12conststringusage="[-in</summary><published>2011-07-24T02:58:00Z</published><updated>2011-07-24T02:58:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/07/24/2115270.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/07/24/2115270.html"/><content type="html">&lt;p&gt;不管是在面向过程时代，还是在面向对象时代，任何一个功能都是由若干函数协作来实现的。一个函数由输入、处理和输出组成。实现这个函数的代码段都假定了输入的参数已经满足了若干规则，在执行这个函数时，函数的代码会拿到输入的参数然后执行代理逻辑。下面我们就来看一个函数的代码。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ParseArgs(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[]&amp;nbsp;arguments)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(_parsedArgs)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(arguments&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;arguments&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CommandLineArgs;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;命令行格式：&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;usage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[-initial&amp;nbsp;5]&amp;nbsp;[-level&amp;nbsp;2]&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;i&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;i&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;arguments.Length;&amp;nbsp;i&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;匹配前导符&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(arguments[i].CompareTo(InitialStartLevelLead)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;step&amp;nbsp;forward&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;i&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;arguments.Length)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;取值&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_initialBundleStartLevel&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Convert.ToInt32(arguments[i]);&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;goto&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;fail;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(arguments[i].CompareTo(StartLevelLead)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;step&amp;nbsp;forward&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;i&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;arguments.Length)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;取值&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_startLevel&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Convert.ToInt32(arguments[i]);&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;38&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;39&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;40&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;41&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;42&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;goto&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;fail;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;43&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;44&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;45&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;46&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_parsedArgs&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;47&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;48&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fail:&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;49&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Exception(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Invalid&amp;nbsp;args,usage:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;usage);&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;50&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;这个函数大致的用意是使得一个程序启动时，允许用户在启动程序时可以带上类似&amp;#8220;-initial 5 -level 2&amp;#8221;这样的参数来改变程序的行为。估计我们经常会写出类似以上的程序，有时候可能是因为经验不足，有时候可能是偷懒。你可以找出这段小程序有哪些问题吗？&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;下面我使用注释的方式把函数中每一个小细节问题标记一下，如果有遗落也请大家补充。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ParseArgs(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[]&amp;nbsp;arguments)&amp;nbsp;&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(_parsedArgs)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;1&amp;nbsp;这个参数的命名不符合规则，正确的命名应该是_isArgsParsed，如果想让参数可读性更强，可以再将参数的限定词声明一下，变成_is&amp;#215;&amp;#215;ArgsParsed。&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(arguments&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;arguments&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;GetCommandLineArgs();&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;命令行格式：&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;usage&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[-initial&amp;nbsp;5]&amp;nbsp;[-level&amp;nbsp;2]&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;div style="display: inline-block; "&gt;&lt;/div&gt;&lt;/span&gt;&lt;span style="font-family: 'Courier New'; color: #008000; "&gt;//&lt;/span&gt;&lt;span style="font-family: 'Courier New'; color: #008000; "&gt;2 硬编码的字符串。&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;i&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;i&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;arguments.Length;&amp;nbsp;i&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;3&amp;nbsp;如果GetCommandLineArgs的返回值为空，则这行代码会出现NullReferenceException；此外，如果arguments.Length大于4个，我们需要给用户提示；如果参数出现重复或者不符合要求，我们也需要给用户提示。&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;匹配前导符&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(arguments[i].CompareTo(InitialStartLevelLead)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;4&amp;nbsp;如果arguments[i]允许带空格，则这行代码会产生错误的执行结果&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;step&amp;nbsp;forward&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;i&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;arguments.Length)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;取值&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_initialBundleStartLevel&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Convert.ToInt32(arguments[i]);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;5&amp;nbsp;如果arguments[i]不是合法的整数，则这行代码会产生转换失败的异常。&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;goto&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;fail;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(arguments[i].CompareTo(StartLevelLead)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;6&amp;nbsp;问题同3&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;step&amp;nbsp;forward&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;i&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;arguments.Length)&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;取值&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_startLevel&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Convert.ToInt32(arguments[i]);&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;7&amp;nbsp;问题同4&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;goto&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;fail;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_parsedArgs&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;br /&gt;fail:&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Exception(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Invalid&amp;nbsp;args,usage:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;usage);&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;8 异常信息不友好，没有清楚告诉用户是哪一个参数输入有问题，此外在英文文法中，&amp;#8220;args&amp;#8221;和&amp;#8220;usage&amp;#8221;中间要空格，另外，给用户的信息不能够随便使用缩写，必须使用完整的词语；硬编码字符串需要放在一个统一的资源文件，并考虑I18N和L10N支持；问题2中的字符串可以直接和这个Exception的字符串直接合并；如果有必要的话，最好重新定义个Exception类型。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;一个健壮的函数，需要考虑的问题不仅仅只是正确的功能。上面的这段代码仅仅是考虑了用户输入是正确的情况。当用户输入错误时，以上代码要么出现没有任何友好提示的异常，要么仅给出一个不友好的错误信息。使一个函数达到健壮，在编码时，我们必须谨记：（1）不能假定函数的输入参数是正确，必须检查函数的输入参数是否符合规则；（2）当函数的输入不符合规则时，必须告诉用户错在哪，并告诉用户如何输入正确的参数；（3）考虑代码的可读性，遵循代码规范。另外，测试时需要确定输入参数的边界，将处于边界内和边界外的参数都测试，以保证函数的参数不正确时函数能给出一个友好的提示。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2115270.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/07/24/2115270.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/baihmpgy/archive/2011/07/13/2105018.html</id><title type="text">确保真正的线程安全——微软为什么不提供线程安全库</title><summary type="text">线程安全在高并发情况下是一个非常严重的问题。以下代码在多线程访问时，会出现问题。我们以List.Add为例，来说明在多线程访问下的状况。以下代码是List.Add的实现。publicvoidAdd(Titem){if(this._size==this._items.Length)this.EnsureCapacity(this._size+1);this._items[this._size++]=item;this._version++;}当两个线程同时访问一个List的Add方法时，这个方法的第一条指令就可能出现不一致性了。因为，此时两个线程访问时_size都是一样的，正确情况下List应该</summary><published>2011-07-13T02:44:00Z</published><updated>2011-07-13T02:44:00Z</updated><author><name>道法自然</name><uri>http://www.cnblogs.com/baihmpgy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/baihmpgy/archive/2011/07/13/2105018.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/baihmpgy/archive/2011/07/13/2105018.html"/><content type="html">&lt;p&gt;线程安全在高并发情况下是一个非常严重的问题。以下代码在多线程访问时，会出现问题。我们以List.Add为例，来说明在多线程访问下的状况。以下代码是List.Add的实现。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Add(T&amp;nbsp;item)&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;{&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;._size&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;._items.Length)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.EnsureCapacity(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;._size&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;._items[&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;._size&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;]&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;item;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;._version&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;当两个线程同时访问一个List的Add方法时，这个方法的第一条指令就可能出现不一致性了。因为，此时两个线程访问时_size都是一样的，正确情况下List应该执行EnsureCapacity(this._size + 2)而不再是EnsureCapacity(this._size + 1)了。为了确保List的线程安全，我们必须保证在任意时刻只能有一个线程来更改List的数据。这样我们的SimpleThreadSafeList就诞生了，在这个List中我们对其的每一个读写操作都加上一个排它锁。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;:&amp;nbsp;IList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;List&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_data;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_syncRoot&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_data&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;List&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;RemoveAt(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;index)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;lock&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(_syncRoot)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_data.RemoveAt(index);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Add(T&amp;nbsp;item)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;lock&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(_syncRoot)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_data.Add(item);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;others......&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;这样我们确保List的数据在任意时刻都只有一个线程对其进行访问，看起来安全很多了。不过，如果所谓线程安全是这么简单的话，微软为什么不提供一个ThreadSafeList呢？JaredPar MSFT在这篇文章中做了一个描述《Why are thread safe collections so hard?&lt;a href="http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx"&gt;http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx&lt;/a&gt;》，他解释微软不实现线程安全集合类，是因为以上这样的所谓&amp;#8220;线程安全&amp;#8221;并不是真正安全，我们可以从以下的代码中看出端倪。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;var&amp;nbsp;list&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;ohters&amp;nbsp;&amp;#8230;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list.Count&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;list[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;];&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在以上代码中，我们创建了SimpleThreadSafeList这个类，其中有一个代码段就是用于获取list的默认值。如果有多个线程访问这段代码时，依然会出现数据不一致问题。即在执行&amp;#8220;return list[0]&amp;#8221;这条语句是，它是以&amp;#8220;list.Count &amp;gt; 0&amp;#8221;为前提的，当两个线程同时对这个SimpleThreadSafeList操作时，当前线程访问到list.Count大于0，但之后可能另一个线程将list清空了，这时候当前线程再来返回list[0]时就会出现IndexOutofRangeException了。SimpleThreadSafeList保证了List内部数据只能由一个线程来操作，但是对于上面的代码，它是无法保证数据不一致的。SimpleThreadSafeList仅能够被称为&amp;#8220;数据线程安全&amp;#8221;，这也是微软不提供线程安全集合类的原因了。JaredPar MSFT提出了一个真正解决线程安全的方法。那就是将SimpleThreadSafeList的_syncRoot 暴露出来。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;:&amp;nbsp;IList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_syncRoot&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SyncRoot&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_syncRoot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;others&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;使用List时，需要使用到SyncRoot来加锁。&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;lock&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list.SyncRoot)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list.Count&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;list[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;不过，使用这种方式，有几个缺陷。第一，没有一个良好的Guide来指导编写线程安全的代码；第二，当SyncRoot使用范围过大时，非常容易造成死锁。下面是一段可能产生死锁的代码。&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;var&amp;nbsp;list1&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;var&amp;nbsp;list2&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Thread(()&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;lock&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list1.SyncRoot)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list2.Add(&lt;/span&gt;&lt;span style="color: #800080;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;间接请求了list2.SyncRoot&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}).Start();&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Thread(()&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;lock&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list2.SyncRoot)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list1.Add(&lt;/span&gt;&lt;span style="color: #800080;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;间接请求了list1.SyncRoot&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}).Start();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;对于死锁这个问题，我们采取的方法是使用Monitor.TryEnter，从而来避免一直死锁。对于前一个问题，我这边仅是基于DisposableLocker来实现尽可能的线程安全，对于如何使用，我目前依然没有一个良好的理论，只能说我们在设计高并发的API时，对多个线程可以同时访问的对象都需要加以判断从而来确定需要采用什么样的方式处理。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;UIShell.OSGi.Collection&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Use&amp;nbsp;Monitor.TryEnter&amp;nbsp;to&amp;nbsp;acquire&amp;nbsp;a&amp;nbsp;lock.&amp;nbsp;This&amp;nbsp;would&amp;nbsp;not&amp;nbsp;cause&amp;nbsp;the&amp;nbsp;dead&amp;nbsp;lock.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;DisposableLocker&amp;nbsp;:&amp;nbsp;IDisposable&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_syncRoot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_lockAcquired;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_millisecondsTimeout;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;DisposableLocker(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;syncRoot,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;millisecondsTimeout)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_syncRoot&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;syncRoot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_millisecondsTimeout&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;millisecondsTimeout;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_lockAcquired&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Monitor.TryEnter(_syncRoot,&amp;nbsp;_millisecondsTimeout);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LogWhenAcquireLockFailed();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;LogWhenAcquireLockFailed()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;_lockAcquired)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;这时候可能要如下处理：（1）记录日志；（2）记录日志并抛出异常；（3）记录日志，然后Block，重现死锁。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FileLogUtility.Error(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Format(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Accquire&amp;nbsp;the&amp;nbsp;lock&amp;nbsp;timeout.&amp;nbsp;The&amp;nbsp;limited&amp;nbsp;time&amp;nbsp;is&amp;nbsp;{0}&amp;nbsp;milliseconds.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_millisecondsTimeout&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Dispose()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dispose(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GC.SuppressFinalize(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Dispose(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;disposing)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(disposing)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(_lockAcquired)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Monitor.Exit(_syncRoot);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;~&lt;/span&gt;&lt;span style="color: #000000;"&gt;DisposableLocker()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dispose(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;当出现死锁时，这里采用的解决方案是记录日志，然后继续运行。不过，这种方法有一定缺陷，可能在极端情况下引起数据不一致。因此，我们可能需要抛出异常或者让锁一直持续下去。SimpleThreadSafeList此时将以以下方式来实现。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleThreadSafeList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;:&amp;nbsp;IList&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_syncRoot&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SyncRoot&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; get&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;_syncRoot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MillisecondsTimeoutOnLock {&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;DisposableLocker&amp;nbsp;CreateLocker()&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;DisposableLocker(MillisecondsTimeoutOnLock,&amp;nbsp;SyncRoot);&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Add(T&amp;nbsp;item)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; using&lt;/span&gt;&lt;span style="color: #000000;"&gt;(CreateLocker())&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; _data.Add(item);&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; &amp;nbsp; //&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;others&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;接下来使用List.CreateLocker来建立一个全局锁&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list.CreateLocker())&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(list.Count&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;list[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000; "&gt;];&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;大家可以看一下是否还有更好的方式来保证线程绝对安全。&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/baihmpgy/aggbug/2105018.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/baihmpgy/archive/2011/07/13/2105018.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
