<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1315956053498110948</id><updated>2012-01-07T16:22:40.170-08:00</updated><category term='C#'/><category term='SCM'/><category term='WebService'/><category term='Visual Studio Tools'/><category term='MustNeedSoftware'/><category term='Software Engineering'/><category term='Mozilla'/><category term='Outlook'/><category term='MultiThread-Processor'/><category term='UsefulCode'/><category term='DesignPattern'/><category term='Delphi'/><category term='Cmd_shell'/><category term='UML'/><category term='XML'/><category term='Cracker'/><category term='Scalability-Performance'/><category term='Windows'/><category term='DevelopSoftware'/><category term='Debug and Test'/><category term='Registry'/><category term='Mediaplayer'/><title type='text'>WadeLiu Blog On Windows</title><subtitle type='html'>This blog is to record my work tips and thoughts of Windows.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>99</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2057717283849197824</id><published>2009-09-19T04:16:00.000-07:00</published><updated>2009-09-19T04:18:50.378-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>VS2008 SP1 ISO version</title><content type='html'>VS2008 RTM的版本是9.0.21022, 打sp1之后为9.0.3&lt;br /&gt;&lt;br /&gt;VS2008 SP1在线安装包vs90sp1-KB945140大小为500K多,  打补丁的过程会非常慢的, 因为下载后总共有800M多.  为了加速打补丁的过程, 可以在MS网站下载SP1 的ISO版本, 参考下面两个博客:&lt;br /&gt;&lt;br /&gt;http://blog.miniasp.com/post/2008/08/Microsoft-Visual-Studio-2008-Service-Pack-1-Released.aspx&lt;br /&gt;http://www.cnblogs.com/vainnetwork/archive/2008/08/13/1266982.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2057717283849197824?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2057717283849197824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2057717283849197824' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2057717283849197824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2057717283849197824'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2009/09/vs2008-sp1-iso-version.html' title='VS2008 SP1 ISO version'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1539087504465251630</id><published>2008-10-17T02:19:00.000-07:00</published><updated>2008-10-17T02:57:57.840-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='MultiThread-Processor'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Asynchronious call Delegate</title><content type='html'>参见 http://blogs.yodersolutions.com/net/?p=17&lt;br /&gt;当我们声明了Delegate 变量(比如FooDelegate), 我们可以使用下面两种方法,来触发这个Delegate,&lt;br /&gt;  1. FooDelegate.Invoke(), 或者直接是FooDelegate().&lt;br /&gt;  2. FooDelegate.BeginInvoke().&lt;br /&gt;第一种调用方法是同步执行这个delegate.&lt;br /&gt;而第二种方式是异步执行这个delegate, 这个delegate会在另一个线程中被执行, 当前线程将继续执行其它代码. 需要说明的是, 一定要确保这个delegate有机会调用了EndInvoke(), 否则会有资源和内存泄漏. &lt;br /&gt;异步调用的一个简单示例是:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;subscriber.BeginInvoke(this, new EventArgs(), Callback, subscriber);&lt;/span&gt;&lt;br /&gt;其中第3个参数是回调函数, 它的签名是AsynCallback delegate.当subscriber被执行完后, Callback会被调用.&lt;br /&gt;其中第4个参数一定要是subscriber本身,或者是subscriber本身的一个wrapper, 这样在callback函数体中, 就能访问到subscriber本身来EndInvoke.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            EventPublisher eventPublisher = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventPublisher();&lt;br /&gt;            eventPublisher.FooEvent += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(eventPublisher_FooEvent1);&lt;br /&gt;            eventPublisher.FooEvent += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler(eventPublisher_FooEvent2);&lt;br /&gt;            Stopwatch sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; Stopwatch();&lt;br /&gt;            sw.Start();&lt;br /&gt;            eventPublisher.AsynFireFooEvent();&lt;br /&gt;            Console.WriteLine(sw.ElapsedMilliseconds.ToString());&lt;br /&gt;            Console.ReadKey();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; eventPublisher_FooEvent1(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            Thread.Sleep(100);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; eventPublisher_FooEvent2(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            Thread.Sleep(200);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; EventPublisher&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; EventHandler FooEvent; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// synchronized invoke the all the subscriber services. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// The process will return until all delegates executions are over.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; FireFooEvent()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (FooEvent != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                FooEvent(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; EventArgs());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt; &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Raising events asynchronously lets the event subscribers do their processing in another thread &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// and allows the thread that raised the event to continue processing.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AsynFireFooEvent()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (FooEvent != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                Delegate[] subscribers =  FooEvent.GetInvocationList();&lt;br /&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (EventHandler subscriber &lt;span class="kwrd"&gt;in&lt;/span&gt; subscribers)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="rem"&gt;//the 3rd arg should be a AsyncCallback type delegate. When one subscriber service will completed, the AsyncCallback method will be raised. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                    &lt;span class="rem"&gt;//the 4th arg should be the exact subscriber or subscriber wrapper, so that in callback function, &lt;/span&gt;&lt;br /&gt;                    &lt;span class="rem"&gt;// we can access the subcriber to call EndInvoke()&lt;/span&gt;&lt;br /&gt;                    subscriber.BeginInvoke(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; EventArgs(), Callback, subscriber);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; Callback(IAsyncResult ar)&lt;br /&gt;        {&lt;br /&gt;            EventHandler raisedEvent = (EventHandler)ar.AsyncState;&lt;br /&gt;            raisedEvent.EndInvoke(ar);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1539087504465251630?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1539087504465251630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1539087504465251630' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1539087504465251630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1539087504465251630'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/10/asynchronious-call-delegate.html' title='Asynchronious call Delegate'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-9170314234018602182</id><published>2008-10-09T19:28:00.000-07:00</published><updated>2008-10-16T22:18:49.160-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Auto build script by using NAnt</title><content type='html'>当我们想专门为一个C#项目架一个build服务器,  怎样对VS的solution文件进行自动build是个问题,  最简单的办法是, 编写一个bat文件, 运行这个bat文件就能完成solution的编译甚至运行单元测试 .  NAnt是个很好的选择. &lt;br /&gt;简单地讲, NAnt就是一个能将xml文件作为参数的命令行工具, 你可以在这个xml中按照NAnt的schema编写你想要完成的任务, 比如压缩文件, 比如删除目录, 当然NAnt最主要的作用是可以编写任务来批量编译c#的代码. 但是考虑到MS官方已经发布了msbuild, 所以一个比较好的做法是：在NAnt的参数xml文件中, 使用msbuild来编译.Net solution, 用NAnt本身的功能完成其它事情. &lt;br /&gt; 当然对于Nant新手来说, 编写这样的xml并不简单. 幸好我们有一些现成工具可以使用, Tree Surgeon就是这样一个开源项目(&lt;a href="http://www.codeplex.com/treesurgeon"&gt;http://www.codeplex.com/treesurgeon&lt;/a&gt;).&lt;br /&gt; TreeSurgeon不仅仅帮你编写xml的build文件(你可以根据需要做比较的修改),  而且会自动将NAnt以及NUnit等整理到一个tools目录.  Treesurgeon创建的solution目录结构也很有参考价值, 比如和src目录同级别的目录, 还有bin, tools, lib, dist目录, 其中bin是存放solution的输出文件(需要在Visual studio中将这个solution的所有project的output目录制定到这个bin目录), dist目录是专门作为solution的release目录.&lt;br /&gt;如果想测试这个xml文件中某些变量设置是否正确, 可以使用在project tag之下, 创建echo tag, 在用NAnt执行这个xml文件时, echo中的message信息就会被输出到屏幕上. &lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;echo&lt;/span&gt; &lt;span class="attr"&gt;message&lt;/span&gt;&lt;span class="kwrd"&gt;="${framework::get-framework-directory(framework::get-target-framework())}\msbuild.exe"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;下面的bat和xml是使用NAnt的示例(它是由TreeSurgeon生成, 并参考了Ninject源码中的NAnt build_xml文件). 使用非常方便,&lt;br /&gt; cmd&gt; build 或&lt;br /&gt; cmd&gt; build test&lt;br /&gt; build.bat的内容是:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;@tools\nant\NAnt.exe -buildfile:DbGear.build %*&lt;br /&gt;rem pause&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;DbGear.build是一个xml文件, 用NAnt命令行程序执行这个xml文件(NAnt0.86版本如用msbuild tag来调用.net 3.5 的msbuild时候, 会有bug. 所以这个例子并没有使用常规的msbuild tag,而是使用 exec tag直接调用3.5版本的msbuild命令行程序)&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;&amp;lt;!--refer to treesurgeon on codeplex, and build file of ninject project--&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;project&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="DbGear"&lt;/span&gt; &lt;span class="attr"&gt;default&lt;/span&gt;&lt;span class="kwrd"&gt;="compile"&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://nant.sf.net/schemas/nant.xsd"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!--tell NAnt try to use msbuild from .net sdk 3.5--&amp;gt;&lt;/span&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="nant.settings.currentframework"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="net-3.5"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!--declare path variables--&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.base"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${project::get-base-directory()}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.src"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.base}/src"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.tools"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.base}/tools"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.build"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.base}/bin"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.dist"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.base}/dist"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.build.testresult"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build}/test-result"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="path.build.debug"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build}/debug"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!--define solution variables--&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="version"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0.0.0"&lt;/span&gt; &lt;span class="attr"&gt;overwrite&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="file.solution"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.src}/DbGear.sln"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!--choose one suitable compiling config, eg Debug, Release or other customized config schema--&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;property&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="build.configuration"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="debug"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!-- define build  targets --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="clean"&lt;/span&gt; &lt;span class="attr"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;="Delete Automated Build artifacts"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;delete&lt;/span&gt; &lt;span class="attr"&gt;dir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build}"&lt;/span&gt; &lt;span class="attr"&gt;if&lt;/span&gt;&lt;span class="kwrd"&gt;="${directory::exists(path.build)}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;delete&lt;/span&gt; &lt;span class="attr"&gt;dir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.dist}"&lt;/span&gt; &lt;span class="attr"&gt;if&lt;/span&gt;&lt;span class="kwrd"&gt;="${directory::exists(path.dist)}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="init"&lt;/span&gt; &lt;span class="attr"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;="create assembly out path"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;mkdir&lt;/span&gt; &lt;span class="attr"&gt;dir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.dist}"&lt;/span&gt; &lt;span class="attr"&gt;if&lt;/span&gt;&lt;span class="kwrd"&gt;="${not(directory::exists(path.dist))}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;mkdir&lt;/span&gt; &lt;span class="attr"&gt;dir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build}"&lt;/span&gt; &lt;span class="attr"&gt;if&lt;/span&gt;&lt;span class="kwrd"&gt;="${not(directory::exists(path.build))}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;mkdir&lt;/span&gt; &lt;span class="attr"&gt;dir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build.testresult}"&lt;/span&gt; &lt;span class="attr"&gt;if&lt;/span&gt;&lt;span class="kwrd"&gt;="${not(directory::exists(path.build.testresult))}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;mkdir&lt;/span&gt; &lt;span class="attr"&gt;dir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build.debug}"&lt;/span&gt; &lt;span class="attr"&gt;if&lt;/span&gt;&lt;span class="kwrd"&gt;="${not(directory::exists(path.build.debug))}"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;echo&lt;/span&gt; &lt;span class="attr"&gt;message&lt;/span&gt;&lt;span class="kwrd"&gt;="Build configuration:"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;echo&lt;/span&gt; &lt;span class="attr"&gt;message&lt;/span&gt;&lt;span class="kwrd"&gt;="${framework::get-framework-directory(framework::get-target-framework())}\msbuild.exe"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!--nant0.86 has a bug  with  Framework 3.5 section,  so we will use exec to call msbuild.exe of 3.5, rather than the regular msbuild  tag --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!--&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;    &amp;lt;target name="compile" depends="init"  description="Compiles using the AutomatedDebug Configuration"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;        &amp;lt;msbuild project="${file.solution}"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;            &amp;lt;property name="Configuration" value="${build.configuration}" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;        &amp;lt;/msbuild&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;    &amp;lt;/target&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         --&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;br /&gt;     &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="compile"&lt;/span&gt; &lt;span class="attr"&gt;depends&lt;/span&gt;&lt;span class="kwrd"&gt;="init"&lt;/span&gt; &lt;span class="attr"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;="Compiles using the Debug Configuration"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exec&lt;/span&gt; &lt;span class="attr"&gt;program&lt;/span&gt;&lt;span class="kwrd"&gt;="${framework::get-framework-directory(framework::get-target-framework())}\msbuild.exe"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;arg&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${file.solution}"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;   &lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;arg&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="/verbosity:minimal"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;arg&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="/property:Configuration=${build.configuration}"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;arg&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="/property:WarningLevel=0"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt; &lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;exec&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="test"&lt;/span&gt; &lt;span class="attr"&gt;depends&lt;/span&gt;&lt;span class="kwrd"&gt;="compile, unittest"&lt;/span&gt;&lt;br /&gt;        &lt;span class="attr"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;="Compile and Run Tests"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="full"&lt;/span&gt; &lt;span class="attr"&gt;depends&lt;/span&gt;&lt;span class="kwrd"&gt;="clean, test"&lt;/span&gt;&lt;br /&gt;        &lt;span class="attr"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;="Compiles, tests, and produces distributions"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!-- Internal targets --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="unittest"&lt;/span&gt; &lt;span class="attr"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;="runs the unit tests"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;&amp;lt;!-- Test Assembly --&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exec&lt;/span&gt; &lt;span class="attr"&gt;program&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.tools}/nunit/nunit-console.exe"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;arg&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build.debug}/UnitTests.dll"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;arg&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="/xml=${path.build.testresult}/UnitTests-Results.xml"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;exec&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="dist"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;zip&lt;/span&gt; &lt;span class="attr"&gt;zipfile&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.dist}\DbGear-${version}.zip"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;fileset&lt;/span&gt; &lt;span class="attr"&gt;basedir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.build.debug}"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.pdb"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;fileset&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;zip&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="package-source"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;zip&lt;/span&gt; &lt;span class="attr"&gt;zipfile&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.dist}\DbGear-${version}-source.zip"&lt;/span&gt; &lt;span class="attr"&gt;ziplevel&lt;/span&gt;&lt;span class="kwrd"&gt;="9"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;fileset&lt;/span&gt; &lt;span class="attr"&gt;basedir&lt;/span&gt;&lt;span class="kwrd"&gt;="${path.src}"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.cs"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.csproj"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.sln"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.txt"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;include&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.build"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;exclude&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="**/*.pdb"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;fileset&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;zip&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;target&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;project&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-9170314234018602182?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/9170314234018602182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=9170314234018602182' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/9170314234018602182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/9170314234018602182'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/10/auto-build-script-by-using-nant.html' title='Auto build script by using NAnt'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7574172476141109137</id><published>2008-09-27T19:33:00.000-07:00</published><updated>2008-09-27T22:13:39.772-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DesignPattern'/><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Using Ninject(one DI container)</title><content type='html'>在设计中, 经常会遇到这样的情况, 在一个类中要创建或使用另一个类的实例,  暂且将前一个类称为大类, 后一个类称为小类,  也许小类有很多变种,  我们会根据不同的情况, 让大类使用不同的小类变种.    可以看出这里有一个耦合关系,  一个好的办法是使用依赖注入模式(Dependency Inject), Martin Fowler 有个非常精彩的文章专门讲述&lt;a href="http://www.martinfowler.com/articles/injection.html"&gt;DI&lt;/a&gt;).&lt;br /&gt;DI原理其实很简单,  我们设计的大类要依赖于小类的接口或基类, 而不是一个具体的小类, 同时不要在大类中创建小类实例, 而是通过大类的构造子或property将小类的实例传进来即可.&lt;br /&gt;目前.Net领域有不少DI容器框架, (这里是&lt;a href="http://www.emadibrahim.com/2008/08/18/the-best-ioc-container/"&gt;DI容器框架&lt;/a&gt;&lt;a href="http://www.emadibrahim.com/2008/08/18/the-best-ioc-container/"&gt;列表&lt;/a&gt;), 这些框架主要有两个功能, (1)帮助完成依赖的注册与依赖实例的创建, 即绑定小类接口和某个具体小类,  绑定的地方不是在大类中, 所以实现了解耦.  (2)更高级的功能是, DI 容器框架可以帮助我们创建大类实例, 就像是一个Factory工厂方法一样, 当然大类所依赖的小类, 也不同我们手动创建, 容器自动按照我们定义的小类绑定关系来创建小类实例.&lt;br /&gt;Ninject是一个新的DI框架,  它的特点是:&lt;br /&gt;(1)不需要使用Xml来定义绑定关系, 使用一个自定义的Module类(基类为StandardModule)来定义绑定关系;&lt;br /&gt;(2)不仅仅支持constructor注入, 而且支持property注册;&lt;br /&gt;(3)对于constrctor注入, 构造子还可以包含其他类型参数, 不仅仅是所依赖的类型参数.&lt;br /&gt;(4)对于非constructor注入, 不仅仅支持无参构造子, 而且支持带参构造子.&lt;br /&gt;(5)支持基于类型的条件绑定, 可以使用Bind().To().ForMembersOf();&lt;br /&gt;(6)部分支持基于variable的Context的条件绑定, 示例代码中对此有说明.(Ninject支持另一种条件绑定, 但它需要在大类的代码加上Parameter attribute或Method attribute, 增加了大类和小类的耦合度, 所以我不喜欢, 好在基于context variable的绑定基本够用了)&lt;br /&gt;(7)对于利用DI容器创建的对象, 可以在定义绑定时, 指定对象的生命周期, 比如Singleton以及SingleCall的生命周期模式.&lt;br /&gt;&lt;br /&gt;下面是一个使用Ninject的简单示例, 需要添加Ninject.core和Ninject.condition两个assembly.&lt;br /&gt;主程序类和自定义的Module类:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Threading;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Core;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Conditions;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Core.Behavior;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Core.Parameters;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Core.Activation;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; NinjectDemo&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; DI: Old way&lt;br /&gt;            IEditor editor = &lt;span class="kwrd"&gt;new&lt;/span&gt; NotePad();&lt;br /&gt;            var csProgrammer = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindowsProgrammer(editor);&lt;br /&gt;            csProgrammer.WriteCode();&lt;br /&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; DI container&lt;br /&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; Initialization &lt;span class="kwrd"&gt;for&lt;/span&gt; &lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject&lt;br /&gt;            var module = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProgrammerModule();&lt;br /&gt;            IKernel kernel = &lt;span class="kwrd"&gt;new&lt;/span&gt; StandardKernel(module);&lt;br /&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; Simple inject&lt;br /&gt;            var vbProgrammer = kernel.Get&amp;lt;WindowsProgrammer&amp;gt;();&lt;br /&gt;            vbProgrammer.WriteCode();&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//Get correct concrete class according to binding condition&lt;/span&gt;&lt;br /&gt;            var linuxProgrammer = kernel.Get&amp;lt;LinuxProgrammer&amp;gt;();&lt;br /&gt;            linuxProgrammer.WriteCode();&lt;br /&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; Including other parameters rather than inject &lt;span class="kwrd"&gt;interface&lt;/span&gt;&lt;br /&gt;            Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; param = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt;();&lt;br /&gt;            &lt;span class="rem"&gt;//there is another parameter named firstName in constructor &lt;/span&gt;&lt;br /&gt;            param.Add(&lt;span class="str"&gt;"firstName"&lt;/span&gt;, &lt;span class="str"&gt;"Harry-Mac OS"&lt;/span&gt;); &lt;br /&gt;            var macProgrammer = kernel.Get&amp;lt;MacProgrammer&amp;gt;(With.Parameters.ConstructorArguments(param));&lt;br /&gt;            macProgrammer.WriteCode();&lt;br /&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt;  Control binding by context variable&lt;br /&gt;            IParameterCollection pc = With.Parameters.ContextVariable(&lt;span class="str"&gt;"OS"&lt;/span&gt;, &lt;span class="str"&gt;"Mac"&lt;/span&gt;).ConstructorArguments(param);&lt;br /&gt;            var programmer = kernel.Get&amp;lt;Programmer&amp;gt;(pc);&lt;br /&gt;            macProgrammer.WriteCode();&lt;br /&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt; DI container&lt;br /&gt;&lt;br /&gt;            Console.WriteLine(&lt;span class="str"&gt;"Enter any key to exit..."&lt;/span&gt;);&lt;br /&gt;            Console.ReadKey();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; ProgrammerModule : StandardModule&lt;br /&gt;    { &lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 注册接口和对象的绑定&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Load()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//This is a default bind for IEditor inteface&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;();&lt;br /&gt;            &lt;span class="rem"&gt;//Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;().Always();// same to the above line&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//This is a condtional bind for IEditor injection&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;Vi&amp;gt;().ForMembersOf&amp;lt;LinuxProgrammer&amp;gt;();&lt;br /&gt;            &lt;span class="rem"&gt;//or the following code&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;Vi&amp;gt;().OnlyIf(c =&amp;gt; c.Member.DeclaringType == typeof(LinuxProgrammer)); &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//or the following code&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;Vi&amp;gt;().OnlyIf(delegate(IContext c) { return c.Member.DeclaringType == typeof(LinuxProgrammer); }); &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;Vi&amp;gt;().ForMembersOf&amp;lt;MacProgrammer&amp;gt;();&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//This is another kind of conditional bind. &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//我们获取对象要用kernel.Get&amp;lt;T1&amp;gt;()方法, 绑定用Bind&amp;lt;T2&amp;gt;()方法, &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//  这种context绑定仅仅适合于T1和T2同一类型或基于同一类型&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;Programmer&amp;gt;().To&amp;lt;MacProgrammer&amp;gt;().Only(When.Context.Variable(&lt;span class="str"&gt;"OS"&lt;/span&gt;) == &lt;span class="str"&gt;"Mac"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Load2 方法在本项目中其实没用, 只是为了列出Ninject在绑定时可指定对象的生命周期&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Load2()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//每次调用kernel.Get&amp;lt;&amp;gt;(), 总是返回一个新的对象, 如果Remoting中讲的SingleCall对象&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;();&lt;br /&gt;            &lt;span class="rem"&gt;//Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;().Using&amp;lt;TransientBehavior&amp;gt;(); //same as the above&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//获取的对象是Singleton对象, 即使是不同线程, 获得的对象总是同一个&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;().Using&amp;lt;SingletonBehavior&amp;gt;();&lt;br /&gt;            &lt;br /&gt;            &lt;span class="rem"&gt;//One instance of the type will be created per web request, and will be destroyed when the request ends.&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;().Using&amp;lt;OnePerRequestBehavior&amp;gt;();&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//在同一个线程中, 每次调用kernel.Get&amp;lt;&amp;gt;()获取的对象总是同一个&lt;/span&gt;&lt;br /&gt;            Bind&amp;lt;IEditor&amp;gt;().To&amp;lt;NotePad&amp;gt;().Using&amp;lt;OnePerThreadBehavior&amp;gt;(); &lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;下面是IEditor接口和实现类:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; NinjectDemo&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEditor&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; Code();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Vi : IEditor&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Code()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"This is Vi editor"&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; NotePad : IEditor&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Code()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"This is NotePad editor"&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;下面是Programmer基类和派生类:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;&lt;span class="preproc"&gt;#region&lt;/span&gt; Ninject &lt;span class="kwrd"&gt;namespace&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Conditions;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Core.Behavior;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Ninject.Core;&lt;br /&gt;&lt;span class="preproc"&gt;#endregion&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; NinjectDemo&lt;br /&gt;{&lt;br /&gt;   &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Programmer&lt;br /&gt;    {&lt;br /&gt;        IEditor m_Editor;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Programmer(IEditor editor)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_Editor = editor;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteCode()&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine(m_Editor.Code());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;class&lt;/span&gt; WindowsProgrammer:Programmer&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; WindowsProgrammer(IEditor editor)&lt;br /&gt;           : &lt;span class="kwrd"&gt;base&lt;/span&gt;(editor)&lt;br /&gt;       {&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;class&lt;/span&gt; MacProgrammer : Programmer&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="kwrd"&gt;string&lt;/span&gt; m_FirstName;&lt;br /&gt;&lt;br /&gt;       [Inject]&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; MacProgrammer(IEditor editor, &lt;span class="kwrd"&gt;string&lt;/span&gt; firstName)&lt;br /&gt;           : &lt;span class="kwrd"&gt;base&lt;/span&gt;(editor)&lt;br /&gt;       {&lt;br /&gt;           m_FirstName = firstName;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteCode()&lt;br /&gt;       {&lt;br /&gt;            Console.Write( m_FirstName+&lt;span class="str"&gt;" , "&lt;/span&gt;);&lt;br /&gt;            &lt;span class="kwrd"&gt;base&lt;/span&gt;.WriteCode();&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;class&lt;/span&gt; LinuxProgrammer : Programmer&lt;br /&gt;   { &lt;br /&gt;       [Inject]&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; LinuxProgrammer(IEditor editor)&lt;br /&gt;           : &lt;span class="kwrd"&gt;base&lt;/span&gt;(editor)&lt;br /&gt;       { &lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7574172476141109137?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7574172476141109137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7574172476141109137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7574172476141109137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7574172476141109137'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/09/using-ninjectone-di-container.html' title='Using Ninject(one DI container)'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-5631154353236284504</id><published>2008-08-26T21:53:00.000-07:00</published><updated>2008-08-26T22:08:41.950-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mozilla'/><category scheme='http://www.blogger.com/atom/ns#' term='Outlook'/><title type='text'>check exchange mail by firefox</title><content type='html'>管理Exchange的邮件账号, 最好是用outlook. 当你不能使用outlook(或没有outlook软件)时,  很自然会想到了通过web方式来访问邮件账户.   web 访问exchange邮箱的前提是, Exchange Server开启了Outlook Web Access功能.&lt;br /&gt; 之后你就可以通过IE访问你的Exchange邮件账号, 方法方式非常简单, 直接输入地址&lt;span style="font-style: italic; font-weight: bold;"&gt;https://mail.xxx.com/&lt;/span&gt; , IE的地址会自动重定向到一个新的地址&lt;span style="font-style: italic; font-weight: bold;"&gt;https://mail.xxx.com/exchweb/bin/auth/owalogon.asp?url=https://mail.xxx.com/exchange&amp;amp;reason=0&lt;/span&gt;&lt;br /&gt;.&lt;br /&gt;其实我不太喜欢IE, 因为它的插件比较少, 更重要的是它的Network管理功能比Firefox差多了.  但Firefox却不能通过前面的那个较简单URL地址直接访问Exchange邮箱,  要访问需要输入这个复杂的地址.&lt;br /&gt;&lt;br /&gt;怎样设置Firefox每隔一段时间自动接受新邮件呢, 另外Firefox最好能缩小到System tray呢?&lt;br /&gt;我们需要Tab Mix Plus和Minimize To Tray 两个插件, 安装这个插件之后, 默认设置情况下, firefox的contextmenu会多了几个菜单项, 其中一个是Reload Every, 也就是每隔一段时间自动加载这个tab 页.&lt;br /&gt;总结一下, 需要的插件有:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tab Mix Plus(&lt;/span&gt;强大的Session管理插件)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Minimize to tray&lt;/span&gt;(将firefox 缩小到traybar)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MR Tech Toolkit&lt;/span&gt; (formerly Local Install) 6.0.1—因为Minimize to tray 这个插件不兼容firefox3, 安装了这个Mr Tech插件之后, 可以跳过Minimize to tray安装时候的compatible check过程.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-5631154353236284504?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/5631154353236284504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=5631154353236284504' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5631154353236284504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5631154353236284504'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/08/check-exchange-mail-by-firefox.html' title='check exchange mail by firefox'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8641588887683181068</id><published>2008-08-21T22:18:00.000-07:00</published><updated>2008-08-21T23:07:17.931-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>svn authorization</title><content type='html'>预先的环境是: svn server的IP是: 11.12.13.14, OS是windows 2003 server.  repository的目录是D:\source, 我们在该repository下建立了两个项目, 分别是Project1和Project2. 建立repository的过程, 见&lt;a href="http://focuswindows.blogspot.com/2008/06/install-subversion-service-on-windows.html"&gt;这个blog &lt;/a&gt;&lt;br /&gt; 常用的Svn访问协议有三种, 第一种是file协议, 第二是svn协议, 第三是https协议.&lt;br /&gt;  https协议比较适合于跨广域网的项目开发, 需要有apache的支持, 所以配置比较复杂一些,   可参考网络上的文章 .&lt;br /&gt;&lt;ol&gt;&lt;li&gt;   Setting up an ASP.NET website development environment using Visual Studio .NET,    Subversion, and Windows XP      &lt;a href="http://www.codeproject.com/KB/aspnet/Subversion.aspx"&gt;http://www.codeproject.com/KB/aspnet/Subversion.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;  HOWTO: Subversion for Windows with Apache server - a beginner's guide [version 0.4]      &lt;a href="http://svn.spears.at/"&gt;http://svn.spears.at/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;   Setting Up Subversion for One or Multiple Projects       &lt;a href="http://www.linuxjournal.com/article/7655"&gt;http://www.linuxjournal.com/article/7655&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;    file协议最适合一个人的项目, 设置非常简单, 你在你本机开一个svn server, 同时在你本机创建一个repository. 你的svn客户端就可以用file协议访问repository了. 也可以多人一起用, 但必须将repository 的目录共享出来, 所以安全性很差, 不建议在多人项目中使用这种模式.&lt;br /&gt;  本机file协议访问project1的url是 &lt;a href="file:///D:/source/project1"&gt;file:///D:/source/project1&lt;/a&gt; .&lt;br /&gt; 如果是局域网访问的话是, &lt;a href="file:///%5C11.12.13.14/source/project1"&gt;file:///\11.12.13.14/source/project1&lt;/a&gt;&lt;br /&gt; Svn协议比较适合于局域网内部多人项目的开发, 在svn server建立了一个repository之后, 我们就可以使用svn协议了, URL是 &lt;a href="svn://11.12.13.14/source/project1"&gt;svn://11.12.13.14/source/project1&lt;/a&gt; ,这是因为缺省情况下, 这个repository已经被开启了匿名读权限了, 但写权限被关闭了. 所以任何人都可以读取这个repository的内容. 我们需要为每个人定制不同的访问权限. 需要修改这个repository目录下的三个文件, 它们都在D:\harry\source\conf下.&lt;br /&gt;(1) svnserve.conf文件, 你需要处理掉4个label的注释, 分别是authz-db和password-db和anon-access和auth-access.需要注意的是, 确保每行前边没有多余的空格, 否则当你访问svn会报错.  另外最好为realm这个label设置一个有意义的名称, 因为svn client连接server时候, 会显示server的realm名称.  同时如果你想让多个repository共用同一组用户账号,   可以将这几个repository的passwd文件指向同一个文件, 可以使用相对路径来指定passwd文件(相对路径是基准是conf目录), 也可以用绝对路径来指定. 需要注意的, 路径必须使用unix风格的分隔符/, 而不能是\.&lt;br /&gt;&lt;br /&gt;(2) passwd文件, 在[users]section下定义用户和密码, 每个账号一行,用户名和密码用=号分隔 .&lt;br /&gt;(3) authz文件, 这是最关键的配置文件. 下面是authz文件的配置:&lt;br /&gt;[groups]&lt;br /&gt;Prj1_Dev_Team=harry,helen&lt;br /&gt;Prj2_Dev_Team=tom,peter&lt;br /&gt;Test_Team=sally,mark&lt;br /&gt;QA_Team=andy&lt;br /&gt;&lt;br /&gt;[/]&lt;br /&gt;*=r  #所有人都能读取这个repository&lt;br /&gt;harry=rw  #harry具有这个repository的读写权限&lt;br /&gt;&lt;br /&gt;[/project1]&lt;br /&gt;#*=rw   #取消所有人的读写权限&lt;br /&gt;@Prj1_Dev_Team=rw&lt;br /&gt;@SE_Team_QA=rw&lt;br /&gt;&lt;br /&gt;[/project2]&lt;br /&gt;#*=rw&lt;br /&gt;@Prj2_Dev_Team=rw&lt;br /&gt;@SE_Team_QA=rw&lt;br /&gt;@Test_Team=rw&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8641588887683181068?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8641588887683181068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8641588887683181068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8641588887683181068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8641588887683181068'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/08/svn-authorization.html' title='svn authorization'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-5956991561599030441</id><published>2008-08-16T01:52:00.000-07:00</published><updated>2008-08-16T01:57:18.835-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='Registry'/><title type='text'>Registry requisite tools</title><content type='html'>Regsnap -registry and windows system folder snapshot tool and analysis tool.&lt;br /&gt;RegMon.exe--product from sysinternal company, it is free tool&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-5956991561599030441?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/5956991561599030441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=5956991561599030441' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5956991561599030441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5956991561599030441'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/08/registry-requisite-tools.html' title='Registry requisite tools'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3973721679146124609</id><published>2008-08-12T21:52:00.000-07:00</published><updated>2008-08-12T21:55:13.897-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>benefits  by using svn</title><content type='html'>首先先讲一下subversion几个特性.&lt;br /&gt;tortoisesvn安装之后, 有个help文档, 非常好, 不仅包含tortoisesvn的帮助, 而且有很多关于subversion服务器端帮助信息. 网络上有一个中文帮助chm文件, 网站为http://svndoc.iusesvn.com&lt;br /&gt;&lt;br /&gt;Subversion 在版本控制方面做的非常好, 它用一个global revision number来标示repository的版本状态.  每次commit, 全局版本号码都增一.  Subversion 一个非常好的特点是, 若一个文件在两个版本中没有任何修改, 其实它在Subversion中仅有个保存, 这里采用了类似于Unix的hard-link技术. 所以你不用担心频繁的commit会不会使repository存储快速增大.&lt;br /&gt;HEAD revision指的是最新版本的revision, 但是需要注意的是, 如果你要针对HEAD revision进行某种操作时候(比如合并), 你的repository可能同时会被其他人进行commit, 这样你的合并结果可能不是你期望的那个. 所以最好的方式是, 在你合并时候, 指定版本号, 即使是合并最新版本, 也要先获取它的版本号.&lt;br /&gt;&lt;br /&gt;Subversion为开发流程提供的新的模式&lt;br /&gt;单单就subversion的合并功能, 其实对于开发模式来讲, 具有非常大的变革.  比如我们要增加一个新的feature, 这个feature的开发有一定的风险或者我们要将这个feature的开发交给另一个team. 通常我们可以将当前的trunk做一个branch, 专供new feature开发的. 由于在new feature的开发中, trunk的代码也在不断演进,  甚至是new feature依赖的基础也可能会变化的, 所以我们不能期待在new feature开发完毕之后, 再将branch和trunk合并, 这样branch的改动量会很大, 所以我们应该每个一周就将trunk的代码合并到branch中, 这样每次合并对于branch这边的冲击会小一些, 迭代几个周期, 当new feature开发完毕之后,  再将branch合并到trunk中.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3973721679146124609?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3973721679146124609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3973721679146124609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3973721679146124609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3973721679146124609'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/08/benefits-by-using-svn.html' title='benefits  by using svn'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-9009141498196055040</id><published>2008-08-11T22:03:00.000-07:00</published><updated>2008-08-12T22:06:01.192-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>routine tortoisesvn operations-2</title><content type='html'>我自己写了一点关于svn的常用功能, 见&lt;a href="http://focuswindows.blogspot.com/2008/08/routine-tortoisesvn-operations-1.html"&gt;http://focuswindows.blogspot.com/2008/08/routine-tortoisesvn-operations-1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;以下内容摘自&lt;a href="http://blog.csdn.net/iNarcissuss/archive/2007/09/16/1787411.aspx"&gt;http://blog.csdn.net/iNarcissuss/archive/2007/09/16/1787411.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Check-out(检出) 和 Export（导出）&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;从 服务器取得 最新版本（Subversion术语--Head Revision）或某个历史版本的拷贝 复制到本地的某个目录，这个本地的目录有个Subversion专门的术语---working copy(工作拷贝)，working copy的特点是自动与服务器关联，并受服务器的版本控制。&lt;br /&gt;所以Subverion的CheckOut相当于VSS的 设定工作路径+签出 。&lt;br /&gt;与CheckOut类似的一个命令是------Export（导出），它能将某个版本复制一份到本机的某个目录，与CheckOut不同的是，这个目录不是woking copy，Export（导出）&lt;br /&gt;后就与服务器没有任何关系了，当然更不会受服务器的版本控制。&lt;br /&gt;TortoiseSVN会在是working copy的目录上加上各种标志，而Export的目录不会有任何标志&lt;br /&gt;SVN Update(SVN　更新) &amp;amp; Get Lock&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;最常用的命令，你可以只CheckOut一次，但是最好经常update，特别是在你修改之前尤其特别一定用Update，以保证本地工作拷贝与服务器项目版本库一致。它的功能是&lt;br /&gt;，从服务器取得最新版本跟新本机工作拷贝，相当于VSS的Get Latest Version，如果习惯VSS，并且对SVN的复制--修改--合并模型不放心的话，可以在Update之后，马上使用&lt;br /&gt;“获取锁定”命令，它的作用是使的别人不可以修改你正在修改的文件，以避免冲突。&lt;br /&gt;Import Export (导入  导出)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;Import是一种快速批量向服务器添加文件的方法，如果你像把本地的文件或文件夹添加到服务器的某个目录下面，那么在本地目录中，右单击选择Import命令，然后&lt;br /&gt;设定URL即可，这是从别的版本管理系统向VSS迁移的一种方法，在版本浏览器上单击某个目录，会有加入文件和加入文件夹的命令，其中加入文件一次只能加入一个文件&lt;br /&gt;加入文件夹只能加入该文件夹下的所有文件，不能加入子文件夹，你可以根据实际需要使用.需要注意的是, 本机目录导入到服务器后，本机目录没有改变，和服务器也没关联，&lt;br /&gt;并不是工作拷贝。Export命令请在本文其他地方找。&lt;br /&gt;Switch &amp;amp; Relocate (切换和重定位)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;Switch -----在版本库内改变与当前工作拷贝关联的服务器路径URL（只限于同一个Repository内），应用情景：有时，服务器的目录会有所变化，和你当前工作拷贝&lt;br /&gt;关联的服务器URL改变了，这种改变的直接结果是，你在工作拷贝中所做的修改不能提交到服务器，这时就需要Switch到正确的URL再提交。&lt;br /&gt;Relocate----功能和Switch雷同，差别在于，Relocate实现的是Repository和Repository之间的切换。当服务器地址或Repository名称发生变化时，可以用它来更新&lt;br /&gt;你的工作拷贝。&lt;br /&gt;Create/Apply patch (创建和应用补丁)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;如果你对某个文件没有修改的权限，但又必须对它进行修改，这时你可以对其创建补丁，然后把补丁发给对此目录有write权限的工作人员，他进行一系列的审核，审核&lt;br /&gt;通过后，他会执行应用补丁命令，可以将你所做的修改提交到服务器上。&lt;br /&gt;copy to working copy...(复制到工作拷贝...)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;首先，注意这里是working copy ，后面在选择目录时一定不要选错！，当然，选错了tortoisesvn会提示错误的，正确的操作应该是选那些有tortoisesvn标志的目录。&lt;br /&gt;执行此命令会在working copy中增加你copy的目录和文件，然后修改，再commit，repository中就做了相应的变化。&lt;br /&gt;当你需要用到这样一个模块，它与已经存在的某个模块类似，然而又不完全一样，需要有一定改动时，用copy to working copy...命令较为快捷。&lt;br /&gt;Resolved ...(已解决的...)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;当两个人同时编辑一个文件，一个人先提交后，另一个人再进行提交时就会出现冲突，TortoiseSVN会提出必须更新你的工作拷贝后才能对这个文件进行修改，&lt;br /&gt;Subversion冲突的种类及解决方法&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;---&gt;1.当两个人同时编辑一个文件的不同部分，一个人先提交后，另一个人再进行提交时就会出现冲突&lt;br /&gt; ---&gt;解决方法：在冲突的文件上调用命令SVN Update(SVN更新)，TortoiseSVN会自动从服务器上下载最新版本，并与本地工作拷贝进行合并，然后调用命令&lt;br /&gt; SVN Commit(SVN 提交)，就会自动生成一个新版本传到服务器上。&lt;br /&gt;---&gt;2.当两个人同时编辑一个文件的相同部分，一个人先提交后，另一个人再进行提交时就会出现冲突&lt;br /&gt; ---&gt;解决方法：这种情况下调用SVN Update时，由于是同一部分修改，TortoiseSVN不知道应该怎么办，它会自动在发生冲突的文件的目录下生成三个文件，一个&lt;br /&gt; 发生冲突文件的基础版本，名称为文件的全名再加上基础版本的版本号，如FileConflict.cpp.r90,另一个是你调用SVN Update时更新的版本，名称也是文件&lt;br /&gt; 的全名再加上基础版本的版本号，如FileConflict.cpp.r95，它是别人已经修改好提交的文件， 还有一个是你的本地修改，后缀为.mine，而原文件以一种TortoriseSVN能识别的方式显示冲突的双方，而且这个文件上会出现TortoiseSVN的图标，要解决这种&lt;br /&gt; 冲突要求造成冲突的两个人进行沟通，确定最终的修改方案，然后进行修改，具体操作是右击有冲突图标的文件，选择“编辑冲突”命令，这时就可以对出现冲突&lt;br /&gt; 的文件进行编辑，TortoiseSVN会打开TortoiseMerge，里面会显示别人的修改、你的修改、最终合并的文件，在最终合并的文件中产生冲突的行上右击，根据弹出&lt;br /&gt; 菜单选择使用别人的修改、我的修改还是两个都用，编辑完后保存，关闭TortoiseMerge，然后右击有冲突图标的文件，选择Resolved...(已解决的...)命令后&lt;br /&gt; 确定即可。&lt;br /&gt;&lt;br /&gt;关于“基础版本”及其命令 ---比较差异，检查更新，显示日志，版本分支图&lt;br /&gt;+-------------------------------------------------+-------------------------------------------------&lt;br /&gt;当我们从服务器上CheckOut某个版本，经过一定的修改后，右击修改的文件（注意，不是目录）会有一个“比较差异”命令，调用它会弹出TortoiseMerge，它列出了&lt;br /&gt;当前修改的工作拷贝与我们CheckOut时用到的版本之间的差异，这个被我们CheckOut的版本称为当前工作拷贝的“基础版本”，注意，基础版本不一定是最新版本，最新版&lt;br /&gt;本也不一定是基础版本，比如另一个人和我们CheckOut同一个版本，它在我们之前提交了一份修改会形成一个最新版本----这时，我们进行提交可能造成冲突。&lt;br /&gt;刚才说过，只有文件才会有“比较差异”命令，而目录没有，有没有办法看到目录的变化呢？--肯定有，是哪个呢？先试一下第一个---“显示日志”，结果不行，它只&lt;br /&gt;显示的是当前工作拷贝对应的服务器目录或文件的版本变化记录，从第一个版本到最新版本，一个也不缺。“版本分支图”也一样，它是“显示日志”命令的图形化显示，&lt;br /&gt;功能和“显示日志”完全一样。答案是----“检查更新”，它比较的是当前工作拷贝相对于基础版本的更新记录，不仅能显示文件的变化，也能显示目录的增减等。&lt;br /&gt;Revert (复原) 和 Update to version&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;当你CheckOut并修改了文件后，如果在提交前发现修改不正确，可以用Revert来取消这次的修改，使文件回到基础版本的状态；如果已经提交，可以用Update to Version&lt;br /&gt;(更新至版本)返回某个旧的版本，或者调用显示日志命令，在任意一处日志上单击，在下方会出现修改记录，右击某一记录，在弹出菜单中选择Save Revision to(保存版本至)&lt;br /&gt;，也可以把原来版本进行存档。需要注意的是，你的本地工作拷贝可以返回到原来的版本，可是服务器上只会记录你对它进行最后一个提交的版本，所以服务器端版本不&lt;br /&gt;会 变化，如果你想把服务器端的文档内容也换为原来的状态，可以用旧版本文件覆盖新版本文件，然后提交，或者使用Revert changes from this revision 和 Revert to this revision命令，她们的用法在本文档中有，自己找找，调用显示日志命令，在任意一处日志上右击，在快捷菜单中会出现这两个命令。&lt;br /&gt;注意，Revert命令很危险，它不向Ctrl-Z命令一样一次只撤销一次修改，它的名字是“还原”，它会把所有的修改全部撤销，直接回到基础版本的状态，如果想只撤销&lt;br /&gt;一 次的修改，我的方法是，使用“检查更新”和“比较差异”命令在TortoriseSVN中修改，TortoriseSVN中的"use this text block ","use other text block ","use both text block "等命令很方便，关于这两个命令在本文中也有介绍，自己找。&lt;br /&gt;Revert changes from this revision 跟Revert to this revision的区别？&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;譬如有个文件，有十个版本，假定版本号是1，2，3，4，5，6，7，8，9，10。&lt;br /&gt;&lt;br /&gt; --&gt;1.Revert to this revision（恢复到某个以前的版本）： 如果在版本6这里点击“Revert to this revision",表示7～10的修改全部作废,历史倒退到了版本6那个年代。&lt;br /&gt;  如果你做了多处修改，然后决定要返回到版本 N，你就可以使用这个命令。再次说明，恢复的修改位于你的工作复本，在你提交之前，并不会影响版本库。&lt;br /&gt;注意，这将会丢弃从那个版本以来的所有修改，使用选中的版本来替换文件/文件夹。&lt;br /&gt;&lt;br /&gt; --&gt;2.Revert changes from this revision（还原选中版本所做的修改）：如果在版本6这里点击“Revert changes from this revision",表示版本6这个历史事件被抹杀了，只剩下9个历史事件了。 如果同时选择了6，7，8三个历史时期并点击“Revert changes from this revision”，表示抹杀6~8这仨历史时期。同理，如果同时选择7～10，然后点击“Revert changes from this revision”，则效果跟在版本6这里点击“Revert to this revision”是一样的。&lt;br /&gt;  还原的内容只在你的工作副本中，所以此操作完全不会影响版本库！要注意的是，这个操作仅仅还原该版本中的修改。不是将整个文件替换成选中的那个版本。&lt;br /&gt;它对于已经做过其它无关修改的还原早期修改非常有用。如果你做了本地修改，此命令将会合并修改到工作副本。&lt;br /&gt;关于“基础版本”及其命令 ---比较差异，检查更新，显示日志，版本分支图&lt;br /&gt;+-------------------------------------------------+-------------------------------------------------&lt;br /&gt;当我们从服务器上CheckOut某个版本，经过一定的修改后，右击修改的文件（注意，不是目录）会有一个“比较差异”命令，调用它会弹出TortoiseMerge，它列出了&lt;br /&gt;当前修改的工作拷贝与我们CheckOut时用到的版本之间的差异，这个被我们CheckOut的版本称为当前工作拷贝的“基础版本”，注意，基础版本不一定是最新版本，最新版&lt;br /&gt;本也不一定是基础版本，比如另一个人和我们CheckOut同一个版本，它在我们之前提交了一份修改会形成一个最新版本----这时，我们进行提交可能造成冲突。&lt;br /&gt;刚才说过，只有文件才会有“比较差异”命令，而目录没有，有没有办法看到目录的变化呢？--肯定有，是哪个呢？先试一下第一个---“显示日志”，结果不行，它只&lt;br /&gt;显示的是当前工作拷贝对应的服务器目录或文件的版本变化记录，从第一个版本到最新版本，一个也不缺。“版本分支图”也一样，它是“显示日志”命令的图形化显示，&lt;br /&gt;功能和“显示日志”完全一样。答案是----“检查更新”，它比较的是当前工作拷贝相对于基础版本的更新记录，不仅能显示文件的变化，也能显示目录的增减等。&lt;br /&gt;Branch &amp;amp; Tag (分支与标记)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;----&gt;1.定义与理解&lt;br /&gt;--&gt;1.1 Branch and Thunk (分支和主线)&lt;br /&gt; 版本控制系统的一个特性是能够把各种修改分离出来放在产品的一个分割线上。这条线被称为Branch（分支）。&lt;br /&gt; 分支经常被用来试验新的特性，而不会对开发有编译错误的干扰。当新的特性足够稳定之后，产品的分支就可以混合回Thunk(主线)里.&lt;br /&gt;&lt;br /&gt;--&gt;1.2 Tag (标记/标签)&lt;br /&gt; 版本控制系统的另一个特性是能够标记特殊的版本(例如某个发布版本)，所以你可以在任何时候重新建立一个特定的构件和环境。这个过程被称作Tag(标记/标签)。&lt;br /&gt;Subversion 没有专门的用于建立分支和标记的特殊命令，它所谓的分支其实就是一个拷贝，把原目录的内容拷到一个新的目录下面。但是这个拷贝的操作不是真正意义&lt;br /&gt;上的拷贝，Subversion称之为"Lean copy"(便宜复制),它类似于Linux的硬链接，实际的操作是建立了一个内部链接，指向那个被建立分支的目录，只有当我们提交一个文件&lt;br /&gt;的修改，才在分支目录下建立一个真实的文件，它的内容就是我们提交的内容，需要注意的时，这时候，除了这个文件以外，其余的文件仍然是作为被建立分支目录下文件的&lt;br /&gt;链接存在的。&lt;br /&gt;采用Lean copy技术的结果是分支和标记能迅速被创建，并且没有在版本库里占据任何额外的空间。&lt;br /&gt;--&gt;1.3 理解Branch&lt;br /&gt;建立分支的情况举例：&lt;br /&gt;a.Project发行版已经完成，正在继续开发Project贺岁版，计划在两个月后发行。不久，客户开始抱怨Project有问题，于是CheckOut（检出）Project的发行版，&lt;br /&gt;找到几个错误，并进行代码更正。但是当前的版本是个不稳定的版本(现在正处于Project2贺岁版的开发中.....)，并且在下个月才能有希望稳定下来，这样就没有办法基于&lt;br /&gt;最新的代码去发行一个修复错误的版本。....这种情况下就可以创建一个Branch(分支)，分支的所有文件是基于Project发行版的，可以修改这个分支而不影响到主干(即当&lt;br /&gt;前正在开发的Project2贺岁版)，当Project2贺岁版完成时，你可以选定是否要把这个分支同主干（Project2贺岁版）合并或继续保留在这个分支里。&lt;br /&gt;b.如果我们在维护一个项目的文档，但有一天，另一个项目也要这份文档，她们有和我们不同的需求，因此要对文档做一些修改才能适应她们的需要，这时，也可以对&lt;br /&gt;这个文档建立一个分支。&lt;br /&gt;c.Branch可以是项目分支，也可以是私有分支。&lt;br /&gt;所谓的项目分支，是指两个项目需要并发开发，它们基于同一个原始版本的拷贝，且这两个项目又互不干扰的进行独立开发，那么这两条开发线对于原来的那个原始版&lt;br /&gt;本来说，就是项目分支，而原始版本就是项目主干。&lt;br /&gt;所谓的私有分支，是指如果多个人共同负责一个模块，当出现两个人同时修改一个文件的同一部分的情况时，就会不断的出现冲突，开发人员就要花大量的时间解决这&lt;br /&gt;些冲突，而在分支上工作避免了频繁的解决冲突，这种分支叫做私有分支，个人可以在主干上建立一个私有分支出来，当开发到一定阶段以后，可以再对自己分支与主干进&lt;br /&gt;行合并，在与主干进行合并的同时，也能关注到其他人在这一段时间内对主干做的修改。&lt;br /&gt;----&gt;2.创建分支&lt;br /&gt;利用TortoiseSVN有两种方法建立分支：&lt;br /&gt;--&gt;1.从本地工作拷贝到服务器建立，在本地工作拷贝右击在弹出菜单中选择“Branch/Tag”会弹出一个对话框，在其中设定要建立分支的URL即可。&lt;br /&gt;--&gt;2.从URL到URL,在Repository Explorer(版本浏览器)中右击要建立分支的目录，在弹出菜单中选择Copy to...(“复制到...”),在弹出对话框设定要建立分支的URL.&lt;br /&gt;----&gt;3.分支的合并&lt;br /&gt;创建分支后一段时间可以根据需要进行Merge(合并)操作，我们既可以将主线的改动合并到分支上，也可以将分支的改动合并到主线上：&lt;br /&gt;--&gt;1.将主线的改动合并到分支上，需要在分支的工作拷贝下进行合并,合并的范围是从主线上上次合并的版本（或建立分支时候的版本）到当前主线上的最新版本，&lt;br /&gt;如果主线和分支都修改了相同的文件的相同部分，合并后会出现冲突，就要进行解决冲突，如果主线修改但是分支没有修改，则主线上合并的变更内容会增加到当前工作&lt;br /&gt;拷贝中，合并的结果会保存到当前的工作拷贝中，提交后改动就会体现在分支中，如果是第一次合并，则起始版本号是上次建立分支的版本号。&lt;br /&gt;--&gt;2.将分支的改动合并到主线中，需要在主线的工作拷贝下进行合并，相关事项与上雷同。&lt;br /&gt;Blame (追溯)&lt;br /&gt;+-------------------------------------------------&lt;br /&gt;这个命令很不错，能显示文件的所有行在哪个版本中被修改及修改的时间，还可以追溯版本库等，有兴趣可以自己研究。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-9009141498196055040?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/9009141498196055040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=9009141498196055040' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/9009141498196055040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/9009141498196055040'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/08/routine-tortoisesvn-operations-2.html' title='routine tortoisesvn operations-2'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1625818527853513785</id><published>2008-08-11T00:08:00.000-07:00</published><updated>2008-08-12T22:03:04.750-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>routine tortoisesvn operations-1</title><content type='html'>接下来, 我们讲一下tortoisesvn的常规操作. update, revert和switch的区别, 这三个命令的图标都是从服务器端到客户端的箭头, 容易搞混.&lt;br /&gt;&lt;br /&gt;1. update是最常用的操作, 就是用来更新本地的work copy, 当然, 如果某个文档是基于svn server的最新版本做了修改,那么update并不会从svn server上download这个文档. 如果你的文档是基于svn server上的一个老版本作了修改, tortoisesvn会让启动一个向导让你解决这个conflict.&lt;br /&gt;&lt;br /&gt;2. revert, 这个操作忽略本地work copy的任何修改, 它直接从svn server上下载被你修改了的文档.&lt;br /&gt;&lt;br /&gt;3. switch, switch是update的一个超强版本, update是从原有的svn folder下取代码的, 而switch可以指定另一个folder的URL(但是仅限于在同一个repository之下的另一个folder), switch操作使得本地的work copy指向新的URL, 同时更新versioned file的footprint信息. 这个操作因为不需要download所有文档的内容, 所以速度很快.&lt;br /&gt;&lt;br /&gt;4. checkout, 就是将svn上的某个directory所有文档都下载到一个本地目录,同时下载文档的footprint信息, 它要求本地目录必须是空目录. 也叫作fresh checkout.&lt;br /&gt;&lt;br /&gt;移动和复制&lt;br /&gt;&lt;br /&gt;当我们对源码结构进行重新组织时, 经常会对versioned file进行复制和移动操作. Tortoisesvn的move和copy命令比较隐蔽, 在tortoisesvn菜单上是找不到这些命令的, 只能是先选中要移动的folder/file, 然后按下鼠标右键, 拖拉到另一个目录, 这时候会出现一个弹出菜单, 其中就有SVN copy和SVN move.&lt;br /&gt;&lt;br /&gt;TortoiseSVN合并和回滚操作&lt;br /&gt;&lt;br /&gt;合并功能是Subversion最大的亮点. 它甚至是改变了我们的开发模式(和Sourcesafe的checkout-lock-checkin模式相比). 当然合并操作本身是很复杂的. 主要有3种合并模式, 需要提醒的是, 合并操作后, 结果仅仅反映到本地的work copy上了, 这时候还没有在svn server上进行merge. 如果你真的要在server上merge的话, 需要再执行commit操作.&lt;br /&gt;&lt;br /&gt;合并模式1-(merge a range of revisions):即同一个branch不同版本的merge, 在这个向导中, 你需要指定一个URL(因为已经有个缺省值, 所以一般情况下你不需关心这个), 然后你要指定一个要merge的版本序列, 这个不好理解, 为什么是一个版本序列呢? 在一般情况下, 你只需要指定一个版本号, 并不需要merge几个版本. 但svn仍然提供了一个让你一次性merge多个版本的功能.&lt;br /&gt;&lt;br /&gt;合并模式2-(reintegrate a branch): 这是subserver提供的一个非常有用的功能, 它可以将我们的另一个branch代码和本地的work copy进行merge.&lt;br /&gt;&lt;br /&gt;合并模式3-(合并两个树): 这应该是三种合并模式中, 最灵活的一种, 选项也最多, 你可以指定两个repository 的URL, 以及相应的版本号码, 然后merge.&lt;br /&gt;&lt;br /&gt;版本回滚: TortoiseSVN的rollback功能放在Show Log的界面上了, 最方便的一个回滚方法是: Revert to this revision, 这个很好理解, 就是将版本回滚到你选定的那个版本上, 点击之后, 会将work copy回滚到刚刚指定的那个版本. 需要commit之后, 才会将这个版本真正地在svn server上了.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1625818527853513785?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1625818527853513785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1625818527853513785' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1625818527853513785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1625818527853513785'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/08/routine-tortoisesvn-operations-1.html' title='routine tortoisesvn operations-1'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1519233339439501252</id><published>2008-07-29T02:29:00.001-07:00</published><updated>2008-07-29T02:36:05.629-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Continuous Integration Tool--CC.Net</title><content type='html'>TeamCity is good tool, the free version is enough for most small-medium projects.&lt;br /&gt;Cruise Control.Net is absolutely free and open source tool. Actually,  it is more hard to configure.&lt;br /&gt;Fortunately, there is a sourceforge project can help you.&lt;br /&gt;cc-config:  &lt;a href="http://cc-config.sourceforge.net/"&gt;http://cc-config.sourceforge.net/ &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;PS,  CC.Net &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;http://cruisecontrol.sourceforge.net/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1519233339439501252?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1519233339439501252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1519233339439501252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1519233339439501252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1519233339439501252'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/continuous-integration-tool-ccnet.html' title='Continuous Integration Tool--CC.Net'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-6012947371150668139</id><published>2008-07-29T01:13:00.000-07:00</published><updated>2008-07-29T02:25:47.297-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Understand TeamCity Work Flow</title><content type='html'>首先可以将TeamCity 看作一个专门Continuous Integration(CI)的Web Portal.  TeamCity可以管理多个Build Agent, ,每个Build Agent可以认为是专门用来编译代码的机器.  当然Build Agent可以和TeamCity是同一台计算机. TeamCity为什么采用多个Build Agent这样的架构呢?&lt;br /&gt;&lt;br /&gt;多个Build Agent的优点:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;主要是考虑到Build代码的过程可能能长, 另外是我们可能又想加入Unit Test的功能, 尤其是Unit Test很多的情况下(或者commit source很频繁), 一台计算机显然不行.  &lt;/li&gt;&lt;li&gt;我们可以将Unit Test按功能分类, 将他们分配到不同的Build Agent上. &lt;/li&gt;&lt;li&gt;我们也可以将Unit Test按工作量进行分配, 将他们分配到不同的Build Agent上.  这其实是Load Balance&lt;/li&gt;&lt;li&gt;提供Pre-Tested commit特性, 详见下文.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;TeamCity的特点:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;TeamCity由Java开发的, 所以是跨平台的,  支持Java和.Net. 它采用Tomcat作为Web Server. &lt;/li&gt;&lt;li&gt;TeamCity支持多种Build工具, Java方面, 你可以选用Ant, Maven, Idea等. .Net方面, 你可以用MSbuild, NAnt以及Visual Studio的Solution文件. &lt;/li&gt;&lt;li&gt;Pre-Tested Commit(Delayed commit)方式: 应该说这是TeamCity杀手级的特性(killer feature). 相信我们都遇到过这样的情况, 有的程序员嫌跑所有的单元测试太费时间,  测试了部分Unit Test就将代码提交到VCS上(或者根本没有跑Unit Test). 结果很不幸, 那些没有测试的case结果却跑不通. 你不得不将代码rollback, 其过程之痛苦不用多言.  TeamCity介绍了Pre-Tested提交这个特性, 可以彻底解决这个问题. 它是为IDE提供TeamCity的插件来触发这个过程. 详细流程见下文的TeamCity的一般工作流程.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;TeamCity的一般工作流程是(&lt;a href="http://lh3.ggpht.com/WadeLiu2008/SI7S4a_H4YI/AAAAAAAAAIA/0eHv4_nisuw/Windows_Teamcity_overview.PNG?imgmax=144"&gt;Workflow_Diagram&lt;/a&gt;):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Programmer在IDE中通过TeamCity的Pre-Tested commit将代码check in到VCS Server&lt;/li&gt;&lt;li&gt;TeamCity根据其Trigger设置, 定时从VCS Server取代码, 然后将代码发送到Build Agent中. 指派Agent 去执行响应的Build和Unit Test 操作.&lt;/li&gt;&lt;li&gt;Build Agent完成操作后, 将结果返回给TeamCity.&lt;/li&gt;&lt;li&gt;如果结果正确的话, 则将Code 真正提交到VCS.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-6012947371150668139?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/6012947371150668139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=6012947371150668139' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6012947371150668139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6012947371150668139'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/understand-teamcity-work-flow.html' title='Understand TeamCity Work Flow'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-5723113623866734018</id><published>2008-07-28T22:13:00.000-07:00</published><updated>2008-07-29T01:13:49.819-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Continuous Integration Tool--TeamCity</title><content type='html'>TeamCity is another famous Continuous Integrating Tool.  It is much easier to configure than CC.Net because TeamCity is allowed to configure through Web UI. The latter one has too many xml files to configure.&lt;br /&gt;&lt;br /&gt;Product Site &lt;a href="http://www.jetbrains.com/teamcity/"&gt;http://www.jetbrains.com/teamcity/&lt;/a&gt;&lt;br /&gt;Free Version License Including&lt;br /&gt;&lt;ul&gt;&lt;li&gt;3 Build Agents at no additional cost&lt;/li&gt;&lt;li&gt;20 User Accounts&lt;/li&gt;&lt;li&gt;20 Build Configurations&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;More detail Info, View the following blogs,&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Our Build Config--TeamCity(&lt;a href="http://blog.eleutian.com/2008/03/07/OurBuildConfigurations.aspx"&gt;http://blog.eleutian.com/2008/03/07/OurBuildConfigurations.aspx&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;CruiseControl.NET is dead. Long live Team City!(&lt;a href="http://blog.eleutian.com/2007/12/22/CruiseControlNETIsDeadLongLiveTeamCity.aspx"&gt;http://blog.eleutian.com/2007/12/22/CruiseControlNETIsDeadLongLiveTeamCity.aspx&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Integration of NCover into Team City for Tech Head Brothers(&lt;a href="http://weblogs.asp.net/lkempe/archive/2008/03/30/integration-of-ncover-into-team-city-for-tech-head-brothers.aspx"&gt;http://weblogs.asp.net/lkempe/archive/2008/03/30/integration-of-ncover-into-team-city-for-tech-head-brothers.aspx&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Continuous Integration Revisited(&lt;a href="http://www.zorched.net/2006/08/10/continuous-integration-revisited/"&gt;http://www.zorched.net/2006/08/10/continuous-integration-revisited/&lt;/a&gt;)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-5723113623866734018?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/5723113623866734018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=5723113623866734018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5723113623866734018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5723113623866734018'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/continuous-integration-tool-teamcity.html' title='Continuous Integration Tool--TeamCity'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-5095258529883130530</id><published>2008-07-28T22:00:00.000-07:00</published><updated>2008-07-28T22:03:37.969-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>NDbUnit Framework</title><content type='html'>NDbUnit test is a good UnitTest framework if you are familiar with C#. But this project seems not active since 2006.&lt;br /&gt;Home Page:  &lt;a href="http://qualitylabs.org/projects/ndbunit/"&gt;http://qualitylabs.org/projects/ndbunit/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-5095258529883130530?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/5095258529883130530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=5095258529883130530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5095258529883130530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5095258529883130530'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/ndbunit-framework.html' title='NDbUnit Framework'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-5098912261669820523</id><published>2008-07-28T00:39:00.000-07:00</published><updated>2008-07-28T00:42:10.795-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scalability-Performance'/><title type='text'>How to increase scalability--InfoQ article</title><content type='html'>&lt;a href="http://www.infoq.com/articles/scalability-panel"&gt;http://www.infoq.com/articles/scalability-panel&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-5098912261669820523?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/5098912261669820523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=5098912261669820523' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5098912261669820523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5098912261669820523'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/how-to-increase-scalability-infoq.html' title='How to increase scalability--InfoQ article'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-280339262722203655</id><published>2008-07-24T23:15:00.000-07:00</published><updated>2008-07-24T23:24:43.043-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WebService'/><title type='text'>WSE-enabled web service to authenticate by user/password</title><content type='html'>WSE is short for web service enhancement.&lt;br /&gt;&lt;br /&gt;WSE 1 user/password authentication&lt;br /&gt;  1. &lt;a href="http://www.eggheadcafe.com/articles/20021227.asp"&gt;http://www.eggheadcafe.com/articles/20021227.asp  &lt;/a&gt;   &lt;br /&gt;  2.&lt;a href="http://www.devx.com/security/Article/15634/1954"&gt;http://www.devx.com/security/Article/15634/1954&lt;/a&gt;&lt;br /&gt;  3.&lt;a href="http://www.eggheadcafe.com/articles/20021231.asp"&gt; http://www.eggheadcafe.com/articles/20021231.asp &lt;/a&gt; ( X509 certification )&lt;br /&gt;    &lt;br /&gt;WSE 3 &lt;br /&gt;   1. &lt;a href="http://geeknotes.wordpress.com/2007/03/16/a-simple-wse-30-web-service-to-authorize-by-username-and-password/"&gt;http://geeknotes.wordpress.com/2007/03/16/a-simple-wse-30-web-service-to-authorize-by-username-and-password/&lt;/a&gt;&lt;br /&gt;  2. &lt;a href="http://blog.nerdbank.net/2006/03/wse3-and-aspnet-membership-provider.html"&gt;http://blog.nerdbank.net/2006/03/wse3-and-aspnet-membership-provider.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-280339262722203655?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/280339262722203655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=280339262722203655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/280339262722203655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/280339262722203655'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/wse-enabled-web-service-to-authenticate.html' title='WSE-enabled web service to authenticate by user/password'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7610919457146440488</id><published>2008-07-24T19:48:00.000-07:00</published><updated>2008-07-24T20:01:02.196-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>version control with TortoiseSVN without SVN Server</title><content type='html'>If you only have a limited number of users, and do not need remote access, you can use Tortoise without a subversion server. This makes set-up much easier.&lt;br /&gt;   Steps:&lt;br /&gt;   1. Install TortoiseSVN software&lt;br /&gt;   2. Open Windows Explorer.&lt;br /&gt;   3. Create a empty folder as your repository, this can be local or on network drive.&lt;br /&gt;   4. Right click the empty folder, and then click on "&lt;span style="font-weight: bold;"&gt;Create repository here&lt;/span&gt;".&lt;br /&gt;   5. Then you can use TortoiseSVN--Repository browser to manage your repository directory. Maybe you can add such directories.&lt;br /&gt;      -project_a&lt;br /&gt;              -trunk&lt;br /&gt;              -branches&lt;br /&gt;              -tags &lt;br /&gt;   6. After the first 5 steps. you can do any operations just like the repository on a SVN Server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7610919457146440488?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7610919457146440488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7610919457146440488' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7610919457146440488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7610919457146440488'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/version-control-with-tortoisesvn.html' title='version control with TortoiseSVN without SVN Server'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-4632452839131556161</id><published>2008-07-24T19:22:00.000-07:00</published><updated>2008-07-24T19:48:18.863-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>How to arrange the svn repository layout</title><content type='html'>&lt;p&gt;怎样组织ｓｖｎ的目录其实非常有学问，比如我们是要将多个项目放在一个ｓｖｎ　ｒｅｐｏｓｉｔｏｒｙ下，　还是为每个项目都建立一个独立的ｓｖｎ　ｒｅｐｏｓｉｔｏｒｙ呢？　实际上，　这两种做法各有优缺点．　&lt;/p&gt;&lt;p&gt;使用单一ｓｖｎ　ｒｅｐｏｓｉｔｏｒｙ的优点是：只需要维护一个ｓｖｎ库，工作量自然会少了很多，　这里维护工作包括ｒｏｕｔｉｎｅｌｙ　ｂａｃｋｕｐ，ｄｕｍｐ以及升级ｓｖｎ软件．　当然缺点也很明显：　一个项目的开发人员可以访问另一个项目的文件，另外一个严重的缺点是，每个项目的ｃｏｍｍｉｔ　ｅｍａｉｌ　ｌｉｓｔ很可能不同，　但如果在一个ｒｅｐｏｓｉｔｏｒｙ下，就不能为不同的项目配置不同的ｅｍａｉｌ　ｌｉｓｔ，　这样一旦项目Ａ被ｃｏｍｍｉｔ，项目Ｂ的也会收到ｃｏｍｍｉｔ　ｅｍａｉｌ．　&lt;br /&gt;&lt;/p&gt;&lt;p&gt;下面是一个多项目的repository结构，　但项目的ｒｅｐｏｓｉｔｏｒｙ也可参照这个．&lt;/p&gt;&lt;p&gt;要说明的是ｔｒｕｎｋ，ｂｒａｎｃｈｅｓ和ｔａｇｓ的意义，　ｔｒｕｎｋ里面维护着是项目的主要开发版本．　ｂｒａｎｃｈｅｓ是ｔｒｕｎｋ版本的各类分支版本．ｔａｇｓ是保存着ｔｒｕｎｋ和ｂｒａｎｃｈｅｓ的某一时刻的快照．　&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre class="screen"&gt;/&lt;br /&gt; calc/&lt;br /&gt;    trunk/&lt;br /&gt;    tags/&lt;br /&gt;    branches/&lt;br /&gt; calendar/&lt;br /&gt;    trunk/&lt;br /&gt;    tags/&lt;br /&gt;    branches/&lt;br /&gt; spreadsheet/&lt;br /&gt;    trunk/&lt;br /&gt;    tags/&lt;br /&gt;    branches/&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-4632452839131556161?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/4632452839131556161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=4632452839131556161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4632452839131556161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4632452839131556161'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/07/how-to-arrange-svn-repository.html' title='How to arrange the svn repository layout'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1244790484030777584</id><published>2008-06-30T00:28:00.000-07:00</published><updated>2009-01-05T21:15:18.712-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Install Subversion server on windows computer</title><content type='html'>步骤1,  创建一个空目录, 比如d:/source&lt;br /&gt;步骤2,  打开d:\source目录, 使用windows explorer的context menu中tortoisesvn/create a repository here菜单项, 在d:\source中创建必要的repository控制文件和数据库文件.&lt;br /&gt;步骤3, 创建一个svn service服务, 并将服务的工作目录指向d:\source即可.  下面有详细的步骤.&lt;br /&gt;&lt;br /&gt;We can register subversion service. the steps are easy. Windows system have a sc command tool to help you register.&lt;br /&gt;If path of subversion contains space or other chars that must be escaped, then you must enclose the path to svnserve.exe with double-quotes, which themselves must be quoted using a backslash. Fortunately the syntax is similar to that on Unix platforms:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Create service methods: &lt;/span&gt;&lt;br /&gt;1)On your computer if the path of svnserve.exe does not contain spaces&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;sc create subversion_local   binpath= "c:\svn\bin\svnserve.exe --service -r d:\source" displayname= "Local Subversion Repository" depend= Tcpip&lt;/span&gt;&lt;br /&gt; 删除这个服务的命令是 sc delete subversion_local&lt;br /&gt;2)On your computer if the path of svnserve.exe contains spaces&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;sc create subversion_local binpath= "\"c:\program files\subversion\bin\svnserve.exe\" --service -r d:\source" displayname= "Local Subversion Repository" depend= Tcpip&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Access the subversion repository&lt;/span&gt;&lt;/span&gt; by tortoiseSVN, you need a repository url.&lt;br /&gt;1)Browse the repository on local computer,the repository url is just like,&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt; file:///d:/source/docs&lt;/span&gt;&lt;br /&gt;2)Browse the repository on remote computer, 前提是computer22机器上的source/docs必须共享出来, 这样才能通过file协议来访问. 访问方式是:&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt; file:///\computer22/source/docs&lt;br /&gt;&lt;/span&gt;这是基于file协议的svn访问方式, 多人项目最好不用file协议(因为共享目录安全性较差, 无法做到精细化权限管理). 最好是用svn协议或https协议. 参见我的另一blog( &lt;a href="http://focuswindows.blogspot.com/2008/08/svn-authorization.html"&gt;svn authorization)&lt;/a&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;3)Browse the repository across internet, the repository url is just like,&lt;br /&gt;https://xxxx.svn.sourceforge.net/svnroot/xxxx&lt;br /&gt;&lt;br /&gt;more info : http://svn.collab.net/repos/svn/trunk/notes/windows-service.txt&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1244790484030777584?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1244790484030777584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1244790484030777584' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1244790484030777584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1244790484030777584'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/06/install-subversion-service-on-windows.html' title='Install Subversion server on windows computer'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-4697710576279454794</id><published>2008-06-23T19:50:00.000-07:00</published><updated>2008-06-30T00:55:06.781-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Software dev environment</title><content type='html'>1. Version control tool&lt;br /&gt;SubVersion and TortoiseSVN&lt;br /&gt;2. A bug administration tool&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mantis&lt;/span&gt;,  hosted by sourceforge,  &lt;a href="http://www.mantisbt.org/download.php"&gt;http://www.mantisbt.org/download.php &lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Trac&lt;/span&gt;, this is a open source bug admin web system. and it provides an interface to subversion, and it has an integrated Wiki and reporting facilities.   &lt;a href="http://trac.edgewall.org/"&gt;http://trac.edgewall.org/&lt;/a&gt;&lt;br /&gt;3. Continuous Build Tool&lt;br /&gt; CruiseControl.net  http://www.codeproject.com/KB/architecture/ContinuousIntegration.aspx&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-4697710576279454794?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/4697710576279454794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=4697710576279454794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4697710576279454794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4697710576279454794'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/06/software-dev-environment.html' title='Software dev environment'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-6655865185628427310</id><published>2008-06-23T19:35:00.000-07:00</published><updated>2008-06-30T00:55:47.420-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delphi'/><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Delphi software dev  environment</title><content type='html'>1. IDE Expert tools&lt;br /&gt;  GExpert, www.gexperts.org&lt;br /&gt;  DelphiSpeedUp, http://andy.jgknet.de/dspeedup/&lt;br /&gt;  DDevExtensions,  http://andy.jgknet.de/dspeedup/index.php?page=DDevExtensions&lt;br /&gt;  DelforExp, Format Expert&lt;br /&gt;&lt;br /&gt;2. Dunit and DUnitLite&lt;br /&gt;  http://dunit.sourceforge.net/&lt;br /&gt;  http://code.google.com/p/dunitlite &lt;br /&gt;&lt;br /&gt;3. madExcept, this is an excellent exception catcher&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-6655865185628427310?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/6655865185628427310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=6655865185628427310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6655865185628427310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6655865185628427310'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/06/delphi-software-dev-environment.html' title='Delphi software dev  environment'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-387866853710783184</id><published>2008-06-10T22:49:00.000-07:00</published><updated>2008-09-11T20:50:16.129-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><title type='text'>Freesoftware and opensoftwares</title><content type='html'>优秀开源和免费软件下载网站有:&lt;br /&gt;http://portableapps.com/&lt;br /&gt;http://nirsoft.net/&lt;br /&gt;http://www.pendriveapps.com/&lt;br /&gt;http://www.downloadsquad.com/&lt;br /&gt;http://www.osalt.com/&lt;br /&gt;&lt;br /&gt;24 Killer Portable Apps For Your USB Flash Drive&lt;br /&gt;http://www.downloadsquad.com/2008/09/02/24-killer-portable-apps-for-your-usb-flash-drive/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Database Browser(Portable Edition,支持Oracle, SQL Server,ODBC)&lt;br /&gt;http://www.dbsoftlab.com/index.php/Freeware/Database-Browser.html&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;NetSetManagement (portable Edition) 方便切换多个IP和网关&lt;br /&gt;http://www.pendriveapps.com/2008/03/31/netsetman-portable-network-settings-manager/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;WinDirStatPortable(分析磁盘文件的占用情况)&lt;br /&gt;http://portableapps.com/apps/utilities/windirstat_portable&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PidginPortable(MSN, QQ等IM 客户端)&lt;br /&gt;http://portableapps.com/apps/internet/pidgin_portable&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;EraserPortable(securely Delete file/folder)&lt;br /&gt;http://portableapps.com/apps/utilities/eraser_portable&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;MyUninstaller(非常好用的卸载工具)&lt;br /&gt;http://www.nirsoft.net/utils/myuninst.html&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sumatra PDF Portable (PDF Reader)&lt;br /&gt;http://portableapps.com/apps/office/sumatra_pdf_portable&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Keepass--Protect your password&lt;br /&gt;  http://keepass.info/&lt;br /&gt;&lt;br /&gt;italc--Local network computer projector, for team learning and team computer control.&lt;br /&gt;  http://italc.sourceforge.net&lt;br /&gt;&lt;br /&gt;Desktops--Virtual Windows desktop manager, just like linux multi-desktop&lt;br /&gt;  http://technet.microsoft.com/en-us/sysinternals/cc817881.aspx&lt;br /&gt;&lt;br /&gt;EyeDefender--Alert you when you have used computer for a period&lt;br /&gt;  http://eterlab.com/&lt;br /&gt;&lt;br /&gt;Locate--Just the linux locate command&lt;br /&gt;  http://locate32.webhop.org/&lt;br /&gt;&lt;br /&gt;WordWeb--English thesaurus and dictionary lookup&lt;br /&gt;http://wordweb.info/free/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-387866853710783184?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/387866853710783184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=387866853710783184' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/387866853710783184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/387866853710783184'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/06/freesoftware-and-opensoftwares.html' title='Freesoftware and opensoftwares'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-4442259837977716207</id><published>2008-06-04T00:40:00.000-07:00</published><updated>2008-06-30T00:56:27.209-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCM'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>how to change file folder in subversion</title><content type='html'>Subversion是一个非常好的Source版本控制软件.&lt;br /&gt;TortoiseSVN是一个Windows平台上Subversion客户端. 操作非常方便, 但有一个问题是: 在TortoiseSVN的菜单中, 怎么也找不到Move file to...或者是change file folder这样的菜单项目, 不知道怎样才能移动文件.&lt;br /&gt;google一搜, 才发现不仅仅是我有这样的困惑.&lt;br /&gt;实际上TortoiseSVN已经考虑了这个问题, 只不过它不是将功能体现在菜单项上,  右键拖拉一个文件到一个versioned folder, 就会出现看到TortoiseSVN已经为你提供了移动功能.&lt;br /&gt;&lt;br /&gt;http://svn.haxx.se/tsvnusers/archive-2006-02/0167.shtml&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-4442259837977716207?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/4442259837977716207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=4442259837977716207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4442259837977716207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4442259837977716207'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/06/how-to-change-file-folder-in-subversion.html' title='how to change file folder in subversion'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2592972550055648230</id><published>2008-05-26T22:08:00.002-07:00</published><updated>2008-05-26T22:12:47.798-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>C_Sharp edition StringList Class</title><content type='html'>Delphi有一个常用的类StringList, 它有一个特点是你可以一行一行加String, 如果你所加的每行String都是Name=Value格式的,它会帮你提取出Name列表和Value列表, 这个类我在用Delphi时候, 常使用它.  下面是C#版的StringList类.&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LiuHarry.Utils.Foundation&lt;br /&gt;{&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.InteropServices;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DelphiStrList&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; M_Items = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; M_Keys = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; M_KeyValueEqualmark = &lt;span class="str"&gt;"="&lt;/span&gt;;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; M_Values = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(&lt;span class="kwrd"&gt;string&lt;/span&gt; item)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; str;&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; str2;&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.Add(item);&lt;br /&gt;           DivideKeyValue(item, &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_KeyValueEqualmark, &lt;span class="kwrd"&gt;out&lt;/span&gt; str2, &lt;span class="kwrd"&gt;out&lt;/span&gt; str);&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.Add(str2);&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.Add(str);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Clear()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.Clear();&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.Clear();&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.Clear();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DevideKeyValuesByItems()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.Clear();&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.Clear();&lt;br /&gt;           &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; str3 &lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; str;&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; str2;&lt;br /&gt;               DivideKeyValue(str3, &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_KeyValueEqualmark, &lt;span class="kwrd"&gt;out&lt;/span&gt; str2, &lt;span class="kwrd"&gt;out&lt;/span&gt; str);&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.Add(str2);&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.Add(str);&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DivideKeyValue(&lt;span class="kwrd"&gt;string&lt;/span&gt; entireStr, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyValueEqualmark, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; keyStr, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; valueStr)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;int&lt;/span&gt; index = entireStr.IndexOf(keyValueEqualmark);&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (index &amp;gt; 0)&lt;br /&gt;           {&lt;br /&gt;               keyStr = entireStr.Substring(0, index);&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; (index &amp;lt; (entireStr.Length - 1))&lt;br /&gt;               {&lt;br /&gt;                   valueStr = entireStr.Substring(index + 1);&lt;br /&gt;               }&lt;br /&gt;               &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;               {&lt;br /&gt;                   valueStr = &lt;span class="str"&gt;""&lt;/span&gt;;&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;           {&lt;br /&gt;               keyStr = entireStr;&lt;br /&gt;               valueStr = &lt;span class="str"&gt;""&lt;/span&gt;;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; IndexOf(&lt;span class="kwrd"&gt;string&lt;/span&gt; item)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.IndexOf(item);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Insert(&lt;span class="kwrd"&gt;int&lt;/span&gt; index, &lt;span class="kwrd"&gt;string&lt;/span&gt; item)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; str;&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; str2;&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.Insert(index, item);&lt;br /&gt;           DivideKeyValue(item, &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_KeyValueEqualmark, &lt;span class="kwrd"&gt;out&lt;/span&gt; str2, &lt;span class="kwrd"&gt;out&lt;/span&gt; str);&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.Insert(index, str2);&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.Insert(index, str);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MakeItemsToText(&lt;span class="kwrd"&gt;string&lt;/span&gt; ItemSeperator)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.MakeStrlistToText(&lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items, ItemSeperator);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MakeKeyItemsToText(&lt;span class="kwrd"&gt;string&lt;/span&gt; ItemSeperator)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.MakeStrlistToText(&lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys, ItemSeperator);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MakeStrlistToText(List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; items, &lt;span class="kwrd"&gt;string&lt;/span&gt; ItemSeperator)&lt;br /&gt;       {&lt;br /&gt;           StringBuilder builder = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();&lt;br /&gt;           &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; str &lt;span class="kwrd"&gt;in&lt;/span&gt; items)&lt;br /&gt;           {&lt;br /&gt;               builder.Append(str);&lt;br /&gt;               builder.Append(ItemSeperator);&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; builder.ToString();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MakeValueItemsToText(&lt;span class="kwrd"&gt;string&lt;/span&gt; ItemSeperator)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.MakeStrlistToText(&lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys, ItemSeperator);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;string&lt;/span&gt; item)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;int&lt;/span&gt; index = &lt;span class="kwrd"&gt;this&lt;/span&gt;.IndexOf(item);&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (index &amp;gt;= 0)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.RemoveAt(index);&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.RemoveAt(index);&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.Remove(item);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RemoveAt(&lt;span class="kwrd"&gt;int&lt;/span&gt; index)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.RemoveAt(index);&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys.RemoveAt(index);&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values.RemoveAt(index);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Sort()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.Sort();&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.DevideKeyValuesByItems();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Count&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items.Count;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; Items&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Items;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; Keys&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Keys;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; KeyValueEqualmark&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_KeyValueEqualmark;&lt;br /&gt;           }&lt;br /&gt;           set&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_KeyValueEqualmark = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; Values&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.M_Values;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2592972550055648230?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2592972550055648230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2592972550055648230' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2592972550055648230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2592972550055648230'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/csharp-edition-stringlist-class.html' title='C_Sharp edition StringList Class'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3383249754225315674</id><published>2008-05-26T21:48:00.000-07:00</published><updated>2008-05-26T22:06:44.711-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to hide or show TabPage of TabControl</title><content type='html'>C# 的TabControl功能严重不足, 尤其是你用它来制作Wizard界面时候, 下面代码会有所帮助的.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LiuHarry.Utils.Components&lt;br /&gt;{&lt;br /&gt;  &lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;  &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Forms;&lt;br /&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TabControlHelper&lt;br /&gt;  {&lt;br /&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; TabControl m_tabControl;&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;public&lt;/span&gt; TabControlHelper(TabControl tabCtrl)&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl = tabCtrl;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; HideTabPage(TabPage tp)&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Contains(tp))&lt;br /&gt;          {&lt;br /&gt;              &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Remove(tp);&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertTabPage(TabPage tabpage, &lt;span class="kwrd"&gt;int&lt;/span&gt; index)&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; ((index &amp;lt; 0) || (index &amp;gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabCount))&lt;br /&gt;          {&lt;br /&gt;              &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Index out of Range."&lt;/span&gt;);&lt;br /&gt;          }&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Add(tabpage);&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (index &amp;lt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabCount - 1))&lt;br /&gt;          {&lt;br /&gt;              &lt;span class="kwrd"&gt;do&lt;/span&gt;&lt;br /&gt;              {&lt;br /&gt;                  &lt;span class="kwrd"&gt;this&lt;/span&gt;.SwapTabPages(tabpage, &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages[&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.IndexOf(tabpage) - 1]);&lt;br /&gt;              }&lt;br /&gt;              &lt;span class="kwrd"&gt;while&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.IndexOf(tabpage) != index);&lt;br /&gt;          }&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.SelectedTab = tabpage;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ShowTabPage(TabPage tp)&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.ShowTabPage(tp, &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Count);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ShowTabPage(TabPage tp, &lt;span class="kwrd"&gt;int&lt;/span&gt; index)&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Contains(tp))&lt;br /&gt;          {&lt;br /&gt;              &lt;span class="kwrd"&gt;this&lt;/span&gt;.InsertTabPage(tp, index);&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SwapTabPages(TabPage tp1, TabPage tp2)&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (!(&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Contains(tp1) &amp;amp;&amp;amp; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.Contains(tp2)))&lt;br /&gt;          {&lt;br /&gt;              &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"TabPages must be in the TabControls TabPageCollection."&lt;/span&gt;);&lt;br /&gt;          }&lt;br /&gt;          &lt;span class="kwrd"&gt;int&lt;/span&gt; index = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.IndexOf(tp1);&lt;br /&gt;          &lt;span class="kwrd"&gt;int&lt;/span&gt; num2 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages.IndexOf(tp2);&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages[index] = tp2;&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.TabPages[num2] = tp1;&lt;br /&gt;          &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.SelectedIndex = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_tabControl.SelectedIndex;&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; text = tp1.Text;&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; str2 = tp2.Text;&lt;br /&gt;          tp1.Text = str2;&lt;br /&gt;          tp2.Text = text;&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3383249754225315674?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3383249754225315674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3383249754225315674' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3383249754225315674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3383249754225315674'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/how.html' title='How to hide or show TabPage of TabControl'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-4356223487410248736</id><published>2008-05-26T21:42:00.001-07:00</published><updated>2008-05-26T21:46:34.877-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>DataGridViewHelper class</title><content type='html'>&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;DataGridView这个控件在开发中经常会被用到,  C#的组件总觉得不如Delphi组件那么容易使用, 怎样在Grid上选择一个Row, 怎样选择一个Cell, 我就被block了好久. 下面是代码:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LiuHarry.Utils.Components&lt;br /&gt;{&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Forms;&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DataGridViewHelper&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; DataGridView m_DataGridView;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; SortedList&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; m_MapListFieldColumn = &lt;span class="kwrd"&gt;new&lt;/span&gt; SortedList&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; DataView m_ShowedDataViewInGrid;&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; DataGridViewHelper(DataGridView dataGridView, DataView showedDataViewInGrid)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView = dataGridView;&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ShowedDataViewInGrid = showedDataViewInGrid;&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.InitFieldColumnMapList();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _GetGridViewColumnName(&lt;span class="kwrd"&gt;string&lt;/span&gt; dataFieldName)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.Columns.Count; i++)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.Columns[i].DataPropertyName == dataFieldName)&lt;br /&gt;               {&lt;br /&gt;                   &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.Columns[i].Name;&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;""&lt;/span&gt;;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InitFieldColumnMapList()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_MapListFieldColumn.Clear();&lt;br /&gt;           &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ShowedDataViewInGrid.Table.Columns.Count; i++)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; columnName = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ShowedDataViewInGrid.Table.Columns[i].ColumnName;&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; str2 = &lt;span class="kwrd"&gt;this&lt;/span&gt;._GetGridViewColumnName(columnName);&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_MapListFieldColumn.Add(columnName, str2);&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; QuickFindGridViewColumnName(&lt;span class="kwrd"&gt;string&lt;/span&gt; dataFieldName)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;int&lt;/span&gt; num = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_MapListFieldColumn.IndexOfKey(dataFieldName);&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (num &amp;lt; 0)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"There no a column in DataGridView corresponding DataFieldName="&lt;/span&gt; + dataFieldName);&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_MapListFieldColumn.Values[num];&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SelectAndScrollToCell(&lt;span class="kwrd"&gt;string&lt;/span&gt; fieldName, &lt;span class="kwrd"&gt;object&lt;/span&gt; fieldValue)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.ClearSelection();&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; ((fieldName != &lt;span class="kwrd"&gt;null&lt;/span&gt;) &amp;amp;&amp;amp; (fieldValue != &lt;span class="kwrd"&gt;null&lt;/span&gt;))&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; str = &lt;span class="kwrd"&gt;this&lt;/span&gt;.QuickFindGridViewColumnName(fieldName);&lt;br /&gt;               &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataGridViewRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; (IEnumerable) &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.Rows)&lt;br /&gt;               {&lt;br /&gt;                   &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;object&lt;/span&gt;.Equals(row.Cells[str].Value, fieldValue))&lt;br /&gt;                   {&lt;br /&gt;                       &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.CurrentCell = row.Cells[str];&lt;br /&gt;                       &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.CurrentCell.Selected = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;                       &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                   }&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SelectRow(&lt;span class="kwrd"&gt;object&lt;/span&gt; valueOfSortedField)&lt;br /&gt;       {&lt;br /&gt;           DataView showedDataViewInGrid = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ShowedDataViewInGrid;&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.ClearSelection();&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; ((showedDataViewInGrid != &lt;span class="kwrd"&gt;null&lt;/span&gt;) &amp;amp;&amp;amp; (valueOfSortedField != &lt;span class="kwrd"&gt;null&lt;/span&gt;))&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;int&lt;/span&gt; num = showedDataViewInGrid.Find(valueOfSortedField);&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; (num &amp;gt;= 0)&lt;br /&gt;               {&lt;br /&gt;                   &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_DataGridView.Rows[num].Selected = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; SortedList&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; MapListFieldColumn&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_MapListFieldColumn;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-4356223487410248736?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/4356223487410248736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=4356223487410248736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4356223487410248736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4356223487410248736'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/datagridviewhelper-class.html' title='DataGridViewHelper class'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1592974473902747038</id><published>2008-05-26T21:24:00.000-07:00</published><updated>2008-05-26T21:28:24.708-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>SQL Execute Trace Helper Class</title><content type='html'>&lt;a href="http://focuswindows.blogspot.com/2008/01/sql-executing-monitor-code.html"&gt;http://focuswindows.blogspot.com/2008/01/sql-executing-monitor-code.html&lt;/a&gt;&lt;br /&gt;该版本可能不是最新的,  最新的代码应该是下面:&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LiuHarry.Utils.DB&lt;br /&gt;{&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; LiuHarry.Utils.Foundation;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;&lt;br /&gt;   &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Reflection;&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SqlExecuteTracer : IDisposable&lt;br /&gt;   {&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; disposed = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; m_ErrorLogFile;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; m_ErrorLogFileSuffix = &lt;span class="str"&gt;"SqlError.txt"&lt;/span&gt;;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; m_LogSqlExecute = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; m_SqlLogFile;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; m_SqlLogFileSuffix = &lt;span class="str"&gt;"SqlLog.txt"&lt;/span&gt;;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; TextWriterTraceListener m_SqlLogListener;&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; SqlExecuteTracer()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; assemblyFileWithoutExt = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetAssemblyFileWithoutExt();&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ErrorLogFile = assemblyFileWithoutExt + &lt;span class="str"&gt;"_"&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ErrorLogFileSuffix;&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogFile = assemblyFileWithoutExt + &lt;span class="str"&gt;"_"&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogFileSuffix;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.Dispose(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;br /&gt;           GC.SuppressFinalize(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose(&lt;span class="kwrd"&gt;bool&lt;/span&gt; disposing)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;this&lt;/span&gt;.disposed &amp;amp;&amp;amp; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogListener.Close();&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;this&lt;/span&gt;.disposed = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetAssemblyFileWithoutExt()&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; location = Assembly.GetExecutingAssembly().Location;&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; (Path.GetDirectoryName(location) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(location));&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetSqlFromCommand(IDbCommand cmd)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;string&lt;/span&gt; commandText = cmd.CommandText;&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (cmd.Parameters.Count &amp;lt;= 0)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; commandText;&lt;br /&gt;           }&lt;br /&gt;           DelphiStrList list = &lt;span class="kwrd"&gt;new&lt;/span&gt; DelphiStrList();&lt;br /&gt;           &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (IDbDataParameter parameter &lt;span class="kwrd"&gt;in&lt;/span&gt; cmd.Parameters)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; (parameter.Value != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;               {&lt;br /&gt;                   list.Add(parameter.ParameterName + &lt;span class="str"&gt;"="&lt;/span&gt; + parameter.Value.ToString());&lt;br /&gt;               }&lt;br /&gt;               &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;               {&lt;br /&gt;                   list.Add(parameter.ParameterName + &lt;span class="str"&gt;"=NULL"&lt;/span&gt;);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;           &lt;span class="kwrd"&gt;return&lt;/span&gt; (commandText + Environment.NewLine + list.MakeItemsToText(Environment.NewLine));&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TraceErrorSqlToLog(IDbCommand cmd, &lt;span class="kwrd"&gt;string&lt;/span&gt; ErrorMessage)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;using&lt;/span&gt; (TraceListener listener = &lt;span class="kwrd"&gt;new&lt;/span&gt; TextWriterTraceListener(&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ErrorLogFile))&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; sqlFromCommand = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetSqlFromCommand(cmd);&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.TraceSqlToLogListener(sqlFromCommand, ErrorMessage, listener);&lt;br /&gt;               listener.Close();&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TraceErrorSqlToLog(&lt;span class="kwrd"&gt;string&lt;/span&gt; sql, &lt;span class="kwrd"&gt;string&lt;/span&gt; ErrorMessage)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;using&lt;/span&gt; (TraceListener listener = &lt;span class="kwrd"&gt;new&lt;/span&gt; TextWriterTraceListener(&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ErrorLogFile))&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.TraceSqlToLogListener(sql, ErrorMessage, listener);&lt;br /&gt;               listener.Close();&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TraceSqlToLog(IDbCommand cmd)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;string&lt;/span&gt; sqlFromCommand = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetSqlFromCommand(cmd);&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.TraceSqlToLogListener(sqlFromCommand, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogListener);&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TraceSqlToLog(&lt;span class="kwrd"&gt;string&lt;/span&gt; sql)&lt;br /&gt;       {&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute)&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.TraceSqlToLogListener(sql, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogListener);&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TraceSqlToLogListener(&lt;span class="kwrd"&gt;string&lt;/span&gt; sql, &lt;span class="kwrd"&gt;string&lt;/span&gt; ErrorInfo, TraceListener listener)&lt;br /&gt;       {&lt;br /&gt;           listener.WriteLine(&lt;span class="str"&gt;"==================================="&lt;/span&gt;);&lt;br /&gt;           listener.WriteLine(DateTime.Now.ToString());&lt;br /&gt;           &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(ErrorInfo))&lt;br /&gt;           {&lt;br /&gt;               listener.WriteLine(&lt;span class="str"&gt;"Error Info:"&lt;/span&gt;);&lt;br /&gt;               listener.WriteLine(ErrorInfo);&lt;br /&gt;               listener.WriteLine(&lt;span class="str"&gt;"SQL:"&lt;/span&gt;);&lt;br /&gt;           }&lt;br /&gt;           listener.WriteLine(sql);&lt;br /&gt;           listener.WriteLine(&lt;span class="str"&gt;"==================================="&lt;/span&gt;);&lt;br /&gt;           listener.WriteLine(&lt;span class="str"&gt;""&lt;/span&gt;);&lt;br /&gt;           listener.Flush();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; LogSqlExecute&lt;br /&gt;       {&lt;br /&gt;           get&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute;&lt;br /&gt;           }&lt;br /&gt;           set&lt;br /&gt;           {&lt;br /&gt;               &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;               &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute &amp;amp;&amp;amp; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogListener == &lt;span class="kwrd"&gt;null&lt;/span&gt;))&lt;br /&gt;               {&lt;br /&gt;                   &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogListener = &lt;span class="kwrd"&gt;new&lt;/span&gt; TextWriterTraceListener(&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlLogFile);&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1592974473902747038?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1592974473902747038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1592974473902747038' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1592974473902747038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1592974473902747038'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/sql-execute-trace-helper-class.html' title='SQL Execute Trace Helper Class'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8091902217879222</id><published>2008-05-26T21:22:00.000-07:00</published><updated>2008-05-26T21:24:29.563-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>SQLite Dataset Helper Class</title><content type='html'>&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LiuHarry.Utils.DB&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data;&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data.SQLite;&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.InteropServices;&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SqliteDataSetHelper : IDisposable&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; DELETED_FLAG;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; disposed;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; INSERTED_FLAG;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; m_ConnectionString;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; m_LogSqlExecute;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; m_SelfBuildConnection;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; SQLiteConnection m_SqlConn;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; SqlExecuteTracer m_SqlExecuteTracer;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; MODIFIED_FLAG;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; PARAMETER_NAME_PREFIX;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; PARAMETER_PREFIX;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SqliteDataSetHelper()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SelfBuildConnection = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.DELETED_FLAG = &lt;span class="str"&gt;"DELETED_FLAG"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.INSERTED_FLAG = &lt;span class="str"&gt;"INSERTED_FLAG"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.MODIFIED_FLAG = &lt;span class="str"&gt;"MODIFIED_FLAG"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_PREFIX = &lt;span class="str"&gt;"@"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_NAME_PREFIX = &lt;span class="str"&gt;"@"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.disposed = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlExecuteTracer();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SqliteDataSetHelper(SQLiteConnection conn) : &lt;span class="kwrd"&gt;this&lt;/span&gt;()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (conn != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SelfBuildConnection = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn = conn;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SqliteDataSetHelper(&lt;span class="kwrd"&gt;string&lt;/span&gt; connectionString) : &lt;span class="kwrd"&gt;this&lt;/span&gt;()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ConnectionString = connectionString;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ActivateConnection()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteConnection(&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ConnectionString);&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SelfBuildConnection = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DeleteRows(List&amp;lt;DataRow&amp;gt; listRows, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; listRows)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToDeleteState(row);&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerDeleteRow(row, tableName, keyFieldName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DeleteRows(List&amp;lt;&lt;span class="kwrd"&gt;long&lt;/span&gt;&amp;gt; listRowKeyFieldValue, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; num &lt;span class="kwrd"&gt;in&lt;/span&gt; listRowKeyFieldValue)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerDeleteRowByKeyField(num, tableName, keyFieldName, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;long&lt;/span&gt;));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DeleteRows(List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; listRowKeyFieldValue, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; str &lt;span class="kwrd"&gt;in&lt;/span&gt; listRowKeyFieldValue)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerDeleteRowByKeyField(str, tableName, keyFieldName, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DeleteRows(DataRow row, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToDeleteState(row);&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerDeleteRow(row, tableName, keyFieldName);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Dispose(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;br /&gt;            GC.SuppressFinalize(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose(&lt;span class="kwrd"&gt;bool&lt;/span&gt; disposing)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;this&lt;/span&gt;.disposed)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryCloseConnection();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.disposed = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ExecCommand(SQLiteCommand sqlcom)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; num2;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ActivateConnection();&lt;br /&gt;            sqlcom.Connection = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn;&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryOpenConnection();&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceSqlToLog(sqlcom);&lt;br /&gt;                num2 = sqlcom.ExecuteNonQuery();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception exception)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceErrorSqlToLog(sqlcom, exception.Message);&lt;br /&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; exception;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryCloseConnection();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; num2;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ExecCommand(&lt;span class="kwrd"&gt;string&lt;/span&gt; sql)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (sql.EndsWith(&lt;span class="str"&gt;","&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                sql = sql.Substring(0, sql.Length - 1);&lt;br /&gt;            }&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(sql);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecCommand(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SQLiteDataReader ExecDataReader(SQLiteCommand sqlcom)&lt;br /&gt;        {&lt;br /&gt;            SQLiteDataReader reader;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ActivateConnection();&lt;br /&gt;            sqlcom.Connection = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn;&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryOpenConnection();&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceSqlToLog(sqlcom);&lt;br /&gt;                reader = sqlcom.ExecuteReader();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception exception)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceErrorSqlToLog(sqlcom, exception.Message);&lt;br /&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; exception;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryCloseConnection();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; reader;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; SQLiteDataReader ExecDataReader(&lt;span class="kwrd"&gt;string&lt;/span&gt; sqlSelect)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (sqlSelect.EndsWith(&lt;span class="str"&gt;","&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                sqlSelect = sqlSelect.Substring(0, sqlSelect.Length - 1);&lt;br /&gt;            }&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(sqlSelect);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecDataReader(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DataTable ExecDataTable(SQLiteCommand sqlcom)&lt;br /&gt;        {&lt;br /&gt;            DataTable table2;&lt;br /&gt;            DataTable dataTable = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataTable();&lt;br /&gt;            SQLiteDataAdapter adapter = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteDataAdapter(sqlcom);&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ActivateConnection();&lt;br /&gt;            sqlcom.Connection = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn;&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryOpenConnection();&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceSqlToLog(sqlcom);&lt;br /&gt;                adapter.Fill(dataTable);&lt;br /&gt;                table2 = dataTable;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception exception)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceErrorSqlToLog(sqlcom, exception.Message);&lt;br /&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; exception;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryCloseConnection();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; table2;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DataTable ExecDataTable(&lt;span class="kwrd"&gt;string&lt;/span&gt; sqlSelect)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (sqlSelect.EndsWith(&lt;span class="str"&gt;","&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                sqlSelect = sqlSelect.Substring(0, sqlSelect.Length - 1);&lt;br /&gt;            }&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(sqlSelect);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecDataTable(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; ExecScalar(SQLiteCommand sqlcom)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;object&lt;/span&gt; obj2;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ActivateConnection();&lt;br /&gt;            sqlcom.Connection = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn;&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryOpenConnection();&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceSqlToLog(sqlcom);&lt;br /&gt;                obj2 = sqlcom.ExecuteScalar();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception exception)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.TraceErrorSqlToLog(sqlcom, exception.Message);&lt;br /&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; exception;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.TryCloseConnection();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; obj2;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; ExecScalar(&lt;span class="kwrd"&gt;string&lt;/span&gt; sqlSelect)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (sqlSelect.EndsWith(&lt;span class="str"&gt;","&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                sqlSelect = sqlSelect.Substring(0, sqlSelect.Length - 1);&lt;br /&gt;            }&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(sqlSelect);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecScalar(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        ~SqliteDataSetHelper()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Dispose(&lt;span class="kwrd"&gt;false&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime GetDbTime()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; commandText = &lt;span class="str"&gt;"select datetime('NOW')  "&lt;/span&gt;;&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(commandText);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (DateTime) &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecScalar(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; DbType GetDbType(Type type)&lt;br /&gt;        {&lt;br /&gt;            DbType guid = DbType.String;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt;)) || type.IsEnum)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.Int32;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;long&lt;/span&gt;)))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.Int32;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;double&lt;/span&gt;)) || type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;double&lt;/span&gt;)))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.Decimal;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(DateTime)))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.DateTime;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;)))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.Boolean;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;)))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.String;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;decimal&lt;/span&gt;)))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.Decimal;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;byte&lt;/span&gt;[])))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; DbType.Binary;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Equals(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Guid)))&lt;br /&gt;            {&lt;br /&gt;                guid = DbType.Guid;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; guid;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; GetMaxID(&lt;span class="kwrd"&gt;string&lt;/span&gt; primaryKeyField, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName)&lt;br /&gt;        {&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(&lt;span class="str"&gt;"Select Max("&lt;/span&gt; + primaryKeyField + &lt;span class="str"&gt;") from "&lt;/span&gt; + tableName);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;long&lt;/span&gt;) &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecScalar(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InnerDeleteRow(DataRow dr, &lt;span class="kwrd"&gt;string&lt;/span&gt; TableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; format = &lt;span class="str"&gt;"Delete from {0} where {1} ="&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_PREFIX + &lt;span class="str"&gt;"{1}"&lt;/span&gt;;&lt;br /&gt;            DataTable table = dr.Table;&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(format, TableName, keyFieldName));&lt;br /&gt;            IDataParameter parameter = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteParameter();&lt;br /&gt;            parameter.ParameterName = &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_NAME_PREFIX + keyFieldName;&lt;br /&gt;            parameter.DbType = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetDbType(table.Columns[keyFieldName].DataType);&lt;br /&gt;            parameter.Value = dr[keyFieldName];&lt;br /&gt;            sqlcom.Parameters.Add(parameter);&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecCommand(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InnerDeleteRowByKeyField(&lt;span class="kwrd"&gt;object&lt;/span&gt; RowKeyFieldValue, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName, Type keyFieldType)&lt;br /&gt;        {&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Delete from {0} where {1} ="&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_PREFIX + &lt;span class="str"&gt;"{1}"&lt;/span&gt;, tableName, keyFieldName));&lt;br /&gt;            IDataParameter parameter = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteParameter();&lt;br /&gt;            parameter.ParameterName = &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_NAME_PREFIX + keyFieldName;&lt;br /&gt;            parameter.DbType = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetDbType(keyFieldType);&lt;br /&gt;            parameter.Value = RowKeyFieldValue;&lt;br /&gt;            sqlcom.Parameters.Add(parameter);&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecCommand(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InnerInsertRow(DataRow dr, &lt;span class="kwrd"&gt;string&lt;/span&gt; TableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; primaryKeyField, &lt;span class="kwrd"&gt;bool&lt;/span&gt; primaryKeyValueIsAutoGenerated, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; primaryKeyValue)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; format = &lt;span class="str"&gt;"Insert into {0}({1}) values ({2})"&lt;/span&gt;;&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand();&lt;br /&gt;            DataTable table = dr.Table;&lt;br /&gt;            StringBuilder builder = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();&lt;br /&gt;            StringBuilder builder2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();&lt;br /&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; dr.Table.Columns.Count; i++)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!primaryKeyValueIsAutoGenerated || !(table.Columns[i].ColumnName == primaryKeyField))&lt;br /&gt;                {&lt;br /&gt;                    IDataParameter parameter = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteParameter();&lt;br /&gt;                    parameter.ParameterName = &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_NAME_PREFIX + table.Columns[i].ColumnName;&lt;br /&gt;                    parameter.DbType = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetDbType(table.Columns[i].DataType);&lt;br /&gt;                    parameter.Value = dr[i];&lt;br /&gt;                    sqlcom.Parameters.Add(parameter);&lt;br /&gt;                    builder2.Append(table.Columns[i].ColumnName);&lt;br /&gt;                    builder.Append(&lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_PREFIX + table.Columns[i].ColumnName);&lt;br /&gt;                    builder2.Append(&lt;span class="str"&gt;","&lt;/span&gt;);&lt;br /&gt;                    builder.Append(&lt;span class="str"&gt;","&lt;/span&gt;);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str2 = builder2.ToString();&lt;br /&gt;            str2 = str2.Substring(0, str2.Length - 1);&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str3 = builder.ToString();&lt;br /&gt;            str3 = str3.Substring(0, str3.Length - 1);&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str4 = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(format, TableName, str2, str3);&lt;br /&gt;            sqlcom.CommandText = str4;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecCommand(sqlcom);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!primaryKeyValueIsAutoGenerated)&lt;br /&gt;            {&lt;br /&gt;                primaryKeyValue = 0L;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                SQLiteCommand command2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand(&lt;span class="str"&gt;"Select Max("&lt;/span&gt; + primaryKeyField + &lt;span class="str"&gt;") from "&lt;/span&gt; + TableName);&lt;br /&gt;                &lt;span class="kwrd"&gt;object&lt;/span&gt; obj2 = &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecScalar(command2);&lt;br /&gt;                primaryKeyValue = (&lt;span class="kwrd"&gt;long&lt;/span&gt;) obj2;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InnerModifyRow(DataRow dr, &lt;span class="kwrd"&gt;string&lt;/span&gt; TableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; format = &lt;span class="str"&gt;"Update {0} set {1} {2}"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str2 = &lt;span class="str"&gt;"{0}= "&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_PREFIX + &lt;span class="str"&gt;"{0}"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str3 = &lt;span class="str"&gt;" Where {0}="&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_PREFIX + &lt;span class="str"&gt;"{0}"&lt;/span&gt;;&lt;br /&gt;            StringBuilder builder = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();&lt;br /&gt;            SQLiteCommand sqlcom = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteCommand();&lt;br /&gt;            DataTable table = dr.Table;&lt;br /&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; dr.Table.Columns.Count; i++)&lt;br /&gt;            {&lt;br /&gt;                IDataParameter parameter = &lt;span class="kwrd"&gt;new&lt;/span&gt; SQLiteParameter();&lt;br /&gt;                parameter.ParameterName = &lt;span class="kwrd"&gt;this&lt;/span&gt;.PARAMETER_NAME_PREFIX + table.Columns[i].ColumnName;&lt;br /&gt;                parameter.DbType = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetDbType(table.Columns[i].DataType);&lt;br /&gt;                parameter.Value = dr[i];&lt;br /&gt;                sqlcom.Parameters.Add(parameter);&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (table.Columns[i].ColumnName == keyFieldName)&lt;br /&gt;                {&lt;br /&gt;                    str3 = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(str3, keyFieldName);&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    builder.Append(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(str2, table.Columns[i].ColumnName));&lt;br /&gt;                    builder.Append(&lt;span class="str"&gt;","&lt;/span&gt;);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str4 = builder.ToString();&lt;br /&gt;            str4 = str4.Substring(0, str4.Length - 1);&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; str5 = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(format, TableName, str4, str3);&lt;br /&gt;            sqlcom.CommandText = str5;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecCommand(sqlcom);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertRows(List&amp;lt;DataRow&amp;gt; listRows, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; listRows)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InsertRows(row, tableName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertRows(DataRow row, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;long&lt;/span&gt; num;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToInsertState(row);&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; primaryKeyField = &lt;span class="str"&gt;""&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;bool&lt;/span&gt; primaryKeyValueIsAutoGenerated = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerInsertRow(row, tableName, primaryKeyField, primaryKeyValueIsAutoGenerated, &lt;span class="kwrd"&gt;out&lt;/span&gt; num);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertRows(List&amp;lt;DataRow&amp;gt; listRows, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; primaryKeyField, &lt;span class="kwrd"&gt;bool&lt;/span&gt; primaryKeyValueIsAutoGenerated, &lt;span class="kwrd"&gt;out&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;long&lt;/span&gt;&amp;gt; listPrimaryKeyValue)&lt;br /&gt;        {&lt;br /&gt;            listPrimaryKeyValue = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;long&lt;/span&gt;&amp;gt;();&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; listRows)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;long&lt;/span&gt; num;&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToInsertState(row);&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerInsertRow(row, tableName, primaryKeyField, primaryKeyValueIsAutoGenerated, &lt;span class="kwrd"&gt;out&lt;/span&gt; num);&lt;br /&gt;                listPrimaryKeyValue.Add(num);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertRows(DataRow row, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; primaryKeyField, &lt;span class="kwrd"&gt;bool&lt;/span&gt; primaryKeyValueIsAutoGenerated, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; primaryKeyValue)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToInsertState(row);&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerInsertRow(row, tableName, primaryKeyField, primaryKeyValueIsAutoGenerated, &lt;span class="kwrd"&gt;out&lt;/span&gt; primaryKeyValue);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ModifyRows(List&amp;lt;DataRow&amp;gt; listRows, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; listRows)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToModifyState(row);&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerModifyRow(row, tableName, keyFieldName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ModifyRows(DataRow row, &lt;span class="kwrd"&gt;string&lt;/span&gt; tableName, &lt;span class="kwrd"&gt;string&lt;/span&gt; keyFieldName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetToModifyState(row);&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.InnerModifyRow(row, tableName, keyFieldName);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetToDeleteState(DataRow row)&lt;br /&gt;        {&lt;br /&gt;            row.RowError = &lt;span class="kwrd"&gt;this&lt;/span&gt;.DELETED_FLAG;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetToInsertState(DataRow row)&lt;br /&gt;        {&lt;br /&gt;            row.RowError = &lt;span class="kwrd"&gt;this&lt;/span&gt;.INSERTED_FLAG;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetToModifyState(DataRow row)&lt;br /&gt;        {&lt;br /&gt;            row.RowError = &lt;span class="kwrd"&gt;this&lt;/span&gt;.MODIFIED_FLAG;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TryCloseConnection()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SelfBuildConnection &amp;amp;&amp;amp; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn != &lt;span class="kwrd"&gt;null&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn.Close();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TryOpenConnection()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SelfBuildConnection)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlConn.Open();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConnectionString&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ConnectionString;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_ConnectionString = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; LogSqlExecute&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_SqlExecuteTracer.LogSqlExecute = &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_LogSqlExecute;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8091902217879222?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8091902217879222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8091902217879222' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8091902217879222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8091902217879222'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/sqlite-dataset-helper-class.html' title='SQLite Dataset Helper Class'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2701735319237302722</id><published>2008-05-26T21:09:00.000-07:00</published><updated>2008-05-26T21:17:12.447-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Managed ExecuteShell API</title><content type='html'>&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LiuHarry.Utils.Foundation&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CommandShell&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; RunCmd(&lt;span class="kwrd"&gt;string&lt;/span&gt; command)&lt;br /&gt;        {&lt;br /&gt;            Process process = &lt;span class="kwrd"&gt;new&lt;/span&gt; Process();&lt;br /&gt;            process.StartInfo.FileName = &lt;span class="str"&gt;"cmd.exe"&lt;/span&gt;;&lt;br /&gt;            process.StartInfo.Arguments = &lt;span class="str"&gt;"/c "&lt;/span&gt; + command;&lt;br /&gt;            process.StartInfo.UseShellExecute = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            process.StartInfo.RedirectStandardInput = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            process.StartInfo.RedirectStandardOutput = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            process.StartInfo.RedirectStandardError = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            process.StartInfo.CreateNoWindow = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            process.Start();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; process.StandardOutput.ReadToEnd();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CallWindowsApp()&lt;br /&gt;        {&lt;br /&gt;            System.Diagnostics.Process proc = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Diagnostics.Process();&lt;br /&gt;            proc.EnableRaisingEvents=&lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span class="rem"&gt;//call calculator&lt;/span&gt;&lt;br /&gt;            proc.StartInfo.FileName=&lt;span class="str"&gt;"calc"&lt;/span&gt;;&lt;br /&gt;            proc.Start();&lt;br /&gt;        }   &lt;br /&gt;        &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; GotoWebSite()&lt;br /&gt;        {&lt;br /&gt;            System.Diagnostics.Process proc = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Diagnostics.Process();&lt;br /&gt;            proc.EnableRaisingEvents=&lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            proc.StartInfo.FileName=&lt;span class="str"&gt;"iexplore"&lt;/span&gt;;&lt;br /&gt;            proc.StartInfo.Arguments=http:&lt;span class="rem"&gt;//www.microsoft.com;&lt;/span&gt;&lt;br /&gt;            proc.Start();&lt;br /&gt;            proc.WaitForExit();&lt;br /&gt;            MessageBox.Show(&lt;span class="str"&gt;"You have just visited www.microsoft.com"&lt;/span&gt;);        &lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OpenWordDocument()&lt;br /&gt;        {&lt;br /&gt;            System.Diagnostics.Process proc = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Diagnostics.Process();&lt;br /&gt;            proc.EnableRaisingEvents=&lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            proc.StartInfo.FileName=&lt;span class="str"&gt;"winword"&lt;/span&gt;;&lt;br /&gt;            proc.StartInfo.Arguments=&lt;span class="str"&gt;"C:\\Dotnetstuff\\TestWordDoc.doc"&lt;/span&gt;;&lt;br /&gt;            proc.Start();        &lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ExecuteBatchFile()&lt;br /&gt;        {&lt;br /&gt;            System.Diagnostics.Process proc = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Diagnostics.Process();&lt;br /&gt;            proc.EnableRaisingEvents=&lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            proc.StartInfo.FileName=&lt;span class="str"&gt;"c:\\dotnetstuff\\netdrv.bat"&lt;/span&gt;;&lt;br /&gt;            proc.Start();&lt;br /&gt;            MessageBox.Show(&lt;span class="str"&gt;"Map Drive Created"&lt;/span&gt;);        &lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2701735319237302722?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2701735319237302722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2701735319237302722' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2701735319237302722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2701735319237302722'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/managed-executeshell-api.html' title='Managed ExecuteShell API'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1187469459019753667</id><published>2008-05-26T18:42:00.000-07:00</published><updated>2008-05-26T19:34:21.182-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to create a new XmlElement</title><content type='html'>XmlNode是一个Context相关的对象, 你不能直接调用XmlNode的构造子来创建一个XmlNode. 要创建一个XmlNode有两个方法. 假设要在xmlParentNode下创建一个newNode.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;方法１：&lt;/span&gt;　通过XmlDocument的CreateElement方法创建一个XmlNode&lt;br /&gt;　　public XmlElement CreateElement(prefix,localName,namespaceURI)，如果元素带有namespace,必须加上namespaceURI，　比如：&lt;br /&gt;步骤1:XmlElement newNode= docNode.CreateElement("w", "br", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");&lt;br /&gt;步骤2:xmlParentNode.InsertAfter(br, rNode.FirstChild);&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;方法2:&lt;/span&gt; 不是直接创建XmlElement，而是通过修改xmlParentNode的InnerXml文本，　来增加一个节点．&lt;span style="font-style: italic; color: rgb(255, 0, 0);"&gt;记住：如果新加的内容包含前缀，一定要加上namespace URI．否则会报错的．&lt;/span&gt;　　 &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;xmlParentNode.InnerXml=　&lt;span class="str"&gt;@"&amp;lt;w:r xmlns:w="&lt;/span&gt;&lt;span class="str"&gt;"http://schemas.openxmlformats.org/wordprocessingml/2006/main"&lt;/span&gt;&lt;span class="str"&gt;"&amp;gt;&amp;lt;w:rPr&amp;gt;&lt;br /&gt;                &amp;lt;/w:rPr&amp;gt;&lt;br /&gt;                &amp;lt;w:br/&amp;gt;&lt;br /&gt;                &amp;lt;w:t&amp;gt;Some string &amp;lt;/w:t&amp;gt;&amp;lt;/w:r&amp;gt;"&lt;/span&gt;;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1187469459019753667?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1187469459019753667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1187469459019753667' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1187469459019753667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1187469459019753667'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/how-to-create-new-xml.html' title='How to create a new XmlElement'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7063840839474404333</id><published>2008-05-21T20:16:00.000-07:00</published><updated>2008-05-27T19:15:27.446-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DesignPattern'/><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Thread safe Singleton pattern</title><content type='html'>&lt;span id="c__e"&gt;&lt;b id="jpu3"&gt;关于Singleton模式的几个误区&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;网上有很多Singleton模式的样板, 多数是错误的, 下面的文档提出了很好的样板.&lt;br /&gt;http://msdn.microsoft.com/en-us/library/ms998558.aspx&lt;br /&gt;http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=486&lt;br /&gt;http://www.yoda.arachsys.com/csharp/singleton.html&lt;br /&gt;http://codebetter.com/blogs/steve.hebert/archive/2005/12/16/135697.aspx&lt;br /&gt;另外特别说明的是:&lt;br /&gt;1. Singleton class的Instance属性或者公开方法GetInstance()不应带参数,  也就是说无论在什么情况下获取Singleton类的对象, 都始终是那一个, 不会有不同的实例.&lt;br /&gt;2. Singleton类不能是Static类, 因为Static类不能包含任何实例方法(包括实例constructor).  但Singleton类一定要包含一个static变量(比如_Instance, 其类型为Singleton)来存储Singleton类的实例, 那为什么必须是static变量呢? 因为我们在使用Singleton类的时候, 不是通过constructor类创建一个Singleton对象, 而是需要通过调用一个static方法(比如GetInstance())来创建一个实例, 而static方法只能使用static变量, 不能使用任何非static变量, 这就要求存放Singleton实例的内部变量必须是static变量.&lt;br /&gt;3. Singleton类必须要使用lock, 否则就不是线程安全的, 除非_Instance这个static变量, 同时被声明为readonly.&lt;br /&gt;4. 一般情况下, 不要Singleton模式, 不必使用Double check+Lock这样的代码, 因为写法复杂, 而且容易会造成线程不安全. 尤其是在多核机器上. 可以直接使用Single Check+Lock写法, 简单而又安全.&lt;br /&gt;&lt;span id="obs3"&gt;&lt;div id="czua"&gt;&lt;table id="aa99" style="color: rgb(0, 0, 0);" border="1" cellpadding="3" cellspacing="0" width="100%"&gt;&lt;tbody id="m2hm"&gt;&lt;tr id="q9:0"&gt;&lt;td id="umzl" width="50%"&gt;&lt;span id="jj4n"&gt;&lt;b id="ow1."&gt;Bad Code&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/td&gt;&lt;td id="x6ow" width="50%"&gt;&lt;span id="iwy9"&gt;&lt;b id="j0r1"&gt;Good Code&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="u:mm"&gt;&lt;td id="no28" width="50%"&gt;&lt;span id="obs3"&gt; &lt;pre id="umim"&gt;&lt;span id="mpnm" class="Attention"&gt;// Bad code! Do not use! Not Thread safe, &lt;/span&gt;&lt;a id="ctl00_rs1_mainContentContainer_ctl30" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl30',this);" href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html"&gt;&lt;/a&gt;&lt;br /&gt;&lt;span id="yak3" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="jt:e" class="Modifier"&gt;sealed&lt;/span&gt; &lt;span id="ks4o" class="ReferenceType"&gt;class&lt;/span&gt; Singleton&lt;br /&gt;{&lt;br /&gt;&lt;span id="phdf" class="Modifier"&gt;static&lt;/span&gt; Singleton instance=&lt;span id="nf20" class="Keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;span id="y0a1" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="fdn_" class="Modifier"&gt;static&lt;/span&gt; Singleton Instance&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;      &lt;span id="n1rs" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="cqzq" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;      {&lt;br /&gt;          instance = &lt;span id="n25n" class="Keyword"&gt;new&lt;/span&gt; Singleton();&lt;br /&gt;      }&lt;br /&gt;      &lt;span id="yi:e" class="Statement"&gt;return&lt;/span&gt; instance;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt; &lt;/span&gt;&lt;/td&gt;&lt;td id="d8uc" width="50%"&gt;&lt;span id="obs3"&gt;&lt;span id="obs3"&gt;&lt;pre id="umim"&gt;&lt;span id="mpnm" class="Attention"&gt;//Thread safe, 不是Lazy load, 特点:实现简单&lt;br /&gt;//But performance suffers as a lock is acquired every time the instance is requested&lt;br /&gt;public sealed class Singleton&lt;br /&gt; {&lt;br /&gt;     static Singleton instance = null;&lt;br /&gt;     static readonly object padlock = new object();&lt;br /&gt;&lt;br /&gt;     Singleton()&lt;br /&gt;     {&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     public static Singleton Instance&lt;br /&gt;     {&lt;br /&gt;         get&lt;br /&gt;         {&lt;br /&gt;             lock (padlock)&lt;br /&gt;             {&lt;br /&gt;                 if (instance == null)&lt;br /&gt;                 {&lt;br /&gt;                     instance = new Singleton();&lt;br /&gt;                 }&lt;br /&gt;                 return instance;&lt;br /&gt;             }&lt;br /&gt;         }&lt;br /&gt;     }&lt;br /&gt; }&lt;span style="font-family:Georgia,serif;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="mmi6"&gt;&lt;td id="b5_5" width="50%"&gt;&lt;pre id="x1b9"&gt;&lt;span id="h:tx" class="Attention"&gt;// Try to double Check, But still is not thread safe! Do not use!&lt;/span&gt;&lt;br /&gt;//Thread safe issue see:&lt;span id="mpnm" class="Attention"&gt;&lt;br /&gt;//&lt;/span&gt;&lt;a id="ctl00_rs1_mainContentContainer_ctl30" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl30',this);" href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html"&gt;http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html&lt;/a&gt;&lt;span&gt;&lt;span id="obs3"&gt;&lt;span id="obs3"&gt;&lt;pre id="umim"&gt;&lt;a id="ctl00_rs1_mainContentContainer_ctl30" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl30',this);" href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html"&gt;&lt;/a&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span id="o9:w" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="z.jw" class="Modifier"&gt;sealed&lt;/span&gt; &lt;span id="fo10" class="ReferenceType"&gt;class&lt;/span&gt; Singleton&lt;br /&gt;{&lt;br /&gt;&lt;span id="qmxj" class="Modifier"&gt;static&lt;/span&gt; Singleton instance=&lt;span id="irj:" class="Keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span id="hgqg" class="Modifier"&gt;static&lt;/span&gt; &lt;span id="iboa" class="Modifier"&gt;readonly&lt;/span&gt; &lt;span id="r.l5" class="ReferenceType"&gt;object&lt;/span&gt; padlock = &lt;span id="rjph" class="Keyword"&gt;new&lt;/span&gt; &lt;span id="pi6m" class="ReferenceType"&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span id="ndd6" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="ac:n" class="Modifier"&gt;static&lt;/span&gt; Singleton Instance&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;      &lt;span id="sg0c" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="c0yd" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;      {&lt;br /&gt;          &lt;span id="ue5j" class="Statement"&gt;lock&lt;/span&gt; (padlock)&lt;br /&gt;          {&lt;br /&gt;              &lt;span id="ql9d" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="pnib" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;              {&lt;br /&gt;                  &lt;span id="liue" style="color: rgb(255, 0, 255);"&gt;instance = &lt;span id="w27a" class="Keyword"&gt;new&lt;/span&gt; Singleton();&lt;/span&gt;&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      &lt;span id="v.bb" class="Statement"&gt;return&lt;/span&gt; instance;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;/td&gt;&lt;td id="oy4t" width="50%"&gt;&lt;span id="obs3"&gt; &lt;pre id="x1b9"&gt;//Thread safe,虽然不是Lazy load. 它使用了static Initilization,特点:简单&lt;br /&gt;public sealed class Singleton&lt;br /&gt;{&lt;br /&gt;private static &lt;span style="color: rgb(204, 0, 0);"&gt;readonly &lt;/span&gt;Singleton instance = &lt;span style="color: rgb(204, 0, 0);"&gt;new &lt;/span&gt;Singleton();&lt;br /&gt;&lt;br /&gt;private Singleton(){}&lt;br /&gt;&lt;br /&gt;public static Singleton Instance&lt;br /&gt;{&lt;br /&gt;   get&lt;br /&gt;   {&lt;br /&gt;      return instance;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="vertical-align: top;"&gt;&lt;span&gt;&lt;span id="obs3"&gt;&lt;span id="obs3"&gt;&lt;pre id="x1b9"&gt;&lt;span id="h:tx" class="Attention"&gt;// double Check, Thread not safe&lt;br /&gt;&lt;/span&gt;&lt;span id="obs3"&gt;&lt;pre id="x1b9"&gt;//Thread safe issue see:&lt;span id="mpnm" class="Attention"&gt;&lt;br /&gt;//&lt;/span&gt;&lt;a id="ctl00_rs1_mainContentContainer_ctl30" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl30',this);" href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html"&gt;http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html&lt;/a&gt;&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;&lt;span id="o9:w" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="z.jw" class="Modifier"&gt;sealed&lt;/span&gt; &lt;span id="fo10" class="ReferenceType"&gt;class&lt;/span&gt; Singleton&lt;br /&gt;{&lt;br /&gt;&lt;span id="qmxj" class="Modifier"&gt;static&lt;/span&gt; Singleton instance=&lt;span id="irj:" class="Keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span id="hgqg" class="Modifier"&gt;static&lt;/span&gt; &lt;span id="iboa" class="Modifier"&gt;readonly&lt;/span&gt; &lt;span id="r.l5" class="ReferenceType"&gt;object&lt;/span&gt; padlock = &lt;span id="rjph" class="Keyword"&gt;new&lt;/span&gt; &lt;span id="pi6m" class="ReferenceType"&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span id="ndd6" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="ac:n" class="Modifier"&gt;static&lt;/span&gt; Singleton Instance&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;      &lt;span id="sg0c" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="c0yd" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;      {&lt;br /&gt;          &lt;span id="ue5j" class="Statement"&gt;lock&lt;/span&gt; (padlock)&lt;br /&gt;          {                 &lt;br /&gt;              &lt;span id="ql9d" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="pnib" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;              {&lt;br /&gt;                  //线程不安全,因为编译器会进行代码优化,&lt;br /&gt;                  //临时变量tempInstance会被舍弃,这样就编程了线程不安全代码了&lt;br /&gt;                  Singleton &lt;span id="h6dp" style="color: rgb(255, 0, 255);"&gt;tempInstance=&lt;span id="w27a" class="Keyword"&gt;new&lt;/span&gt; Singleton();                  &lt;br /&gt;                  instance = tempInstance;&lt;/span&gt;&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      &lt;span id="v.bb" class="Statement"&gt;return&lt;/span&gt; instance;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style="vertical-align: top;"&gt;&lt;span&gt;&lt;span id="obs3"&gt;&lt;span id="obs3"&gt;&lt;pre id="x1b9"&gt;&lt;span id="h:tx" class="Attention"&gt;// double Check, Thread safe&lt;/span&gt;&lt;br /&gt;&lt;span id="o9:w" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="z.jw" class="Modifier"&gt;sealed&lt;/span&gt; &lt;span id="fo10" class="ReferenceType"&gt;class&lt;/span&gt; Singleton&lt;br /&gt;{&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;volatile &lt;/span&gt;&lt;span id="qmxj" class="Modifier"&gt;static&lt;/span&gt; Singleton instance=&lt;span id="irj:" class="Keyword"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;span id="hgqg" class="Modifier"&gt;static&lt;/span&gt; &lt;span id="iboa" class="Modifier"&gt;readonly&lt;/span&gt; &lt;span id="r.l5" class="ReferenceType"&gt;object&lt;/span&gt; padlock = &lt;span id="rjph" class="Keyword"&gt;new&lt;/span&gt; &lt;span id="pi6m" class="ReferenceType"&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span id="ndd6" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="ac:n" class="Modifier"&gt;static&lt;/span&gt; Singleton Instance&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;      &lt;span id="sg0c" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="c0yd" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;      {&lt;br /&gt;          &lt;span id="ue5j" class="Statement"&gt;lock&lt;/span&gt; (padlock)&lt;br /&gt;          {&lt;br /&gt;             //线程安全,因为instance被标记为volatile&lt;br /&gt;              &lt;span id="ql9d" class="Statement"&gt;if&lt;/span&gt; (instance==&lt;span id="pnib" class="Keyword"&gt;null&lt;/span&gt;)&lt;br /&gt;              {&lt;br /&gt;                  &lt;span id="h6dp" style="color: rgb(255, 0, 255);"&gt;Instance=&lt;span id="w27a" class="Keyword"&gt;new&lt;/span&gt; Singleton();    &lt;/span&gt;&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      &lt;span id="v.bb" class="Statement"&gt;return&lt;/span&gt; instance;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;div id="spsw"&gt;&lt;table id="kaa2" style="color: rgb(0, 0, 0);" border="1" cellpadding="3" cellspacing="0" width="100%"&gt;&lt;tbody id="h_t9"&gt;&lt;tr id="f8b:"&gt;&lt;td id="tl_w" width="50%"&gt;&lt;span id="obs3"&gt;thread-safe, &lt;/span&gt;not quite as lazy, without using locks&lt;br /&gt;&lt;/td&gt;&lt;td id="t:xa" width="50%"&gt;&lt;span id="obs3"&gt;&lt;span id="obs3"&gt;thread-safe&lt;/span&gt;, f&lt;/span&gt;ully lazy instantiation&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id="esa2"&gt;&lt;td id="vdmx" width="50%"&gt;&lt;pre id="srel"&gt;&lt;span id="c.tb" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="zy5i" class="Modifier"&gt;sealed&lt;/span&gt; &lt;span id="fyrp" class="ReferenceType"&gt;class&lt;/span&gt; Singleton&lt;br /&gt;{&lt;br /&gt;&lt;span id="arw4" class="Modifier"&gt;static&lt;/span&gt; &lt;span id="g8qk" class="Modifier"&gt;readonly&lt;/span&gt; Singleton instance=&lt;span id="t8yp" class="Keyword"&gt;new&lt;/span&gt; Singleton();&lt;br /&gt;&lt;br /&gt;&lt;span id="dflx" class="InlineComment"&gt;// Explicit static constructor to tell C# compiler&lt;/span&gt;&lt;br /&gt;&lt;span id="bl56" class="InlineComment"&gt;// not to mark type as beforefieldinit&lt;/span&gt;&lt;br /&gt;&lt;span id="bxyc" class="Modifier"&gt;static&lt;/span&gt; Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span id="fdt1" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="to26" class="Modifier"&gt;static&lt;/span&gt; Singleton Instance&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;      &lt;span id="l6:7" class="Statement"&gt;return&lt;/span&gt; instance;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;/td&gt;&lt;td id="b13o" width="50%"&gt;&lt;pre id="vy_q"&gt;&lt;span id="wqes" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="iovq" class="Modifier"&gt;sealed&lt;/span&gt; &lt;span id="t:u:" class="ReferenceType"&gt;class&lt;/span&gt; Singleton&lt;br /&gt;{&lt;br /&gt;Singleton()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span id="o4ry" class="Modifier"&gt;public&lt;/span&gt; &lt;span id="l-33" class="Modifier"&gt;static&lt;/span&gt; Singleton Instance&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;      &lt;span id="v-i6" class="Statement"&gt;return&lt;/span&gt; Nested.instance;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span id="xl0b" class="ReferenceType"&gt;class&lt;/span&gt; Nested&lt;br /&gt;{&lt;br /&gt;  &lt;span id="ynl2" class="InlineComment"&gt;// Explicit static constructor to tell C# compiler&lt;/span&gt;&lt;br /&gt;  &lt;span id="rjc4" class="InlineComment"&gt;// not to mark type as beforefieldinit&lt;/span&gt;&lt;br /&gt;  &lt;span id="wa9-" class="Modifier"&gt;static&lt;/span&gt; Nested()&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span id="ji:z" class="Modifier"&gt;internal&lt;/span&gt; &lt;span id="cdbk" class="Modifier"&gt;static&lt;/span&gt; &lt;span id="jw4t" class="Modifier"&gt;readonly&lt;/span&gt; Singleton instance = &lt;span id="dbsj" class="Keyword"&gt;new&lt;/span&gt; Singleton();&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;b id="xh9v"&gt; &lt;/b&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7063840839474404333?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7063840839474404333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7063840839474404333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7063840839474404333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7063840839474404333'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/thread-safe-singleton-pattern.html' title='Thread safe Singleton pattern'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1874248563114593521</id><published>2008-05-06T00:36:00.000-07:00</published><updated>2008-05-06T00:38:44.536-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to design a class which has absolute readonly List property</title><content type='html'>&lt;p&gt;&lt;br /&gt;   &lt;span style="FONT-FAMILY: Courier New"&gt;有时候, 我们设计的类,包含一个Collection对象, 要求该类的使用者可以访问这个Collection属性, 而不能修改Collection的Item, 比如一个容器类.&lt;br /&gt;   如果这个属性是List&amp;lt;T&amp;gt;类型的话, 即使该Collection属性只有getter方法, 也无法阻止容器类的使用者修改的Collection的元素.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;   &lt;span style="FONT-FAMILY: Courier New"&gt;.Net的System.Collections.ObjectModel命名空间中包含一个ReadOnlyCollection&amp;lt;T&amp;gt;,&lt;br /&gt;   可以帮你做到对Collection的绝对只读封装. 其实ReadOnlyCollection类实现了IList&amp;lt;T&amp;gt;接口, 但它没有将Items属性设置public, 而是将它设为protected,&lt;br /&gt;   这样就ReadOnlyCollection对象就不能得到Items属性, 但可以通过属性索引来查的单个元素的值.ReadOnlyCollection的这种实现方法值得好好学习.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;     &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// CtrlContainer的使用者&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Form1 : Form&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Form1()&lt;br /&gt;        {&lt;br /&gt;            InitializeComponent();&lt;br /&gt;        }&lt;br /&gt; &lt;br /&gt;    &lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            CtrlContainer cc = &lt;span class="kwrd"&gt;new&lt;/span&gt; CtrlContainer(&lt;span class="str"&gt;"file1.dfm"&lt;/span&gt;);&lt;br /&gt;            &lt;span class="rem"&gt;//可以通过cc.ListControl属性增加一个元素&lt;/span&gt;&lt;br /&gt;            cc.ListControl.Add(&lt;span class="str"&gt;"ImageBox"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//不能可以通过cc.ReadOnlyListControl属性增加或修改一个元素, 只能读取某个元素&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; firstControlName = cc.ReadOnlyListControl[0];&lt;br /&gt;            MessageBox.Show(firstControlName);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// 一个展现ReadOnlyCollection的Demo Class, &lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// 这个类是一个Control的容器类, 它通过分析一个dfm文件, 获取该文件包含的所有Control,&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// 不允许CtrlContainer类的使用者修改Control的列表&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CtrlContainer&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; m_ListControl = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 这个只读属性其实并不能很好地防止CtrlContainer类的使用者修改m_ListControl的元素, &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 因为他仍然可以使用ListControl.Add()等方法.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; ListControl&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; m_ListControl; } &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;//using System.Collections.ObjectModel;&lt;/span&gt;&lt;br /&gt;        ReadOnlyCollection&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; m_ReadOnlyListControl;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 这个属性可以确保CtrlContainer类的使用者不能修改m_ListControl的元素, 只能读取m_ListControl的元素&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ReadOnlyCollection&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; ReadOnlyListControl&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; m_ReadOnlyListControl; } &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; CtrlContainer(&lt;span class="kwrd"&gt;string&lt;/span&gt; dfmFileName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//parse the dfm file, and extract all controls &lt;/span&gt;&lt;br /&gt;            m_ListControl.Add(&lt;span class="str"&gt;"Button"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;// 因为m_ListControl是以引用的方式传给ReadOnlyCollection, &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;// 所以, 无论是在创建m_ReadOnlyListControl之前或之后, 对m_ListControl的元素进行操作, 都将反映到m_ReadOnlyListControl上&lt;/span&gt;&lt;br /&gt;            m_ReadOnlyListControl = &lt;span class="kwrd"&gt;new&lt;/span&gt; ReadOnlyCollection&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(m_ListControl);&lt;br /&gt;&lt;br /&gt;            m_ListControl.Add(&lt;span class="str"&gt;"Richbox"&lt;/span&gt;);&lt;br /&gt;            m_ListControl.Add(&lt;span class="str"&gt;"ComboBox"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1874248563114593521?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1874248563114593521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1874248563114593521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1874248563114593521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1874248563114593521'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/how-to-design-class-which-has-absolute.html' title='How to design a class which has absolute readonly List property'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-6935694846389196905</id><published>2008-05-05T23:57:00.001-07:00</published><updated>2008-05-05T23:59:31.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>A simple method to parse characteristic text to enum</title><content type='html'>&lt;p&gt;&lt;br /&gt;   设想下面的场景, 我们要解析一个文本文件, 在该文件中包含一些特征文本, 有richbox, 有combobox, 就像是delphi的dfm文件一样. 然后我们要针对不同的特征做不同的处理.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;   这时, 我们往往定义一个枚举类型, 然后读取文本, 根据特征文本, 转成一个枚举值.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;   我以前的做法是定义一个SortedList&amp;lt;string,ControlType&amp;gt;, 其中包含richbox和对应的枚举值. 在解析特征文本的时候, 通过这个SortedList, 就可以得到枚举值.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;   其实, 这个过程也可以使用Enum这个类的Parse()来完成, 前提是你定义的枚举值的名称和特征文本一摸一样(大小写可以不同). 下面是一个示例:&lt;br /&gt;&lt;/p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt;  &lt;span class="kwrd"&gt;class&lt;/span&gt; EnumMapping &lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 根据枚举的名称,返回对应的枚举值&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;enumName&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; ControlType ConvertFromName(&lt;span class="kwrd"&gt;string&lt;/span&gt; enumName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (ControlType)Enum.Parse(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ControlType), enumName, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; ControlType&lt;br /&gt;    {&lt;br /&gt;        richbox,&lt;br /&gt;        combobox,&lt;br /&gt;        image&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-6935694846389196905?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/6935694846389196905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=6935694846389196905' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6935694846389196905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6935694846389196905'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/simple-method-to-parse-characteristic.html' title='A simple method to parse characteristic text to enum'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1269923636529517619</id><published>2008-05-05T22:44:00.000-07:00</published><updated>2008-05-05T23:27:29.266-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to handle xml namespace and xpath by using Linq Xml</title><content type='html'>&lt;p&gt;&lt;br /&gt;   .Net3.5对XML的支持更进一步, 你可以彻底地抛弃Dom处理方式了. 因为XDocument和XElement以及XNode比之前的XmlDocument和XmlNode处理速度更快.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;   下面是一个相对较为复杂的例子, 其中展现了怎样处理Xml的Namespace以及如何使用XPath来定位一个Xml元素.&lt;br /&gt;&lt;/p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 查找所有节点名为p:cNvPr的Xml元素&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;sender&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;e&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button_SelectElementByXPath_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            XDocument xDoc=XDocument.Load(&lt;span class="str"&gt;@&amp;quot;c:\\slide1.xml&amp;quot;&lt;/span&gt;);&lt;br /&gt;            &lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//using System.Xml.XPath &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//  XElement或XDocument之所以有能力处理XPath, 是靠System.Xml.XPath.Extensions这个扩展static类提供的功能&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//  public static IEnumerable&amp;lt;XElement&amp;gt; XPathSelectElements(this XNode node, string expression, IXmlNamespaceResolver resolver)&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//   XPathSelectElements()函数还需要一个参数作为XML Namespace的解析器, 而XmlNamespaceManager类就是一个这样的解析器, &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//  所以还需要引入System.Xml命名空间, 来创建一个XmlNamespaceManager对象&lt;/span&gt;&lt;br /&gt;            &lt;br /&gt;            NameTable nt = &lt;span class="kwrd"&gt;new&lt;/span&gt; NameTable();&lt;br /&gt;            XmlNamespaceManager nameMgr = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlNamespaceManager(nt);&lt;br /&gt;            nameMgr.AddNamespace(&lt;span class="str"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;http://schemas.openxmlformats.org/presentationml/2006/main&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//***注意参数应该是p:cNvPr, 而不是cNvPr&lt;/span&gt;&lt;br /&gt;            var elements = from element &lt;span class="kwrd"&gt;in&lt;/span&gt; xDoc.XPathSelectElements(&lt;span class="str"&gt;&amp;quot;//p:cNvPr&amp;quot;&lt;/span&gt;,nameMgr)&lt;br /&gt;                           select element ;&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var element &lt;span class="kwrd"&gt;in&lt;/span&gt; elements)&lt;br /&gt;            {&lt;br /&gt;                System.Console.Out.Write(element);&lt;br /&gt;                System.Console.Out.WriteLine(&lt;span class="str"&gt;&amp;quot;==============&amp;quot;&lt;/span&gt;);&lt;br /&gt;            }  &lt;br /&gt;              &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 查找所有节点名为p:cNvPr的Xml元素&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;sender&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;e&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button_SelectElementByDescendant_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            XDocument xDoc = XDocument.Load(&lt;span class="str"&gt;@&amp;quot;c:\\slide1.xml&amp;quot;&lt;/span&gt;);&lt;br /&gt;            XNamespace xns = XNamespace.Get(&lt;span class="str"&gt;&amp;quot;http://schemas.openxmlformats.org/presentationml/2006/main&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//public IEnumerable&amp;lt;XElement&amp;gt; Descendants(XName name)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//***注意参数应该是cNvPr, 而不是p:cNvPr&lt;/span&gt;&lt;br /&gt;            var elements1 = from element &lt;span class="kwrd"&gt;in&lt;/span&gt;  xDoc.Descendants(xns.GetName(&lt;span class="str"&gt;&amp;quot;cNvPr&amp;quot;&lt;/span&gt;)) &lt;br /&gt;                           select element ;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//因为XNamespace类重载了加法运算符号, &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//  所以对一个XNamespace对象和一个localName字符串相加, 返回的是一个XName对象,&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//  正是 XElement或XDocument的Descendants()函数所需要的参数类型&lt;/span&gt;&lt;br /&gt;            &lt;br /&gt;            &lt;span class="rem"&gt;//下面代码返回的elements1, 和elements1是完全一样的&lt;/span&gt;&lt;br /&gt;            var elements2 = from element &lt;span class="kwrd"&gt;in&lt;/span&gt;  xDoc.Descendants(xns + &lt;span class="str"&gt;&amp;quot;cNvPr&amp;quot;&lt;/span&gt;)&lt;br /&gt;                           select element ;&lt;br /&gt; &lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt;(var element &lt;span class="kwrd"&gt;in&lt;/span&gt; elements2)&lt;br /&gt;            {&lt;br /&gt;                System.Console.Out.Write(element) ;&lt;br /&gt;                System.Console.Out.WriteLine(&lt;span class="str"&gt;&amp;quot;==============&amp;quot;&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1269923636529517619?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1269923636529517619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1269923636529517619' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1269923636529517619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1269923636529517619'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/05/how-to-handle-xml-namespace-and-xpath.html' title='How to handle xml namespace and xpath by using Linq Xml'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1448949865236853834</id><published>2008-04-24T01:40:00.001-07:00</published><updated>2008-04-24T01:40:28.254-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>ADO.NET call oracle stored procedure</title><content type='html'>&lt;p&gt;&lt;a href="http://www.c-sharpcorner.com/UploadFile/john_charles/CallingOraclestoredproceduresfromMicrosoftdotNET06222007142805PM/CallingOraclestoredproceduresfromMicrosoftdotNET.aspx"&gt;http://www.c-sharpcorner.com/UploadFile/john_charles/CallingOraclestoredproceduresfromMicrosoftdotNET06222007142805PM/CallingOraclestoredproceduresfromMicrosoftdotNET.aspx&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1448949865236853834?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1448949865236853834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1448949865236853834' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1448949865236853834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1448949865236853834'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/04/adonet-call-oracle-stored-procedure.html' title='ADO.NET call oracle stored procedure'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1357936789259718767</id><published>2008-04-03T00:06:00.000-07:00</published><updated>2008-05-06T00:45:03.782-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MultiThread-Processor'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Understand Thread and Lock</title><content type='html'>Keywords: C#&lt;br /&gt;&lt;br /&gt;Very good articles about thread and synchronizition:&lt;br /&gt;   &lt;a href="http://www.albahari.com/threading/"&gt;http://www.albahari.com/threading/&lt;/a&gt;&lt;br /&gt;Chinese version:  &lt;a href="http://knowledge.swanky.wu.googlepages.com/threading_in_c_sharp.html"&gt;http://knowledge.swanky.wu.googlepages.com/threading_in_c_sharp.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1357936789259718767?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1357936789259718767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1357936789259718767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1357936789259718767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1357936789259718767'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/04/understand-thread-and-lock.html' title='Understand Thread and Lock'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1133086810817010697</id><published>2008-04-02T22:28:00.000-07:00</published><updated>2008-07-29T02:19:40.289-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scalability-Performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Debug and Test'/><title type='text'>Best Practice--.Net Performance Test</title><content type='html'>Production Debugging for .NET Framework Applications&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms954594.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms954594.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Performance and scalability checklist&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms998592.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms998592.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Performance Test guide&lt;br /&gt;&lt;a href="http://www.codeplex.com/PerfTesting"&gt;http://www.codeplex.com/PerfTesting&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Performance Optimization and Test Best Practice Tools&lt;br /&gt;&lt;a href="http://www.codeplex.com/GuidanceExplorer"&gt;http://www.codeplex.com/GuidanceExplorer&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1133086810817010697?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1133086810817010697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1133086810817010697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1133086810817010697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1133086810817010697'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/04/best-practice-net-performance-test.html' title='Best Practice--.Net Performance Test'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8911661333549154215</id><published>2008-03-31T19:41:00.000-07:00</published><updated>2008-05-21T20:18:38.923-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DesignPattern'/><category scheme='http://www.blogger.com/atom/ns#' term='MultiThread-Processor'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>My offen misunderstand things of CSharp</title><content type='html'>对于C#语言总有一些容易混淆的东西, 比如App Domain, lock语句块, 线程安全, deadlock和Content, 以及类的析构子和Finializer.&lt;br /&gt;我总结了一个文章, &lt;a id="publishedDocumentUrl" class="tabcontent" target="_blank" href="http://docs.google.com/Doc?id=ddhzfwz6_1gkm272fd"&gt;http://docs.google.com/Doc?id=ddhzfwz6_1gkm272fd&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8911661333549154215?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8911661333549154215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8911661333549154215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8911661333549154215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8911661333549154215'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/my-offen-misunderstand-things-of-csharp.html' title='My offen misunderstand things of CSharp'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8613202337264736570</id><published>2008-03-18T19:16:00.001-07:00</published><updated>2008-03-18T19:16:21.224-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><title type='text'>Wonderful software-Task Coach</title><content type='html'>&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Keywords: Task Management, Track Task, Schedule management&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Today, I visit the famious website--&lt;a href="http://portableapps.com/apps"&gt;http://portableapps.com/apps&lt;/a&gt;,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;And I found one good software, &lt;strong&gt;Task Coach&lt;/strong&gt;. It is more powerful than outlook, sunlight.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;From now on, I make one day schedule by using TaskCoach in the morning. I track my task by it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Before I leave office I export the calendar from TaskCoach, and import it into Mozilla ThunderBird/SunLight to publish my task into google.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8613202337264736570?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8613202337264736570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8613202337264736570' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8613202337264736570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8613202337264736570'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/wonderful-software-task-coach.html' title='Wonderful software-Task Coach'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2419155053279568194</id><published>2008-03-11T19:26:00.001-07:00</published><updated>2008-03-11T20:30:41.883-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>OOXML resource</title><content type='html'>&lt;p style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 9pt"&gt;&lt;strong&gt;Keywords: OOXML, Office 2007&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 9pt"&gt;Tutorial book: &lt;a href="http://openxmldeveloper.org/articles/1970.aspx"&gt;http://openxmldeveloper.org/articles/1970.aspx&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 9pt"&gt;Tutorial presentation: &lt;a href="http://openxmldeveloper.org/articles/DeveloperWorkshopContent.aspx"&gt;h&lt;/a&gt;&lt;a href="http://openxmldeveloper.org/articles/DeveloperWorkshopContent.aspx"&gt;ttp://openxmldeveloper.org/articles/DeveloperWorkshopContent.aspx&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 9pt"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 9pt"&gt;Reference book: &lt;a href="http://www.ecma-international.org/news/TC45_current_work/Office"&gt;http://www.ecma-international.org/news/TC45_current_work/Office&lt;/a&gt; Open XML Part 3 - Primer_final.docx&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2419155053279568194?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2419155053279568194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2419155053279568194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2419155053279568194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2419155053279568194'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/ooxml-resource.html' title='OOXML resource'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-5280789271086508844</id><published>2008-03-10T21:09:00.001-07:00</published><updated>2008-03-11T01:18:20.555-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><title type='text'>Study Use Case</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: UML, Use case, 用例, Use Case Diagram, 用例图&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;这篇文章基本上是&lt;a href="http://focuswindows.blogspot.com/2008/02/2-uml-tutorial.html"&gt;http://focuswindows.blogspot.com/2008/02/2-uml-tutorial.html&lt;/a&gt;的中文翻译, 该英文文档相当棒. 这节只关注Use Case.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;1. 用例图的几个概念&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;Use Case Diagram是站在用户的视点去理解系统到底是什么样子的. 它关注于系统是什么, 而不关注怎样构建系统. Use Case Diagram由Actor、Use Case和Communication association(或者简称为Communication)组成. 怎样画Use Case diagram, 需要先明白Use Case和Actor概念.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Use Case是面向对象的概念, 所以我们要用面向对象的概念来理解Use Case,到底什么是UseCase呢? 我们开发的系统其实是真实世界中的一个对象, 那么这个对象对外提供的服务,可以说就是Use Case.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;大家在讲Use Case的粒度问题的时候, 常犯的错误就是将该系统的服务的步骤, 当成Use Case. 步骤不是Use Case diagram关注的东西, (UML用Sequence diagram和Activity diagram来体现步骤)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Actor是目标系统的用户, 这个用户可以是人, 也可以是其他系统. 通常将用户按照角色分类, 就能确定用例图的Actor了.&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;2. 怎样画Use Case diagram&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;2.1 画Actor: Actor用一个小人表示.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.2 画Use Case: Use Case是一个椭圆, 里面包含Use Case名.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.3 画Communication: 用一个直线连接Actor和一个Use Case.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.4 画System boundary: 用矩形表示, doundary圈住所有的Use Case.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.5 理解Use case 之间的关系&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.5.1 Generalization关系, 这个关系和类的继承关系一样. 可以说derived use case就是Base use case的具体化(或者说是Base use case的一个实例). 比如刷卡付款和付款这两个用例, 就有generalization关系. 画法是:一条实线带一个实线箭头, 箭头指向Base Use Case.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.5.2 Include关系, 包含关系很好理解, 如果多个Use case有相同的部分, 可以将相同的部分抽取出来, 这样新Use Case和原有的Use Case就有了Include关系.UML 画法是: 一条虚线带箭头, 箭头指向derived Use Case, 并且在虚线上打&amp;lt;&amp;lt;Include&amp;gt;&amp;gt;标记.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2.5.3 Extend关系, 表示一个Use Case是另一个Use Case的变种, 要注意它和Generalization的区别, Generalization关系就像基类和派生类间的关系; Extend关系就象是同一个基类的两个派生类之间的关系. UML画法是:一条虚线带箭头, 箭头指向参考的Use Case, 并且在虚线上打&amp;lt;&amp;lt;Extend&amp;gt;&amp;gt;标记.&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;3. 用例图的用处:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;3.1. 协助我们来确定系统的feature或需求&lt;/p&gt;&lt;br /&gt;&lt;p&gt;3.2. 作为和Client沟通的材料, 因为用例图是站在用户的角度来理解系统, 所以特别适合和Client沟通.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;3.3. 生成Test Case. 用例图会反映出系统会有哪些Scenario, 所以可以用来设计Test Case.&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;img src="http://lh3.google.com/WadeLiu2008/R9Y_2EKYbHI/AAAAAAAAAH4/JkVDC3PhyPc/Windows_UML_UseCase.PNG" style="DISPLAY: inline; WIDTH: 714px; HEIGHT: 742px" height="742" width="714"/&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-5280789271086508844?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/5280789271086508844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=5280789271086508844' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5280789271086508844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/5280789271086508844'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/study-use-case.html' title='Study Use Case'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-651244320817300328</id><published>2008-03-10T21:00:00.001-07:00</published><updated>2008-03-10T21:00:14.449-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>ScrewTurn Wiki Project(C#, Architecture Design)</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: Wiki, ScrewTurn Wiki&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There is a wonderful our source project, ScrewTurn Wiki(&lt;a href="http://www.screwturn.eu/MainPage.ashx"&gt;http://www.screwturn.eu/MainPage.ashx&lt;/a&gt;). Download the source and research it. You will gain a lot from it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;1. Multiple Database supported: By using plugin architecuture.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2. MVC Pattern: Wonderful layer division&lt;/p&gt;&lt;br /&gt;&lt;p&gt;3. Asp.net: Good code&lt;/p&gt;&lt;br /&gt;&lt;p&gt;4. How to build one web application and how make it deploy easily&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-651244320817300328?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/651244320817300328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=651244320817300328' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/651244320817300328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/651244320817300328'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/screwturn-wiki-projectc-architecture.html' title='ScrewTurn Wiki Project(C#, Architecture Design)'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2736483491358430122</id><published>2008-03-10T20:18:00.001-07:00</published><updated>2008-03-10T20:27:06.366-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>all about .net framework 3.0(copied article)</title><content type='html'>&lt;p&gt;&lt;span&gt;&lt;span class="subtitle"&gt;&lt;span class="subtitle"&gt;&lt;span id="title"&gt;All about .NET Framework 3.0&lt;/span&gt; &lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all"&gt;http://aspalliance.com/1351_All_about_NET_Framework_30.all&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span class="subtitle"&gt;&lt;span class="subtitle"&gt;Published:&lt;/span&gt; &lt;span id="DatePublishedLabel"&gt;10 Jul 2007&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span class="subtitle"&gt;Abstract&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span id="abstractLabel"&gt;The .NET Framework 3.0 is the next generation of the .NET Framework that sits on the top of the previous version. It introduces some additional features, and in this article Hima discusses these features in detail.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;strong&gt;Article Contents&lt;/strong&gt;:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul class="aspaBullets"&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page1"&gt;Introduction&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page2"&gt;What Happens when we install Framework 3.0&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page3"&gt;Features&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page4"&gt;Windows Presentation Foundation (WPF)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page5"&gt;Windows Workflow Foundation (WF)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page6"&gt;Windows Communication Foundation (WCF)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page7"&gt;Microsoft Windows Card Space (WCS)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page8"&gt;Related Downloads&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page9"&gt;References&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span&gt;&lt;a href="http://aspalliance.com/1351_All_about_NET_Framework_30.all#Page10"&gt;Conclusion&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2736483491358430122?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2736483491358430122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2736483491358430122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2736483491358430122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2736483491358430122'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/all-about-net-framework-30copied.html' title='all about .net framework 3.0(copied article)'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-748736883115494504</id><published>2008-03-06T21:33:00.001-08:00</published><updated>2008-03-06T21:33:55.726-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Avoid using FileMode.OpenOrCreate to open stream</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: C#, Stream, FileMode.OpenOrCreate&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;C#提供多种方式来创建一个具有不同读写权限的流, 这主要是通过设置不同的FileMode和FileAccess值来实现的. 我们如果要取得一个具有读写权限的流, 最好是用FileMode.Create和FileAcess.ReadWrite来获取. 源码后说明原因. &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Test()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//get the main part of docx. The main part is just document.xml in docx package&lt;/span&gt;&lt;br /&gt;            PackagePart wordMainPackagePart=GetMainPart();&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//load document.xml into wholeDocument object&lt;/span&gt;&lt;br /&gt;            XmlDocument wholeDocument = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlDocument();&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream stream = wordMainPackagePart.GetStream())&lt;br /&gt;            {&lt;br /&gt;                wholeDocument.Load(stream);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//change the wholeDocument &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//save wholeDocument into document.xml. It is better avoid using FileMode.OpenOrCreate,  we had better use FileMode.Create&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream stream = wordMainPackagePart.GetStream(FileMode.Create, FileAccess.ReadWrite))&lt;br /&gt;            {&lt;br /&gt;                wholeDocument.Save(stream);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;FileMode有几个枚举值:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;  FileMode.Append的意义是, 如果文件存在, 流定位到文件尾部, 新写的东西将追加到原文件尾; 如果文件不存在, 则新增文件. 这个FileMode只能和FileAccess.Write一起使用, 不能和其他的FileAccess同时使用.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;  FileMode.Create的意义是:如果文件存在, 首先删除文件的内容, 然后重写文件; 如果文件不存在, 则新增文件&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;  FileMode.CreateNew的意义是: 如果文件存在, 则抛出一个异常; 如果文件不存在, 则新增文件&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;  FileMode.Open的意义是,如果文件存在,再根据FileAccess的取值, 来确定可不可写; 如果文件不存在, 则抛出一个异常&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;  FileMode.OpenOrCreate的意义是, 如果文件存在, 则重写这个文件, 重写的机制是不删除原有文件的内容, 那么从原文件头开始重写, 比如原有文件共10个字节, 新的内容只有5个字节的话, 则重写后的文件后5个字节仍是原有文件的内容.&lt;br/&gt;&lt;br /&gt;  FileMode.Truncate的意义是, 如果文件存在的话, 首先删除 文件的内容, 然后重写文件.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;为什么我们推荐使用FileMode.Create呢, 因为FileMode.Create其实同时具有FileMode.CreateNew和FileMode.Truncate的效果, 即当文件存在的时候,它使用FileMode.Truncate方式重写文件, 当文件不存在的时候, 它使用FileMode.CreateNew来新增文件.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-748736883115494504?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/748736883115494504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=748736883115494504' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/748736883115494504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/748736883115494504'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/avoid-using-filemodeopenorcreate-to.html' title='Avoid using FileMode.OpenOrCreate to open stream'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-4530123602346042858</id><published>2008-03-06T19:43:00.000-08:00</published><updated>2008-03-06T20:01:52.103-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>misunderstand when using XmlNode.SelectSingleNode function</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: System.Xml, XmlNode, XPath&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;在使用System.Xml命名空间的XmlNode类, 有一个方法 XmlNode.SelectSingleNode(string xpath).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;刚开始使用它时, 对它的作用理解有误. 如果XPath以"/"开始, 其意义为从根节点开始搜索Node. 原本想使用XmlNode456对象的SelectSingleNode(XPath123)方法, XPath123这个表达式所指的根节点应是XmlNode456, 但事实是, 这个函数仍以XmlNode456所在文档的根节点root作为搜索的起点.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;要搜索Node456下的Child节点, 有2个方法, 最好使用方法2, 因为它更加简单.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;方法1: 如果想通过SelectSingleNode()来搜索的话, 构建一个从根节点root指向Child的绝对路径的XPath, (XPath表达式应该以"./"开头)&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;方法2: 将Node456.OutXml赋值给一个tempXmlDocument., 然后再使用tempXmlDocument.SelectSingleNode(AbsoluteXPath), 可以定位到子节点. 这时候, 你可以用tempXmlDocument来直接提取Node456节点的内容, 如果还要修改Node456, 应该在修改tempXmlDocument之后, 再将修改后的内容保存到原有的Node456节点上.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;            XmlDocument tempXmlDocument = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlDocument();&lt;br /&gt;            &lt;span class="rem"&gt;//Load the xml from Node456&lt;/span&gt;&lt;br /&gt;            tempXmlDocument.LoadXml(Node456.OutXml);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//extract Info from tempXmlDocument&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//change the tempXmlDocument info &lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//save the result after changed into the Node456&lt;/span&gt;&lt;br /&gt;            Node456.InnerXml = tempXmlDocument.DocumentElement.InnerXml;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-4530123602346042858?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/4530123602346042858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=4530123602346042858' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4530123602346042858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4530123602346042858'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/03/misunderstand-when-using.html' title='misunderstand when using XmlNode.SelectSingleNode function'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/13031045445888422286</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2905541642564376867</id><published>2008-02-28T23:20:00.001-08:00</published><updated>2008-03-10T01:02:26.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='DesignPattern'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>2 UML tutorial</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: UML 2.1&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br/&gt;&lt;br /&gt;网上关于UML的文章很多, 但下面2篇文章很实用.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://dn.codegear.com/article/31863"&gt;http://dn.codegear.com/article/31863&lt;/a&gt;(这个文章还带测试题目)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.sparxsystems.com.au/resources/uml2_tutorial/index.html"&gt;&lt;span style="FONT-FAMILY: Calibri"&gt;http://www.sparxsystems.com.au/resources/uml2_tutorial/index.html&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;点空间&lt;a href="http://www.dotspace.idv.tw/"&gt;http://www.dotspace.idv.tw/&lt;/a&gt; 也有比较好的文章.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2905541642564376867?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2905541642564376867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2905541642564376867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2905541642564376867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2905541642564376867'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/2-uml-tutorial.html' title='2 UML tutorial'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-29537432978533529</id><published>2008-02-27T19:32:00.001-08:00</published><updated>2008-02-27T19:32:00.922-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>how to Use Subversion with TortoiseSVN</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: SVN, TortoiseSVN&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;how to Use Subversion with TortoiseSVN, visit&lt;/strong&gt; &lt;a href="http://www.codeproject.com/KB/books/Subversion_TortoiseSVN.aspx"&gt;&lt;strong&gt;http://www.codeproject.com/KB/books/Subversion_TortoiseSVN.aspx&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-29537432978533529?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/29537432978533529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=29537432978533529' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/29537432978533529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/29537432978533529'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/how-to-use-subversion-with-tortoisesvn.html' title='how to Use Subversion with TortoiseSVN'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8618591174044787068</id><published>2008-02-27T19:17:00.001-08:00</published><updated>2008-02-27T19:30:56.182-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>SVN-How to set ignore-list</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: Subversion, svn, tortoiseSVN&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Subversion is a powerful source code control system. We can upload the source code into svn database. In many cases, we do not want to version some types files, such as bin folder and .user file. There are 2 ways to set ignore list.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For example, In .net development, some files need always ignore to verion such as bin obj *.suo *.obj *.pdb *.exe *.dll *.csproj.user&lt;/p&gt;&lt;br /&gt;&lt;p&gt;1. For one specific directory, we can use the tortoiseSVN to achieve it.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Steps:&lt;br /&gt;&lt;br/&gt;&lt;/strong&gt; Select one folder in explorer and then select the property menuitem. In Property/Subversion window, click the properties button,&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;And then click add button, select svn:ignore in the property combobox in subsequence window, Input the file extension in the textbox&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2. Set global Ignore list.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;Steps:&lt;/strong&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Find the config file for subversion, which is located in "\Documents and Settings\&amp;lt;user&amp;gt;\Application Data\Subversion" and the file name is &lt;strong&gt;Config&lt;/strong&gt; with no extension.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;To get it to ignore these directories or files, you need to uncomment or edit the &lt;strong&gt;global-ignores&lt;/strong&gt; line. In mine, I have it set to:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;strong&gt;global-ignores&lt;/strong&gt; = bin obj *.suo *.obj *.pdb *.exe *.dll *.csproj.user&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;This will causes it to ignore the bin and obj sub-directories of a typical Visual Studio projects.&lt;/p&gt;&lt;br /&gt;&lt;p/&gt;&lt;br /&gt;&lt;p/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8618591174044787068?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8618591174044787068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8618591174044787068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8618591174044787068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8618591174044787068'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/svn-how-to-set-ignore-list.html' title='SVN-How to set ignore-list'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3620202878735339203</id><published>2008-02-25T00:02:00.001-08:00</published><updated>2008-02-25T00:02:49.495-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><title type='text'>ruby dev tools</title><content type='html'>&lt;p&gt;&lt;strong&gt;keywords: Ruby, JDT&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;One-Click Installer- Ruby interpretor and extenstion(Windows OS)&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://rubyforge.org/frs/?group_id=167"&gt;http://rubyforge.org/frs/?group_id=167&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;ActiveScriptRuby- Ruby interpretor and extenstion package(Windows OS)&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://arton.hp.infoseek.co.jp/indexj.html"&gt;http://arton.hp.infoseek.co.jp/indexj.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br/&gt;&lt;br /&gt;RDE- Ruby Dev Eniviroment&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://homepage2.nifty.com/sakazuki/rde_en/index.html"&gt;http://homepage2.nifty.com/sakazuki/rde_en/index.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;RDT homepage&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://rubyeclipse.sourceforge.net/"&gt;http://rubyeclipse.sourceforge.net/&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Using the Ruby Development Tools plug-in for Eclipse&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a href="http://www.ibm.com/developerworks/opensource/library/os-rubyeclipse"&gt;http://www.ibm.com/developerworks/opensource/library/os-rubyeclipse&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3620202878735339203?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3620202878735339203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3620202878735339203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3620202878735339203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3620202878735339203'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/ruby-dev-tools.html' title='ruby dev tools'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7981930381657789686</id><published>2008-02-24T19:48:00.001-08:00</published><updated>2008-02-24T19:48:45.457-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>obfuscator .net Assembly</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: Protection .net assembly&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;1. Aspose.Obfuscator is free, but use it at you own risk. &lt;span id="_ctl0_MainContent_PostFlatView"&gt;&lt;span&gt;&lt;span style="FONT-SIZE: 0.75em"&gt;&lt;a style="FONT-FAMILY: tahoma,helvetica,sans-serif" href="http://www.aspose.com/Products/Aspose.Obfuscator/"&gt;&lt;span style="COLOR: #008000"&gt;http://www.&lt;strong&gt;aspose&lt;/strong&gt;.com/Products/Aspose.Obfuscator/&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="FONT-SIZE: 0.75em"&gt;2. CodeVeil is commercial software&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="FONT-SIZE: 0.75em"&gt;&lt;a href="http://www.xheo.com/products/codeveil/default.aspx"&gt;http://www.xheo.com/products/codeveil/default.aspx&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="FONT-SIZE: 0.75em"&gt;3. .NET Obfuscator community edition is free. But standard edition is not free.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="FONT-SIZE: 0.75em"&gt;&lt;a href="http://www.preemptive.com/products/dotfuscator/index.html"&gt;http://www.preemptive.com/products/dotfuscator/index.html&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7981930381657789686?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7981930381657789686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7981930381657789686' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7981930381657789686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7981930381657789686'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/obfuscator-net-assembly.html' title='obfuscator .net Assembly'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3025553730509188765</id><published>2008-02-20T01:03:00.001-08:00</published><updated>2008-02-20T01:03:28.814-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>open source net and security class library of c#</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: C#, Opensource, Net library, Security Library, Certificate library&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; COLOR: #008000"&gt;great opensource site &lt;a href="http://www.mentalis.org/"&gt;http://www.mentalis.org/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3025553730509188765?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3025553730509188765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3025553730509188765' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3025553730509188765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3025553730509188765'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/open-source-net-and-security-class.html' title='open source net and security class library of c#'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3593414567116539930</id><published>2008-02-20T00:55:00.001-08:00</published><updated>2008-02-20T00:55:30.987-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>interconvert byte[] and string and stream</title><content type='html'>&lt;p&gt;&lt;strong&gt;keywords: C#, byte array, string, stream&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;stream和string和byte[]都是内存中的对象, 一般而言, string和byte[]都是轻量级的数据包装体, 在作layer间数据交换应优先使用它们, 因为它们占用更少的内存. 但它们本身的成员方法比较少, 尤其在持久化方面, 有可能需要借助Stream来完成, 那么怎样将string和byte[]转化成stream呢? 本文给出了一些代码. 有关不同类型stream相互转换, 可以参考另一篇文章(&lt;a href="http://focuswindows.blogspot.com/2008/02/convert-filestream-fromto-memorystream.html"&gt;http://focuswindows.blogspot.com/2008/02/convert-filestream-fromto-memorystream.html&lt;/a&gt;).&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///如果你并不需要解析转换后的String, 那么可以将byte数组转换成Base64String. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 使用这个方法你不需要关心buffer数组中每个byte的编码, 统统都可以将它们转换成Base64String.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// because Base64 store one char in 64 digits. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// But the Base64 char is hard to recognized compared with the ASCII encode.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="buffer"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConvertBytesToBase64String(&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; Convert.ToBase64String(buffer);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 将一个Base64String转换成Byte[]&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="str"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] ConvertBase64StringToBytes(&lt;span class="kwrd"&gt;string&lt;/span&gt; str)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; Convert.FromBase64String(str);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 将Stream转换为String&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="ms"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConvertStreamIntoString(Stream ms)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//使用StreamReader应该是读取Stream最简单的方法&lt;/span&gt;&lt;br /&gt;            System.IO.StreamReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(ms);&lt;br /&gt;            ms.Position = 0;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; reader.ReadToEnd();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        &lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// 将string转换成stream&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="str"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; MemoryStream ConvertStringToMemoryStream(&lt;span class="kwrd"&gt;string&lt;/span&gt; str)&lt;br /&gt;        {&lt;br /&gt;            MemoryStream ms=&lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream() ;&lt;br /&gt;            &lt;span class="rem"&gt;//使用一个StreamWriter来将str写到一个MemoryStream&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamWriter writer = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(ms))&lt;br /&gt;            {&lt;br /&gt;                writer.Write(str);&lt;br /&gt;                writer.Flush();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; ms;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3593414567116539930?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3593414567116539930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3593414567116539930' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3593414567116539930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3593414567116539930'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/interconvert-byte-and-string-and-stream.html' title='interconvert byte[] and string and stream'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2142499102381441787</id><published>2008-02-19T01:46:00.001-08:00</published><updated>2008-02-19T01:46:38.735-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Msn dev resources</title><content type='html'>&lt;p&gt;Keywords: MSN&lt;/p&gt;&lt;br /&gt;&lt;p&gt;百步穿杨 &lt;a href="http://www.blogjava.net/coacoa2008/archive/2007/12/04/165182.html"&gt;http://www.blogjava.net/coacoa2008/archive/2007/12/04/165182.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;巴士飞扬 &lt;a href="http://www.busfly.cn/"&gt;http://www.busfly.cn/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2142499102381441787?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2142499102381441787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2142499102381441787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2142499102381441787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2142499102381441787'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/msn-dev-resources.html' title='Msn dev resources'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1790117989820813401</id><published>2008-02-19T01:37:00.001-08:00</published><updated>2008-02-24T22:46:43.433-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Develop MSN Robot By C#</title><content type='html'>&lt;p&gt;this article is copied from &lt;a href="http://www.busfly.cn/post/183.html"&gt;http://www.busfly.cn/post/183.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="post-title"&gt;用.NET开发MSN聊天机器人 - MSN聊天机器人开发揭秘(收藏)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1790117989820813401?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1790117989820813401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1790117989820813401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1790117989820813401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1790117989820813401'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/develop-msn-robot-by-c.html' title='Develop MSN Robot By C#'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1283561150076795394</id><published>2008-02-13T01:39:00.001-08:00</published><updated>2008-02-13T01:39:36.396-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>MSDN magazine reader--MSDNReader</title><content type='html'>&lt;p style="MARGIN: 0in 0in 0pt"&gt;Keywords: MSDNReader, MSDN&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt"&gt;download: &lt;a href="http://code.msdn.microsoft.com/msdnreader"&gt;http://code.msdn.microsoft.com/msdnreader&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt"&gt;This is a downloadable tool to allow you to read &lt;strong&gt;MSDN magazine - which is a great magazine to get up-to-date information on .NET&lt;/strong&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 0pt"&gt;Please download and share with your friends too. This requires .NET 3.0 to be installed on your system.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1283561150076795394?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1283561150076795394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1283561150076795394' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1283561150076795394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1283561150076795394'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/msdn-magazine-reader-msdnreader.html' title='MSDN magazine reader--MSDNReader'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3353864604511107632</id><published>2008-02-13T01:20:00.001-08:00</published><updated>2008-02-13T01:20:56.348-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>Show all C# exceptions by using  Exception_Hunter of Red Gate software</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: Exception, Exception Hunter, Red Gate&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;How to show all exceptions in you c# project before you release your product? It is important, because we will always leave some exceptions not handled. If you are in the situation, dont worry, you are not alone.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There is a tool can help you. The tool is Exception Hunter, It is a commerical software by Red Gate Software. I think the command line tool is more useful than the UI tool.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Command line usage:&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;"C:\Program Files\Red Gate\Exception Hunter 1\hunt.exe" /a:"D:\YourAssembly.Exe" /er:"Result_YourAssembly.html" /allpublicmethods&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3353864604511107632?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3353864604511107632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3353864604511107632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3353864604511107632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3353864604511107632'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/show-all-c-exceptions-by-using.html' title='Show all C# exceptions by using  Exception_Hunter of Red Gate software'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-4115499055716084391</id><published>2008-02-03T21:47:00.001-08:00</published><updated>2008-02-03T21:47:36.355-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DevelopSoftware'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>the powerful DebugView</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: capture debug output, Win32, .Net&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;DebugView is made by the famous Sysinternals company owned by Microsoft. 我们在程序中通常会有意用debug类(c#)输出一些调试信息, 或者我们要捕捉一些其他人开发的程序是否有异常, 都可以使用这个工具. 只要启动一个DebugView实例, 就可以监控所有程序的debug输出.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;它不仅仅可以监视Windows和Console程序的debug, 而且可以监视Web程序的debug输出(需要在Web服务器上运行debugview).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-4115499055716084391?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/4115499055716084391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=4115499055716084391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4115499055716084391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/4115499055716084391'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/powerful-debugview.html' title='the powerful DebugView'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3146370422706438870</id><published>2008-02-03T21:34:00.001-08:00</published><updated>2008-02-03T21:34:25.244-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to test performance in C#</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: Performace test, Win32, .Net Framework&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;In Win32,&lt;/strong&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Low resolution: GetTickCount() Api&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;High resolution: QueryPerformanceCounter() and &lt;span id="intelliTXT"&gt;QueryPerformanceFrequency()&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;In .Net&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Low resolution: Enviroment.TickCount, the best resolution it will give you is 10 milliseconds.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;High resolution: System.Diagnostics.Stopwatch class.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Stopwatch class usage:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnPerformaceTest_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            System.Diagnostics.Stopwatch sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; Stopwatch();&lt;br /&gt;            sw.Start();&lt;br /&gt;            &lt;span class="rem"&gt;//Process1();&lt;/span&gt;&lt;br /&gt;            sw.Stop();&lt;br /&gt;            System.Console.WriteLine(sw.ElapsedMilliseconds);&lt;br /&gt;            &lt;br /&gt;            sw.Reset();&lt;br /&gt;            sw.Start();&lt;br /&gt;            &lt;span class="rem"&gt;//Process2();&lt;/span&gt;&lt;br /&gt;            sw.Stop();&lt;br /&gt;            System.Console.WriteLine(sw.ElapsedMilliseconds);&lt;br /&gt;&lt;br /&gt;            sw.Reset();&lt;br /&gt;            sw.Start();&lt;br /&gt;            &lt;span class="rem"&gt;//Process3();&lt;/span&gt;&lt;br /&gt;            sw.Stop();&lt;br /&gt;            System.Console.WriteLine(sw.ElapsedMilliseconds); &lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3146370422706438870?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3146370422706438870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3146370422706438870' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3146370422706438870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3146370422706438870'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/how-to-test-performance-in-c.html' title='How to test performance in C#'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1065935078014312504</id><published>2008-02-03T01:55:00.001-08:00</published><updated>2008-02-03T01:55:16.549-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>how to read binary file and save it into xml</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: CDATA node of xml, FileStream, MemoryStream, Base64String&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In xml document, you can define CDATA node to store some large text string. There is a constraint in xml document, the xml document only can contain text string.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;How to save image data or other binary data into xml?&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;We can convert the binary data into Base64String data, then we can store the Base64String data into xml document. We can use the following approach to achive.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Approach1: BinaryFile===&amp;gt;Byte[]===&amp;gt;Base64String===&amp;gt;CDATA&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The following is pseudo code:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;byte[] buffer=File.ReadAllBytes(string path);&lt;/p&gt;&lt;br /&gt;&lt;p&gt;string base64String= Convert.ToBase64String();&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;XmlCDATA=new XmlCDATA(base64String);&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;XmlDocument.AddChild(XmlCDATA);&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;How to restore the Base64String data into a FileStream?&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;It is easy to reach. The procedure is just reverse the above process.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1065935078014312504?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1065935078014312504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1065935078014312504' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1065935078014312504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1065935078014312504'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/how-to-read-binary-file-and-save-it.html' title='how to read binary file and save it into xml'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2412328132093422971</id><published>2008-02-03T01:32:00.001-08:00</published><updated>2008-02-20T00:57:04.989-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Convert  MemoryStream into FileStream</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: C#, FileStream, MemoryStream&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Sometimes, we need to convert FileStream into MemoryStream. And in other times, you need to convert memoryStream into fileStream because filestream is able to save to disk file.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;How to convert string/byte[] into stream or convert stream into string/byte[], please refer another article. (&lt;a href="http://focuswindows.blogspot.com/2008/02/interconvert-byte-and-string-and-stream.html"&gt;http://focuswindows.blogspot.com/2008/02/interconvert-byte-and-string-and-stream.html&lt;/a&gt;)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;How to convert MemoryStream into FileStream?&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If you can solve the problem, it is will be easy to convert FileStream into MemoryStream because they are based the same parent class. There are 3 approaches to convert.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The 1st solution is use the loop strategy. This method can be used largely. Every time you read some bytes from Source_Stream into a buffer(buffer is byte array, it's length usually is 1k or 10k), then write the buffer into Target_Stream.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The 2nd solution is use MemoryStream.WriteTo(stream anotherStream). This have the highest performance, but Only MemoryStream has this method. (Because it do not need allocate additional memory for carriage buffer. It uses the MemoryStream object buffer property.)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The 3rd solution is read the whole Source_Stream into one single byte array, and then write byte array into Target_Stream. But it is not good solution, because you have to allocate too big memory for byte array.&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Form1 : Form&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Form1()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//Add one textbox, named "textBox1"&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//Add one button, named "btnTest"&lt;/span&gt;&lt;br /&gt;            InitializeComponent();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///  Convert one MemoryStream object into FileStream Object.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///  Performance:&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///    This method has the highest performance. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///    This method can used largely. It is also suited for convert other kind Stream into FileStream.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="ms"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="newFilePath"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ConvertMemoryStreamToFileStream_1(MemoryStream ms, String newFilePath)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (FileStream fs = File.OpenWrite(newFilePath))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; blockSize = 1024;&lt;br /&gt;                &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[blockSize];&lt;br /&gt;                &lt;span class="kwrd"&gt;int&lt;/span&gt; numBytes;&lt;br /&gt;                &lt;span class="kwrd"&gt;while&lt;/span&gt; ((numBytes = ms.Read(buffer, 0, blockSize)) &amp;gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    fs.Write(buffer, 0, numBytes);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Convert one MemoryStream object into FileStream Object.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// The method is so simple. but only MemoryStream has method WriteTo(Stream anotherStream)&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Performance: &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///   This method performace is worse than ConvertMemoryStreamToFileStream_1()&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="ms"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="newFilePath"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ConvertMemoryStreamToFileStream_2(MemoryStream ms, String newFilePath)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (FileStream fs = File.OpenWrite(newFilePath))&lt;br /&gt;            {&lt;br /&gt;                ms.WriteTo(fs);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Convert one MemoryStream object into FileStream Object.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Performace:&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///     This method is the less effectively. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///     Because it have to allocate a great deal of memory to accommodate the whole MemoryStream all at once.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="filePath"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ConvertMemoryStreamToFileStream_3(MemoryStream ms, String newFilePath)&lt;br /&gt;        {&lt;br /&gt;&lt;span class="rem"&gt;            // Allocate a large memory at first.&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[ms.Length];&lt;br /&gt;            ms.Read(buffer, 0, (&lt;span class="kwrd"&gt;int&lt;/span&gt;)ms.Length);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (FileStream fs = File.OpenWrite(newFilePath))&lt;br /&gt;            {&lt;br /&gt;                fs.Write(buffer, 0, (&lt;span class="kwrd"&gt;int&lt;/span&gt;)ms.Length);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Create one MemoryStream object. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// The result is not expanable MemoryStream. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Performance: &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///     Create one MemoryStream object is fastest. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///     But read bytes from unexpansble memoryStream will consume more time. I do not know the reason.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="filePath"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; MemoryStream CreateMemoryStream_1(&lt;span class="kwrd"&gt;string&lt;/span&gt; filePath)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//Step1: read whole FileStream into byte array.&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = System.IO.File.ReadAllBytes(filePath);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//Step2:convert byte array into MemoryStream.  &lt;/span&gt;&lt;br /&gt;            MemoryStream ms1 = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream(buffer);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; ms1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Create one MemoryStream object. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// The result is not expanable MemoryStream. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Performace:&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///    Create one MemoryStream object is slower&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///    But read bytes from expansble memoryStream will consume less time. I do not know the reason.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="filePath"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; MemoryStream CreateMemoryStream_2(&lt;span class="kwrd"&gt;string&lt;/span&gt; filePath)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; blockSize = 1024;&lt;br /&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; bytesNum;&lt;br /&gt;            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[blockSize];&lt;br /&gt;            MemoryStream ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (FileStream fs = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileStream(filePath, FileMode.Open))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;while&lt;/span&gt; ((bytesNum = fs.Read(buffer, 0, blockSize)) &amp;gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    ms.Write(buffer, 0, bytesNum);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; ms;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnTest_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; SourceFile = &lt;span class="str"&gt;@"c:\Launch.wmv"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; NewFile1 = &lt;span class="str"&gt;@"c:\1.wmv"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; NewFile2 = &lt;span class="str"&gt;@"c:\2.wmv"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; NewFile3 = &lt;span class="str"&gt;@"c:\3.wmv"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (File.Exists(NewFile1))&lt;br /&gt;                File.Delete(NewFile1);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (File.Exists(NewFile2))&lt;br /&gt;                File.Delete(NewFile2);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (File.Exists(NewFile3))&lt;br /&gt;                File.Delete(NewFile3);&lt;br /&gt;&lt;br /&gt;            textBox1.Clear() ;&lt;br /&gt;            Application.DoEvents();&lt;br /&gt;            MemoryStream ms = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;                System.Diagnostics.Stopwatch sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; Stopwatch();&lt;br /&gt;                sw.Start();&lt;br /&gt;                ms = CreateMemoryStream_2(SourceFile);&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (ms != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    sw.Stop();               &lt;br /&gt;                    textBox1.AppendText(sw.ElapsedMilliseconds.ToString() + &lt;span class="str"&gt;"--CreateMemoryStream_2"&lt;/span&gt;); &lt;br /&gt;                    textBox1.AppendText(Environment.NewLine);&lt;br /&gt;&lt;br /&gt;                    sw.Reset();&lt;br /&gt;                    sw.Start();&lt;br /&gt;                    ConvertMemoryStreamToFileStream_1(ms, NewFile1);&lt;br /&gt;                    &lt;br /&gt;                    sw.Stop();&lt;br /&gt;                    textBox1.AppendText( sw.ElapsedMilliseconds.ToString() + &lt;span class="str"&gt;"--ConvertMemoryStreamToFileStream_1"&lt;/span&gt;);&lt;br /&gt;                    textBox1.AppendText(Environment.NewLine);&lt;br /&gt;&lt;br /&gt;                    sw.Reset();&lt;br /&gt;                    sw.Start();&lt;br /&gt;                    ConvertMemoryStreamToFileStream_2(ms, NewFile2);&lt;br /&gt;                    sw.Stop();&lt;br /&gt;                    textBox1.AppendText( sw.ElapsedMilliseconds.ToString() + &lt;span class="str"&gt;"--ConvertMemoryStreamToFileStream_2"&lt;/span&gt;);&lt;br /&gt;                    textBox1.AppendText(Environment.NewLine);&lt;br /&gt;&lt;br /&gt;                    sw.Reset();&lt;br /&gt;                    sw.Start();&lt;br /&gt;                    ConvertMemoryStreamToFileStream_3(ms, NewFile3);&lt;br /&gt;                    sw.Stop();&lt;br /&gt;                    textBox1.AppendText( sw.ElapsedMilliseconds.ToString() + &lt;span class="str"&gt;"--ConvertMemoryStreamToFileStream_3"&lt;/span&gt;);&lt;br /&gt;                    textBox1.AppendText(Environment.NewLine);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (ms != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                    ms.Close();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;The performance test results:&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In test case c:\Launch.wmv is an video file, its size is about 66M. if we use CreateMemoryStream_Method1() to create one unexpandable MemoryStream, the output result is:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;212--CreateMemoryStream_1&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;968--ConvertMemoryStreamToFileStream_1&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;2016--ConvertMemoryStreamToFileStream_2&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;1929--ConvertMemoryStreamToFileStream_3&lt;/p&gt;&lt;br /&gt;&lt;p&gt;if we use CreateMemoryStream_Method2() to create an expandable MemoryStream, the output result is:&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;1011--CreateMemoryStream_2&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;1--ConvertMemoryStreamToFileStream_1&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;1619--ConvertMemoryStreamToFileStream_2&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;1225--ConvertMemoryStreamToFileStream_3&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2412328132093422971?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2412328132093422971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2412328132093422971' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2412328132093422971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2412328132093422971'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/convert-filestream-fromto-memorystream.html' title='Convert  MemoryStream into FileStream'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2306998578179538885</id><published>2008-02-01T17:44:00.001-08:00</published><updated>2008-02-01T17:50:54.281-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Using List&lt;T&gt;.Sort() and Find() by delegate</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: C# Generic, List&amp;lt;T&amp;gt; class, Find, Sort, Comparison, Predicate&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In List&amp;lt;T&amp;gt; class, Sort() method will perform to sort the list item. For List&amp;lt;string&amp;gt;, you can call Sort() method without argument. It will perform well. But if you sort List&amp;lt;Person&amp;gt; by using the same way, One error happened.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Why? Because the .Net Runtiime know how to compare toow string object, but it do not know how to compare two Person objects. In this situation, you will need define your comparison method. There is the same problem when using List.Find() method.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;How to use List&amp;lt;T&amp;gt;.Sort()?&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Refer to the List&amp;lt;T&amp;gt;.Sort source code. There are 4 override method, one of them is as follows,&lt;/p&gt;&lt;br /&gt;&lt;p&gt;public &lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;void&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;Sort(&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #2b91af"&gt;Comparison&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;&amp;lt;T&amp;gt; comparison);&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;And then refer to Comparison&amp;lt;T&amp;gt;, In System namespace&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;&lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;int&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #2b91af"&gt;Comparison&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;&amp;lt;T&amp;gt;(T x, T y);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;Ok, it is time to write code. You can define a static comparison method in PersonHelper class(one helper class for Person), it must follow the &lt;span style="COLOR: #2b91af"&gt;Comparison&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;&amp;lt;T&amp;gt; delegate signature.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;&lt;strong&gt;How to use List&amp;lt;T&amp;gt;.Find() ?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Look at the arguement of the Find(). This is also a delegate.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;T Find(&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #2b91af"&gt;Predicate&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;&amp;lt;T&amp;gt; match);&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;and then refer to Predicate&amp;lt;T&amp;gt;, In System namespace&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;&lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #0000ff"&gt;bool&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #2b91af"&gt;Predicate&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;&amp;lt;T&amp;gt;(T obj);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;We need pass one delegate object to Find() method, e.g &lt;span style="FONT-SIZE: 0.9em"&gt;CompareByNamePredicate&lt;/span&gt;. But the ComparePredicate() have only one argument, which is the enumerator of Generic List dictionary. How we specify the find condition, e.g, "TOM" for one Person name. We can encapsulate the &lt;span style="FONT-SIZE: 0.9em"&gt;CompareByNamePredicate&lt;/span&gt; method in one helper class. and we let one private variable of the helper class object to hold&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em"&gt;"TOM". Then we have Predicate method and Find condition. The subsequence is simple.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;If you want use Helper class to achieve it, you can use anonymous delegate method. please refer to &lt;a href="http://blogs.msdn.com/devdev/archive/2006/06/30/652802.aspx"&gt;http://blogs.msdn.com/devdev/archive/2006/06/30/652802.aspx&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em"&gt;The following code demo how to use helper class and anonymous delegate to approach the Find() and Sort() function.&lt;/span&gt; &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// Main class, in this class we call the List.Find() and List.Sort().&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Form1 : Form&lt;br /&gt;    {&lt;br /&gt;        List&amp;lt;Person&amp;gt; m_ListPerson = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Person&amp;gt;();&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Form1()&lt;br /&gt;        {&lt;br /&gt;            InitializeComponent();&lt;br /&gt;            m_ListPerson.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"c1"&lt;/span&gt;));&lt;br /&gt;            m_ListPerson.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"a1"&lt;/span&gt;));&lt;br /&gt;            m_ListPerson.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"TOM"&lt;/span&gt;));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Use named delegate method to approach the sort function&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; buttonSort_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            m_ListPerson.Sort(PersonHelper.CompareByName);&lt;br /&gt;            listBox1.Items.Clear();&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Person p &lt;span class="kwrd"&gt;in&lt;/span&gt; m_ListPerson)&lt;br /&gt;            {&lt;br /&gt;                listBox1.Items.Add(p.FirstName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// use anonymous delegate to approach the sort function &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; buttonSortByDelegate_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;//public delegate int Comparison&amp;lt;T&amp;gt;(T x, T y);&lt;/span&gt;&lt;br /&gt;            m_ListPerson.Sort(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(Person p1, Person p2) { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Compare(p1.FirstName, p2.FirstName); });&lt;br /&gt;            listBox1.Items.Clear();&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Person p &lt;span class="kwrd"&gt;in&lt;/span&gt; m_ListPerson)&lt;br /&gt;            {&lt;br /&gt;                listBox1.Items.Add(p.FirstName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Use Helper class and named method to approach the find function&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; buttonFind_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            PersonHelper personHelper = &lt;span class="kwrd"&gt;new&lt;/span&gt; PersonHelper();&lt;br /&gt;            personHelper.FirstName = &lt;span class="str"&gt;"TOM"&lt;/span&gt;;&lt;br /&gt;            Person person = m_ListPerson.Find(personHelper.CompareByNamePredicate);&lt;br /&gt;            listBox1.Items.Clear();&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (person != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                listBox1.Items.Add(person.FirstName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// use anonymous delegate to approach the find function &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; buttonFindByDelegate_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;///public delegate bool Predicate&amp;lt;T&amp;gt;(T obj);&lt;/span&gt;&lt;br /&gt;            Person person = m_ListPerson.Find(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(Person p) { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Equals(p.FirstName, &lt;span class="str"&gt;"TOM"&lt;/span&gt;); });&lt;br /&gt;            listBox1.Items.Clear();&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (person != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                listBox1.Items.Add(person.FirstName);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// This is a simple Class&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; m_FirstName;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; m_FirstName; }&lt;br /&gt;            set { m_FirstName = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; firstName)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.m_FirstName = firstName;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// This is helper class, which provides sort and find capablity for Generic Collection Class&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PersonHelper&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// implement the compare method, and it has the same signature with delegate Comparison&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="p1"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="p2"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;//public delegate int Comparison&amp;lt;T&amp;gt;(T x, T y);&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CompareByName(Person p1, Person p2)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Compare(p1.FirstName, p2.FirstName);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; m_FirstName;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; m_FirstName; }&lt;br /&gt;            set { m_FirstName = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// /// implement the predicate method in order to find one person, and it has the same signature with delegate Predicate&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="p"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;///public delegate bool Predicate&amp;lt;T&amp;gt;(T obj);&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; CompareByNamePredicate(Person p)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Equals(p.FirstName, m_FirstName);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2306998578179538885?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2306998578179538885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2306998578179538885' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2306998578179538885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2306998578179538885'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/02/using-list-and-find-by-delegate.html' title='Using List&amp;lt;T&amp;gt;.Sort() and Find() by delegate'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2491854901487400620</id><published>2008-01-31T23:41:00.001-08:00</published><updated>2008-01-31T23:41:23.551-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Cmd_shell'/><title type='text'>VBScript debug and execute</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: VBscript, debugger, execute&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;同事要我帮助他修改他的一个VBScript脚本, 当我收到邮件后, 我在想, 1.我该怎样运行这个脚本; 2. 我该使用什么编辑器?; 3.有没有比较好的script调试器?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;首先google, 微软最新的脚本执行器为Microsoft script 5.7 版本. 需要download并install. 执行脚本的方法是: cscript yourscript.vbs [options], 详见cscript /?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;用什么编辑器编辑VB script呢? 最好能有intellisense功能, Visual studio 6有一个这样的编辑器. 但可以使用Office软件的VBA editor.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2491854901487400620?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2491854901487400620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2491854901487400620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2491854901487400620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2491854901487400620'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/vbscript-debug-and-execute.html' title='VBScript debug and execute'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7123037079094540072</id><published>2008-01-31T17:50:00.001-08:00</published><updated>2008-01-31T17:50:48.165-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><title type='text'>Zip Rar Outlook Excel Word password remove tool</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: password remove&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;trial version: &lt;a href="http://www.apasscracker.com/download/"&gt;http://www.apasscracker.com/download/&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;It has can only recovery a few pdf pages if trial version was used.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;and this company has also other password crack tools, for zip, rar, GoogleTalk, MSN, Outlook, Excel, Word, PST file.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7123037079094540072?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7123037079094540072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7123037079094540072' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7123037079094540072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7123037079094540072'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/zip-rar-outlook-excel-word-password.html' title='Zip Rar Outlook Excel Word password remove tool'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1964781398334018927</id><published>2008-01-31T17:47:00.000-08:00</published><updated>2008-01-31T17:48:34.520-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cracker'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><title type='text'>PDF restriction remove tool</title><content type='html'>&lt;p&gt;Keywords: decrypt pdf, allow print permission, change permission restrication&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Some ebooks are in pdf format, but they probably have some permission restrication, such as disable print or save.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There are some tools that can remove the restrications.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;1. PDF password remover 3.0&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.verypdf.com/"&gt;http://www.verypdf.com/&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;its registration key maker: &lt;a href="http://crackdb.org/get_112804_PDF.Password.Remover.v3.0_crack.html"&gt;http://crackdb.org/get_112804_PDF.Password.Remover.v3.0_crack.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;2. Atomic PDF Password Recovery&lt;/p&gt;&lt;br /&gt;&lt;p&gt;trial version: &lt;a href="http://www.apasscracker.com/download/"&gt;http://www.apasscracker.com/download/&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;It has can only recovery a few pdf pages if trial version was used.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;and this company has also other password crack tools, for zip, rar, GoogleTalk, MSN, Outlook, Excel, Word, PST file.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1964781398334018927?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1964781398334018927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1964781398334018927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1964781398334018927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1964781398334018927'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/pdf-restriction-remove-tool.html' title='PDF restriction remove tool'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1066248186295650064</id><published>2008-01-30T21:44:00.001-08:00</published><updated>2008-01-30T21:44:57.289-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>short introduction of c# syntax</title><content type='html'>&lt;p&gt;Keywords: C#, Syntax&lt;/p&gt;&lt;br /&gt;&lt;p&gt;i sometimes forget some c# basic. There are some links which can help me keep in mind.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Sharp New Language: C# Offers the Power of C++ and Simplicity of Visual Basic&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/0900/csharp/default.aspx"&gt;http://msdn.microsoft.com/msdnmag/issues/0900/csharp/default.aspx&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;C++ -&amp;gt; C#: What You Need to Know to Move from C++ to C#&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/01/07/ctocsharp/"&gt;http://msdn.microsoft.com/msdnmag/issues/01/07/ctocsharp/&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-FAMILY: verdana, helvetica"&gt;Nice Things About C#&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.cs.princeton.edu/~cdecoro/csharp.html"&gt;http://www.cs.princeton.edu/~cdecoro/csharp.html&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1066248186295650064?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1066248186295650064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1066248186295650064' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1066248186295650064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1066248186295650064'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/short-introduction-of-c-syntax.html' title='short introduction of c# syntax'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8934172701187512296</id><published>2008-01-29T22:17:00.001-08:00</published><updated>2008-02-21T17:54:41.082-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Download Web Content other than using WebClient class</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: WebClient, UTF-8, WebRequest&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;从一个URI上下载网页Content或Xml, 可以直接使用WebClient类(在System.Net命名空间), 非常简单. 它有很多Download方法, 比如DownloadString()和DownloadFile(). 这些都是同步方法, 当然它也有异步Download方法, 不过经常用的是它的同步方法.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;但在用WebClient.DownloadString()一个以UTF-8编码格式存盘的一个Xml文件时, 得到的Xml字符串有乱码, 不管怎样设置WebClient的Encode属性都没有用处, 可能是WebClient的一个bug吧.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;可以WebRequest方法来实现同步DownloadString的功能. 代码如下:&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DownloadAndLoadXml(&lt;span class="kwrd"&gt;string&lt;/span&gt; uri, XmlDocument doc)&lt;br /&gt;        {&lt;br /&gt;            System.Net.WebRequest request = System.Net.WebRequest.Create(uri);&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (System.Net.WebResponse response=request.GetResponse())&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (System.IO.Stream stream=response.GetResponseStream())&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (stream.Length &amp;gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    stream.Position = 0;&lt;br /&gt;                    doc.Load(stream);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// download the web page from the given uri&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="uri"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; DownloadStringFromWeb(&lt;span class="kwrd"&gt;string&lt;/span&gt; uri)&lt;br /&gt;        {&lt;br /&gt;            System.Net.WebRequest request = System.Net.WebRequest.Create(uri);&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (System.Net.WebResponse response = request.GetResponse())&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (System.IO.Stream stream = response.GetResponseStream())&lt;br /&gt;            {&lt;br /&gt;                System.IO.StreamReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(stream);&lt;br /&gt;                &lt;span class="rem"&gt;//save all info from stream into a string variable &lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;string&lt;/span&gt; result=reader.ReadToEnd();&lt;br /&gt;                reader.Close();&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8934172701187512296?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8934172701187512296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8934172701187512296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8934172701187512296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8934172701187512296'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/download-web-content-other-than.html' title='Download Web Content other than using WebClient class'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-6138254579161356473</id><published>2008-01-29T02:30:00.000-08:00</published><updated>2008-01-29T22:22:20.368-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DesignPattern'/><category scheme='http://www.blogger.com/atom/ns#' term='UsefulCode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>XmlBeautifier tool development</title><content type='html'>&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;&lt;strong&gt;Keywords: Event, Class Inherit, Drag and drop supported&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;Preface&lt;/h1&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 10pt"&gt;一直想写一个具有实际功能的C#例程, 来加深我对C# Event和Delegate的理解. 这个例程最好不要太庞大, 因为庞大的程序需要考虑的东西太多, 容易跑题. 碰巧在项目中, 经常需要查看Word2007的docx文件包中Xml文件(注: docx格式为zip格式, 里面包含很多xml文件, 但这些xml文件的element没有缩进). 我喜欢用Notepad++这个编辑器, 但用Notepad++不支持没有缩进的xml的collapse element功能, 浏览起来并不直观. 所以打算写一个小工具, 能够缩进xml的element. 这个工具我命名为XmlBeautifier.&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;Dev Environment:&lt;/h1&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;Visual Studio 2005, .Net Framework 2.0, .Net Framework 3.0&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;System Design&lt;/h1&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 10pt"&gt;XmlBeautifier设计初衷是能处理docx中的xml文件, 为了使它更具通用性, 它应该还能处理单个的xml文件, 最好还能批量处理一个目录下的所有xml文件. 我设计一个抽象基类SourcePackage, 它有3个子类, 分别是DirectoryPackage(负责批量处理某个目录下所有文件的美化), DocxPackage(负责处理docx文件), 以及SingleFilePackage(负责处理单一xml文件) .&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 10pt"&gt;SourcePackage类是整个程序的核心. CollectFileStream()是一个抽象方法, 负责获取这个包中的所有文件的流, 三个子类都要实现这个方法; 因为需要将包中文件以流的形式加载到内存, 所以SourcePackage类需要实现IDisposable接口, 来释放文件流资源; BeautifyFiles()负责执行xml文件的美化工作, 当把所有的文件以流的形式加载到一个m_ListFileStream后, BeautifyFiles()方法就很简单, 循环各个文件流, 分别美化它们.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;img src="http://lh4.google.com/WadeLiu2008/R5_myJxQ1VI/AAAAAAAAAD0/ENrQLz340jk/windows_xml_SourcePackage.PNG" style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px"/&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1 lang="" xml:lang=""&gt;Extra Features Design&lt;/h1&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 10pt"&gt;一个好的程序应该是用户友好型的, 对于我们这样的小工具, 也要做到这样. 为此, 我为这个工具增加2个必要的feature. F1. 用户能够处理的进度; F2.工具支持文件(或目录)的拖拉处理.&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;F1. 为了是工具能实时显示处理的进度, 需要为SourcePackage类增加两个事件Handler, 一个是OneXmlProcessedHandler(当一个文件被处理完后, 这个Handler会被Invoke); 另一个是ProcessOverHandler(当整个文件包被处理完毕后, 这个Handler会被Invoke). 这2个Handler的类型为delegate, 分别为OneXmlProcessedEventHandler, ProcessOverEventHandler. 为了能将Package的文件总数和当前处理的文件Index传给UI类, 我定义了ProcessCountEventArgs这个类, 这样UI类的EventHandler就能获取这些信息. 有关事件的详细论述, 请看我的&lt;a href="http://focuswindows.blogspot.com/2008/01/understand-event-of-c.html"&gt;另一篇文章&lt;/a&gt; .&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;&lt;img src="http://lh4.google.com/WadeLiu2008/R5_mzJxQ1WI/AAAAAAAAAD8/YjjEtbewVrA/windows_xml_EventModule.png" style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px"/&gt;&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0.14in" xml:lang=""&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;F2. 拖拉的支持&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN: 0in 0in 10pt"&gt;C#的Form和Panel都有个bool型属性AllowDrop, 只要AllowDrop=true, 你就可以在资源管理器中将文件或目录拖到Form(或Panel)上, 只不过鼠标Cursor不对头, 在Panel的DragEnter事件中设置DragEventArgs参数的Effect就可以.&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;当文件 ( 或目录 )Drop 到 Panel 后 , 需要美化这些文档 , 在 Panel 的 DragDrop 事件中调用相应的代码就可 . 调用之前需判断 Drop 下的东西是否是文件或目录 .&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%"&gt;private void panelDrop_DragDrop(object sender, DragEventArgs e)&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%" xml:lang=""&gt;{&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%"&gt;if (e.Data.GetDataPresent(DataFormats.FileDrop))&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%" xml:lang=""&gt;{&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%"&gt;String[] filenames = (String[])e.Data.GetData(DataFormats.FileDrop);&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%" xml:lang=""&gt;textBoxSourcePath.Text = filenames[0];&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%" xml:lang=""&gt;ProcessBeautify() ;&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0in; LINE-HEIGHT: 100%" xml:lang=""&gt;}&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0.14in" xml:lang=""&gt;}&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;主要类的 Class Diagram 见下图 .&lt;/p&gt;&lt;br /&gt;&lt;p lang="" style="MARGIN-BOTTOM: 0.14in" xml:lang=""&gt;&lt;img src="http://lh6.google.com/WadeLiu2008/R5_m0pxQ1XI/AAAAAAAAAEE/92w-CXOznOk/Windows_xml_OverallModule.PNG" style="BORDER-TOP-WIDTH: 0px; DISPLAY: inline; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; WIDTH: 1024px; HEIGHT: 819px; BORDER-RIGHT-WIDTH: 0px" height="819" width="1024"/&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="MARGIN-BOTTOM: 0.14in"&gt;代码下载 (&lt;a title="xmlBeautifier_Src.zip" href="http://www.mediamax.com/wadewindows/Hosted/blogs/src/xmlBeautifier_Src.zip" id="r8ic" name="r8ic"&gt;xmlBeautifier_Src.zip&lt;/a&gt; ), 可执行文件下载 (&lt;a title="XmlBeautifier_Bin.zip" href="http://www.mediamax.com/wadewindows/Hosted/blogs/bin/XmlBeautifier_Bin.zip" id="oo9q" name="oo9q"&gt;XmlBeautifier_Bin.zip&lt;/a&gt; )&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-6138254579161356473?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/6138254579161356473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=6138254579161356473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6138254579161356473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6138254579161356473'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/xmlbeautifier-tool-development.html' title='XmlBeautifier tool development'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-6284160957108281832</id><published>2008-01-28T22:13:00.001-08:00</published><updated>2008-01-28T22:14:08.817-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Registry'/><title type='text'>disable the screensaver broadcasted on the intranet</title><content type='html'>&lt;p&gt;&lt;strong&gt;Keywords: Screen Saver&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;公司电脑屏保非常烦人, 3分钟不用, 就启动屏保, 退出屏保要输密码. 禁止屏保的办法是修改注册表.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Registry Entry: HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Control Panel\Desktop&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-6284160957108281832?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/6284160957108281832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=6284160957108281832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6284160957108281832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6284160957108281832'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/disable-screensaver-broadcasted-on.html' title='disable the screensaver broadcasted on the intranet'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-8350369227243284446</id><published>2008-01-27T21:47:00.001-08:00</published><updated>2008-05-04T02:41:03.532-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DesignPattern'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>understand event of c#</title><content type='html'>&lt;p style="margin: 0in 0in 10pt;"&gt;&lt;strong&gt;Keywords: Event, delegate, Publish and subscribe pattern&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;我打算设计一个程序, 它能一次性美化一个目录之下所有的xml文件, 在UI上, 要求能显示处理的进度(即每处理完一个xml文件, UI的ProgressBar就变化一下). 美化xml的由SourcePackage类的BeautifyFiles方法完成, 而UI是另一个类FormMain. 显然这要处理SourcePackage类和FormMain类之间的通讯问题. 怎样解决这个问题呢? 这其实这是一个如何解耦的问题.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;如果你学过C语言, 你会很自然想到使用回调函数, 即在FormMain类中新增一个方法, 比如UpdateProgressBar(), 然后将UpdateProgressBar()这个函数传给SourcePackage.BeautifyFiles()方法. 这确实是一个解决方法. 即将一个被调用者传给调用者. 这种方法直接有效, 但耦合度很高.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;另一个方案是, 采用Publish-Subscribe模式, 使用这个模式, 首先要定义一个通知, 即发布什么, 以及订阅什么. 就本实例来讲, 这个通知就是一个xml文件已经被处理完了, 在UI类中, 订阅这个通知, 然后再编写这个通知的一个Handler函数(即进行更新进度条).&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;C#就是采用Publish-Subscribe来实现Event, 因为C#Delegate支持多播, 所以非常完美地实现了Publish-subscribe; 如果你使用C++, 也可采用了Observer模式来实现Event. 我们用C#的Event来实现设计要求. 设计的详细思路是:&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;在Publish方(Publish方多数为一个服务的服务端), 需要完成的工作是:&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; text-indent: -0.25in;"&gt;(1) 如果需要的话,使用delegate来定义通知类型, (一般的EventHandler已经在Framework中定义了, 特殊的Handler需要自定义)&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in;"&gt;public delegate void OneXmlProcessedEventHandler(object sender, ProcessCountEventArgs e);&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; text-indent: -0.25in;"&gt;(2) 在SourcePackage类中, 使用event关键字来发布通知.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in;"&gt;public event OneXmlProcessedEventHandler OneXmlProcessed;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; text-indent: -0.25in;"&gt;(3) 在SourcePackage.BeautifyFiles()触发这个通知的Handler.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;foreach (Stream fileStream in m_ListFileStream)&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;{&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;m_FileBeautifier.FileStream = fileStream;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;m_FileBeautifier.Beautify();&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;if (OneXmlProcessed != null)&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;{&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;eventArgs.ProcessedIndex = eventArgs.ProcessedIndex+1 ;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;OneXmlProcessed(this, eventArgs);&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;}&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt 0.5in;"&gt;}&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;在Subscribe方(Subscribe方多为服务的消费端), 需要完成的工作是:&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; text-indent: -0.25in;"&gt;(1) 订阅这个通知&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in; line-height: normal;"&gt;SourcePackage sourcePackage = new SourcePackage(packageFullName);&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in;"&gt;sourcePackage.OneXmlProcessed += new OneXmlProcessedEventHandler(OneXmlProcessedHandler);&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt 0.5in; text-indent: -0.25in;"&gt;(2) 编写通知Handler&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt; line-height: normal;"&gt;void OneXmlProcessedHandler(object sender, ProcessCountEventArgs e)&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt; line-height: normal;"&gt;{&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt; line-height: normal;"&gt;const string progressIndicator="{0} of {1} is proceeded!" ;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt; line-height: normal;"&gt;toolStripStatusLabel1.Text = string.Format(progressIndicator, e.ProcessedIndex, e.FileCount);&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt; line-height: normal;"&gt;toolStripProgressBar1.Value = e.ProcessedIndex;&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt; line-height: normal;"&gt;Application.DoEvents();&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt;}&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 0pt 0.5in;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt 0.5in;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt; &lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0in 0in 10pt;"&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-8350369227243284446?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/8350369227243284446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=8350369227243284446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8350369227243284446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/8350369227243284446'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/understand-event-of-c.html' title='understand event of c#'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-1574186951462972708</id><published>2008-01-25T02:12:00.001-08:00</published><updated>2008-01-27T21:50:18.424-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>how to use XmlDocument.Save and XmlWriter</title><content type='html'>&lt;p&gt;&lt;span style="TEXT-DECORATION: none"&gt;Keywords: XmlDocument class, XmlWriter, FileStream, StringBuilder&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;原本想使用XmlWriter来格式化一个文件流, 结果是: Xml是被格式化了, 但格式化后的字符串是append到原来的流中, 而不是重写到文件流中. 为什么会出现这个现象呢? 我们先分析一下原来的代码:&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BeautifyXml(FileStream fileStream)&lt;br /&gt;        {&lt;br /&gt;            XmlDocument xmlDoc = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlDocument(); &lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//1. 重置m_fileStream的position为0, 否则xmlDoc.Load可能会出现异常&lt;/span&gt;&lt;br /&gt;            fileStream.Position = 0;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//2. 加载m_FileStream的内容到xmlDoc&lt;/span&gt;&lt;br /&gt;            xmlDoc.Load(fileStream);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//3. 创建一个XmlWriterSettings对象, 设置它的Format&lt;/span&gt;&lt;br /&gt;            XmlWriterSettings xmlWriterSettings = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlWriterSettings();&lt;br /&gt;            xmlWriterSettings.Indent = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;            xmlWriterSettings.IndentChars = &lt;span class="str"&gt;"  "&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//4.创建一个输出到fileStream的XmlWriter&lt;/span&gt;&lt;br /&gt;            XmlWriter writer = XmlWriter.Create(fileStream, xmlWriterSettings);&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//5.保存XmlDocument的内容, 即输出到fileStream&lt;/span&gt;&lt;br /&gt;            xmlDoc.Save(writer);&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;在step2之后,XmlDoc对象已经完成Xml的加载, 然后在step4创建了一个输出到fileStream的XmlWriter, step5用xmlDoc.Save(writer)输出Xml到流中. 可以想象保存动作执行顺序应该是xmlDoc.Save()---&amp;gt;writer---&amp;gt;fileStream, 在保存时fileStream还保存着原来未被格式化的内容, 所以writer将xml的内容追加到fileStream. 知道问题的原因, 解决方案就简单了. 在step5之前先将fileStream的内容清空,可以用下面语句&lt;/p&gt;&lt;br /&gt;&lt;p&gt;fileStream.SetLength(0);&lt;br /&gt;&lt;br/&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-1574186951462972708?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/1574186951462972708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=1574186951462972708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1574186951462972708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/1574186951462972708'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/how-to-use-xmldocumentsave-and.html' title='how to use XmlDocument.Save and XmlWriter'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-2444352425967512972</id><published>2008-01-24T23:03:00.001-08:00</published><updated>2008-01-24T23:05:27.670-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><title type='text'>Hide program window by using HideWindowHotkey software</title><content type='html'>&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-FAMILY: Arial"&gt;&lt;strong&gt;Keywords: Hide program software window, Hide Window Hotkey&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-FAMILY: Arial"&gt;&lt;strong&gt;Hide Window Hotkey&lt;/strong&gt; is a utility which allows you to hide the windows, and programs which are running on your screen.It will instantly hide or close all (or some) programs through mouse hotkey or keyboard hotkey.It also could resize your programs automatically,such as maximize, minimize,normal,minimize to tray.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-FAMILY: Arial"&gt;&lt;a href="http://www.elongsoft.com/" target="_blank"&gt;http://www.elongsoft.com&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-2444352425967512972?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/2444352425967512972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=2444352425967512972' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2444352425967512972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/2444352425967512972'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/hide-program-window-by-using.html' title='Hide program window by using HideWindowHotkey software'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3660909607556971048</id><published>2008-01-24T23:00:00.001-08:00</published><updated>2008-01-24T23:00:15.429-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='MustNeedSoftware'/><title type='text'>Minimize software window to system tray</title><content type='html'>&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Keywords: Tools, Minimize software window to TrayIcon&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Trayconizer&lt;/strong&gt;, This is a cool little software. It allows you to minimize almost applications to system tray. Using Trayconizer is simple. To start TrayConizer on Notepad, you would execute: c:\Path\to\Trayconizer.exe c:\windows\notepad.exe&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.whitsoftdev.com/trayconizer/"&gt;http://www.whitsoftdev.com/trayconizer/&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-3660909607556971048?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/3660909607556971048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=3660909607556971048' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3660909607556971048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/3660909607556971048'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/minimize-software-window-to-system-tray.html' title='Minimize software window to system tray'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7572722583910523291</id><published>2008-01-23T02:16:00.000-08:00</published><updated>2008-01-23T02:29:27.842-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>Getting Started with NUnit</title><content type='html'>&lt;div&gt;         &lt;h1&gt;&lt;span style="font-family:Arial;font-size:180%;"&gt;&lt;b&gt;Getting Started with  NUnit&lt;/b&gt;&lt;/span&gt;&lt;/h1&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Richard Davis, SharpLogic Software&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;In this article, we will take a look  at unit testing, test-driven development, and the NUnit framework. If  you are already familiar with these topics and are instead looking for  information about how it all ties in with the Software Design Competition,  feel free to skip ahead to the &lt;/span&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;NUnit  and the Software Design Competition&lt;/u&gt;&lt;/span&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;  section.&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Prerequisite&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Read and complete the steps described  in the &lt;/span&gt;&lt;a href="http://imaginecup.sharplogic.com/Downloads/Getting%20Started%20With%20The%20Software%20Design%20Competition.doc"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;Getting Started With The Software  Design Competition&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt; article.  This will give you a cursory introduction to the process of using the  NUnit GUI application to run test code.&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Requirements and Setup&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;One of the great advantages of competing  in the Imagine Cup Software Design Competition is that you’re able  to use the best tools available, and they’re absolutely free!&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Download and install a version    of Visual Studio 2005 Express from &lt;/span&gt;&lt;a href="http://msdn.microsoft.com/vstudio/express/"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://msdn.microsoft.com/vstudio/express/&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;. You can use any language to develop your class    library, but the baseline source code and tests are provided in C# so    you’ll need to have that installed if you want to use them. Install    with the default settings.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Note: You may use any version of  Visual Studio 2005 that you have available.&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ol start="2" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Download the “NUnit 2.2.8    for .NET 2.0 MSI” installer from &lt;/span&gt;&lt;a href="http://www.nunit.org/index.php?p=download"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://www.nunit.org/index.php?p=download&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt; and install it with the default settings.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Download the practice Level    100 Tutorial challenge from &lt;/span&gt;&lt;a href="http://imaginecup.sharplogic.com/Challenge.aspx?challenge=4265d098-52ac-4eb6-8549-e8ab652d99b8"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://imaginecup.sharplogic.com/Challenge.aspx?challenge=4265d098-52ac-4eb6-8549-e8ab652d99b8&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt; and unzip it to a convenient location, such    as “C:L100MathLib”. At this point you should have a directory structure    that looks like the following:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Unzip the challenge package (C:L100MathLibL100Math.zip)  to the “C:L100MathLib” directory so that its contents are placed  into the “C:L100MathLibL100Math” directory. The resulting directory  should look like the following:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Test-Driven Development and  Unit Testing&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Testing software is an integral phase  of the development lifecycle. As software projects grow in size, so  too does the complexity. Complexity can refer to the size of the source  code base, architecture and design of components, number of code paths,  and even algorithmic considerations. The decisions to be made about  testing have to do with the “when” and the “how”, not the “why”.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Software testing provides a valuable  means to help verify that software was build correctly, but it can also  serve as a form of requirements specification up front. Consider the  development of a method that computes the division of two integral numbers:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; Divide(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; dividend, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; divisor)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;{ }&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;To devise tests for this method we need  to think like a tester. This process includes asking questions like  the following:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;What are the types of input    and what is the set of values they can possess?&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;What is the expected return    type? Are there any restrictions to be considered upon return to the    caller?&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;If the input includes reference    types, is null (C#) or nothing (VB.NET) ever passed in?&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;It is important to identify and test  for cases where state and input lead to faulty operation. In the case  of the Divide method, we can determine that the operation is invalid  when the divisor input is zero. Next, we can write a test to exercise  the Divide method and check for the desired response. In the case of  the Divide method, we expect a &lt;i&gt;System.DivideByZeroException&lt;/i&gt; to  be thrown when the divisor input is zero. &lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The test method that we just devised  is a type of &lt;b&gt;unit test&lt;/b&gt;. Unit tests typically look for a very  specific result from an operation. This means that there is often a  many to one relationship of tests to one piece of code. Consider the  Divide method once again. We already have one test designed, but we  also want tests that make sure various valid inputs return the correct  results.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;As you can see from the Divide example,  the development of unit tests can be done before the application code  is implemented. This process is known as &lt;b&gt;test-driven development&lt;/b&gt;,  and it provides many benefits:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Requirements are self-documented.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests are automatic and repeatable.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests are designed to work    with known bad and good input values.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The development of unit tests provides  an automatic and repeatable method for verifying the correct functioning  of code. Each time code is added or modified in a project, the suite  of unit tests can be re-run to make sure that the changes did not break  functionality that worked previously. The act of re-running a suite  of unit tests is known as regression testing.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Keep in mind that unit testing does not  guarantee that software will be free of bugs. Generally speaking, it  is not realistic to get full code path coverage that exercises the entire  set and combinations of input to all methods in a piece of software.  In addition, the quality of testing relies solely on the developer of  the tests. There may be cases where a unit test fails to identify problems  in code. Nevertheless, test-driven development and unit testing are  powerful allies to have throughout the software development lifecycle.&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Developing Tests for  NUnit&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;In this section, we will walk through  the development of some simple unit tests that target the NUnit testing  framework. Make sure that you have downloaded and installed the &lt;i&gt;L100Math&lt;/i&gt;  example as described in the &lt;/span&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;Requirements  and Setup&lt;/u&gt;&lt;/span&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt; section before continuing.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Load the &lt;i&gt;L100Math&lt;/i&gt; solution    file with Visual Studio 2005:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ol type="a"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Double-click on the &lt;i&gt;L100Math.sln&lt;/i&gt;    file that you previously downloaded and extracted to your computer (C:L100MathLibL100MathL100Math.sln).&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ol start="2" type="a"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Double-click on the &lt;i&gt;MathHelperTests.cs&lt;/i&gt;    source file.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol start="2" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Examine the &lt;i&gt;MathHelperTests&lt;/i&gt;    class found within the &lt;i&gt;MathHelperTests.cs&lt;/i&gt; source file. Notice    that the test class has an attribute named &lt;b&gt;TestFixture&lt;/b&gt; attached    to it. This attribute is defined as part of the NUnit framework and    is used by NUnit to determine which classes contain tests.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Examine the test methods found    within the &lt;i&gt;MathHelperTests.cs&lt;/i&gt; source file:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ol type="a"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;There are two test methods    designed to test the functionality of the &lt;i&gt;MathHelper.Add&lt;/i&gt; method, &lt;i&gt;   TestAdd&lt;/i&gt; and &lt;i&gt;TestAdd2&lt;/i&gt;.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ol start="2" type="a"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Each test method is marked    with the &lt;b&gt;Test&lt;/b&gt; attribute so that NUnit can locate designated tests.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Each test method is responsible    for conducting tests in way that allows the NUnit framework to determine    when a test is a success or failure. This is done by using the NUnit &lt;b&gt;   Assert&lt;/b&gt; class. In the &lt;i&gt;TestAdd&lt;/i&gt; test method, we add 3 and 5    together and store the result. Next, the &lt;b&gt;Assert.AreEqual&lt;/b&gt; method    is given the expected result, the actual result, and a message to be    presented to the user in case the provided values are not equal.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol start="4" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Add a new test method to the &lt;i&gt;   MathHelperTests&lt;/i&gt; class which tests for the raising of a &lt;i&gt;DivideByZeroException&lt;/i&gt;    when  the divisor parameter is zero:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ol type="a"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Copy and paste the following    code:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;[&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Test&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;]&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;[&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;ExpectedException&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;DivideByZeroException&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;))]&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;void&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; TestDivide2()&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;{&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;p&gt;      &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;  quotient = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;MathHelper&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.Divide(4, 0);&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ol start="2" type="a"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Here we used another NUnit    framework attribute named &lt;b&gt;ExpectedException&lt;/b&gt; to inform NUnit that    the test will be considered a success if the specified &lt;i&gt;DivideByZeroException&lt;/i&gt;    exception type is thrown.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Note that we could alternatively    wrap the call to the &lt;i&gt;MathHelper.Divide&lt;/i&gt; method within a try…catch    block. The test will succeed in this case because we prevent the &lt;i&gt;   DivideByZeroException&lt;/i&gt; from being propagated up the call stack to    the NUnit framework.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;[&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Test&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;]&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;void&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; TestDivide2()&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;{&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;    &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;try&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;    {&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;        &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;  quotient = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;MathHelper&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.Divide(4, 0);&lt;/span&gt; &lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;        &lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.Fail(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"MathHelper.Divide(4,  0) " + &lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;                &lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"failed to throw a  DivideByZeroException."&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;);&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;    }&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;    &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;catch&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;  (&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;DivideByZeroException&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;    {&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;        &lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;    }&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;    &lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;It is important to note the requirements  for the most essential NUnit framework attributes, TestFixture and Test. &lt;b&gt; TestFixture&lt;/b&gt; requires the following from the class that it is applied  to:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Public scope.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;A public, default constructor    without parameters.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;If a method that is marked with the TestFixture  attribute does not have a default constructor with the correct signature,  i.e. you marked it as private instead of public; all tests will fail  to run. The reason will be listed under the &lt;b&gt;Tests Not Run&lt;/b&gt; tab  as shown below.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Note: You should just leave out the constructor  unless you need to perform initialization.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The &lt;b&gt;Test&lt;/b&gt; attribute requires the  following from the method that it is applied to:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Public scope.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Void return type.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;No parameters.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;If a method that is marked with the Test  attribute does not return void, the test will not be run by NUnit and  the reason why will be listed under the &lt;b&gt;Tests Not Run&lt;/b&gt; tab as  shown below.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assertions are another very important  topic to become familiar with as you gain more experience using the  NUnit platform. The Assert.AreEqual method, which we just saw in action,  is categorized as an equality assertion by NUnit. Another type of equality  assertion is the &lt;b&gt;Assert.AreNotEqual&lt;/b&gt; method, which does exactly  what its name implies. Other categories of assertion include &lt;b&gt;identity&lt;/b&gt;, &lt;b&gt; comparison&lt;/b&gt;, &lt;b&gt;type&lt;/b&gt;, and &lt;b&gt;condition&lt;/b&gt;. The following tables  describe a number of the different assertion categories and their methods:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;a name="table01"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;ul&gt;&lt;table border="2" cellspacing="0" width="583"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Equality    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.AreEqual&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether the expected    and actual arguments are equal, asserting when they are not equal.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.AreNotEqual&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Opposite of AreEqual method.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    a successful AreEqual test.&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; expected = 5;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; actual = 5;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.AreEqual(expected, actual, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"Expected and actual    values are not&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;       equal."&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;);&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/ul&gt; &lt;/div&gt; &lt;br /&gt;&lt;a name="table02"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;table border="2" cellspacing="0" width="583"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Identity    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.AreSame&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether the expected    and actual arguments are the same object reference, asserting when they    are not the same.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.AreNotSame&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Opposite of AreSame method.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.Contains&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether an object    is contained in an array or list.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    a successful AreSame test.&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; objA = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;();&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; objB = objA;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.AreSame(objA, objB, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"Object    references are not the same."&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;);&lt;/span&gt;&lt;br /&gt;  &lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example    shows a successful Contains test.&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;string&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;[] myArray = { &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"a"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"b"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"c"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; };&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.Contains(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"b"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;, myArray, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"Array    does not contain expected&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;       value."&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;);&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt; &lt;br /&gt;&lt;a name="table03"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;table border="2" cellspacing="0" width="583"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Comparison    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.Greater&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether one object    is greater than another.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.Less&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether one object    is less than another.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    a successful Less test (arg1 &amp;lt; arg2).&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; arg1 = 5;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; arg2 = 6;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.Less(arg1, arg2);&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt; &lt;br /&gt;&lt;a name="table04"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;table border="2" cellspacing="0" width="583"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Type    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;IsInstanceOfType&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether an object    is of a specified type or derived from a specified type, asserting when    it is not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;IsNotInstanceOfType&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Opposite of IsInstanceOfType    method.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;IsAssignableFrom&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether it is valid    to assign an instance of the specified type to a given object, asserting    if it is not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;IsNotAssignableFrom&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Opposite of IsAssignableFrom    method.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    a successful IsInstanceOfType test.&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Exception&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; myException = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Exception&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;();&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.IsInstanceOfType(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Exception&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;), myException);&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example    shows a successful IsAssignableFrom test.&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; myObject = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;object&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;();&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.IsAssignableFrom(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Exception&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;), myObject);&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Exception&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; myException = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Exception&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;();&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// Assertion guarantees    that myObject can be assigned myException (or // any other object that    is typeof(Exception)).&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;myObject = myException;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt; &lt;br /&gt;&lt;a name="table05"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;table border="2" cellspacing="0" width="583"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Condition    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsTrue&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether a boolean    condition is true, asserting when it is not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsFalse&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether a boolean    condition is false, asserting when it is.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsNull&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether an object    is null, asserting when it is not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsNotNull&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Opposite of IsNull method.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsNaN&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether a double is    not a number (NaN), asserting when it is not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsEmpty&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;One overload tests whether    a string is empty (string.Empty or “”), asserting when it is not.&lt;/span&gt;&lt;br /&gt;  &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Another overload tests whether a collection    or array is empty, asserting when it is not.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.IsNotEmpty&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Opposite of IsEmpty method.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    an unsuccessful IsNotEmpty test.&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;List&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;&amp;gt; myList = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;List&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;&amp;gt;();&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.IsNotEmpty(myList, &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"List    is empty."&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;);&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt; &lt;br /&gt;&lt;a name="table06"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;table border="2" cellspacing="0" width="583"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Utility    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.Fail&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Throws an AssertionException    with specified failure message.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="30%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assert.Ignore&lt;/span&gt;&lt;/td&gt;   &lt;td width="69%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Causes the current test    to be ignored.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    a custom assertion that fails when the&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// myDouble variable    does not fit within the specified value range.&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;double&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; myDouble = 0.94;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;if&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;    (myDouble &amp;lt; 0.95 || myDouble &amp;gt; 1.05)&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;{&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;       Assert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.Fail(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"Value    is not within the specified range."&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;);&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt; &lt;br /&gt;&lt;a name="table07"&gt;&lt;/a&gt; &lt;div align="left"&gt; &lt;table border="2" cellspacing="0" width="584"&gt; &lt;tbody&gt;&lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;String    Asserts&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;   &lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="45%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Method&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;   &lt;td width="54%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="45%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;StringAssert.Contains&lt;/span&gt;&lt;/td&gt;   &lt;td width="54%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether a string contains    an expected substring, asserting when it does not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="45%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;StringAssert.StartsWith&lt;/span&gt;&lt;/td&gt;   &lt;td width="54%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether a string starts    with an expected substring, asserting when it does not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="45%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;StringAssert.EndsWith&lt;/span&gt;&lt;/td&gt;   &lt;td width="54%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether a string ends    with an expected substring, asserting when it does not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td width="45%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;StringAssert.AreEqualIgnoringCase&lt;/span&gt;&lt;/td&gt;   &lt;td width="54%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Tests whether an expected    string is equal to an actual string ignoring case, asserting when they    are not.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr valign="top"&gt;&lt;td colspan="2" width="100%"&gt;   &lt;span style="font-family:Courier New;font-size:85%;color:#008000;"&gt;// This example shows    a successful AreEqualIgnoringCase test.&lt;/span&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;string&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt; actual = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"test"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;StringAssert&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.AreEqualIgnoringCase(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"tEsT"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;, actual);&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Running Tests Using NUnit&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Assuming that you satisfied the &lt;/span&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;prerequisite&lt;/u&gt;&lt;/span&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt; listed at the beginning of this article, loading  and running tests using the NUnit GUI should be a familiar process at  this point. In this section, we will take a more detailed look at two  ways in which tests can be run and results generated.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;u&gt;NUnit GUI Application&lt;/u&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The NUnit GUI application provides a  complete, easy to use interface with which you can load, select, and  view the results for unit tests. As you are already aware, loading a  test assembly is as simple as selecting &lt;b&gt;File | Open&lt;/b&gt;. Once an  assembly is loaded, the &lt;i&gt;nunit-gui.exe&lt;/i&gt; application will continue  to monitor the file for changes. If you make changes in Visual Studio  and re-compile, the NUnit application will re-load the assembly automatically  so that it remains in sync with your development.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Build the solution by selecting &lt;b&gt;   Build | Build Solution&lt;/b&gt; from the main menu.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The NUnit GUI application works with  .nunit project files, so any configuration options can be tied to an  assembly and saved for future use. If you take a look at the L100MathTests  project again, you will notice a file named &lt;i&gt;L100MathTests.nunit&lt;/i&gt;.  This file stores NUnit project configuration data in an XML format and  it is added to the project as a matter of convenience. &lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Follow these steps to have Visual Studio  open the NUnit project file using the &lt;i&gt;NUnit-Gui.exe&lt;/i&gt; application  by default:&lt;/span&gt;&lt;/p&gt; &lt;ol start="2" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Right-click&lt;/b&gt; on &lt;i&gt;L100MathTests.nunit&lt;/i&gt;    and select &lt;b&gt;Open With&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Select&lt;/b&gt; the &lt;i&gt;NUnit-Gui    (NUnit)&lt;/i&gt; program followed by the &lt;b&gt;Set as Default&lt;/b&gt; button.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Select&lt;/b&gt; the &lt;b&gt;OK&lt;/b&gt;    button.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Now you can load the unit tests by simply &lt;b&gt; double-clicking&lt;/b&gt; on the .nunit project file from &lt;b&gt;Solution Explorer&lt;/b&gt;.  If NUnit fails to launch, you may need to repeat steps 2-4, but this  time add a new program to the list and navigate to the nunit-gui.exe  application explicitly.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;You can run all tests by selecting the  root node and then selecting the &lt;b&gt;Run&lt;/b&gt; button. If tests fail to  meet the assertion criteria, informative messages will be placed in  the &lt;b&gt;Errors and Failures&lt;/b&gt; tab. A red node means that not all tests  passed at that node or at its descendent nodes. Green indicates that  all tests passed at a node and at its descendent nodes. It is also possible  to run individual test classes or even individual tests within test  classes. To do so, simply &lt;b&gt;select&lt;/b&gt; the &lt;b&gt;test node&lt;/b&gt; that you  want to run and then select &lt;b&gt;Run&lt;/b&gt;.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;NUnit test results can be saved for future  use by selecting &lt;b&gt;Tools | Save Results as XML&lt;/b&gt; from the main menu.  If you select the &lt;i&gt;TestAdd&lt;/i&gt; method and run the test, the resulting  XML document will include the following information:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;&amp;lt;test-case name="L100MathTests.MathHelperTests.TestAdd"  executed="True" success="False" time="0.047"  asserts="0"&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;    &amp;lt;failure&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;      &amp;lt;message&amp;gt;&amp;lt;![CDATA[Tested:  MathHelper.Add(3, 5)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;      &lt;span style="font-family:Arial;font-size:85%;"&gt;expected:  &amp;lt;8&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;      &lt;span style="font-family:Arial;font-size:85%;"&gt;  but was: &amp;lt;0&amp;gt;]]&amp;gt;&amp;lt;/message&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;&amp;lt;stack-trace&amp;gt;&amp;lt;![CDATA[    at L100MathTests.MathHelperTests.TestAdd() in C:L100MathLibL100MathL100MathTestsMathHelperTests.cs:line  20&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;p&gt;   &lt;span style="font-family:Arial;font-size:85%;"&gt;]]&amp;gt;&amp;lt;/stack-trace&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;    &amp;lt;/failure&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt; &amp;lt;/test-case&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;This XML tells us that the &lt;i&gt;TestAdd&lt;/i&gt;  method was executed successfully but failed to meet the conditions of  an assertion. A stack trace is also provided to let us know exactly  where the assertion that failed is located.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;u&gt;NUnit Console Application&lt;/u&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The NUnit console application is an alternative  to the GUI application that is capable of performing tests and producing  XML test results. As a quick demonstration, let’s use the NUnit console  application to test the &lt;i&gt;L100Math&lt;/i&gt; library we have been working  with.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Load a command prompt window    by selecting &lt;b&gt;Start | All Programs | Accessories | Command Prompt&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Change the &lt;b&gt;current directory&lt;/b&gt;    to the location where the test DLL is created by Visual Studio when    built as shown below.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="3" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Temporarily modify the &lt;b&gt;   Path&lt;/b&gt; environment variable to include the path to the &lt;i&gt;nunit-console.exe&lt;/i&gt;    application. Use the following command:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;path=%path%;”c:Program  FilesNUnit-Net-2.0 2.2.8bin”&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ol start="4" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Use the NUnit console application    to test all test methods contained within the &lt;i&gt;L100MathTests.dll&lt;/i&gt;    assembly:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;nunit-console  L100MathTests.dll&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Once the NUnit console application  has finished running tests, failure messages are output to the console  window. If you see errors here, it is an indication that you should  check the results XML file for more details. By default, NUnit will  create the results XML file in the same directory where you performed  the tests and name it &lt;b&gt;&lt;i&gt;TestResult.xml&lt;/i&gt;&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ol start="5" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Open the &lt;i&gt;TestResult.xml&lt;/i&gt;    file generated from the last test run. You can do this from an Explorer    window or by issuing the command:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;notepad TestResult.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The NUnit console application can also  use Visual Studio project files and NUnit project files to run tests,  as show in the examples below:&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;Nunit-console  L100MathTests.csproj&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;Nunit-console  L100MathTests.nunit&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Many other options are available for  use with the NUnit console application. Please refer to the official  NUnit documentation for more information.&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;NUnit and the Software Design Competition&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Now that you understand how to write  unit tests for the NUnit framework and use the associated tools, let’s  take a moment to discuss how the Software Design Competition affects  the testing environment and strategy. In this section, we will highlight  important points that competitors will need to keep in mind as they  develop, test, submit, and debug their entries.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The design and nature of the Software  Design Competition has a number of effects upon user-submitted challenge  entries:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Entries must be optimized    enough so that they can complete the tests performed on the backend    before a set timeout.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Entries must only use code    that can run under the &lt;b&gt;“Execution”&lt;/b&gt; permission set.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;For some challenges, it may be difficult  to know how much optimization is necessary because the backend tests  are not available to you. One solution to this problem is to simply  not worry about optimization unless you get a &lt;b&gt;timeout message&lt;/b&gt;  back from the testing server. A timeout message would be something like, &lt;i&gt; “Test has exceeded timeout. 3000 ms.”&lt;/i&gt; If you get a timeout message,  you will need to examine your solution for areas that need to be optimized.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;User-submitted entries will only be given  the ability to execute code as defined by the .NET code access security  policy. This means that you can not use file I/O, sockets, networking,  or other tasks that require more privileges. One way that you can ensure  your code meets this requirement during testing is to add an appropriate &lt;b&gt; PermissionSet&lt;/b&gt; attribute to the top of your classes. The &lt;i&gt;L100Math&lt;/i&gt;  library test class, &lt;i&gt;MathHelperTests&lt;/i&gt;, shows this in action:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;      &lt;span style="font-family:Courier New;font-size:85%;"&gt;[&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;TestFixture&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;]&lt;/span&gt;&lt;/p&gt; &lt;p&gt;      &lt;span style="font-family:Courier New;font-size:85%;"&gt;[&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;PermissionSet&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;(&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;SecurityAction&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;.PermitOnly, Name = &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#800000;"&gt;"Execution"&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;)]&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="font-family:Courier New;font-size:85%;color:#008080;"&gt;MathHelperTests&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Note that you will need to create a unit  test in order to exercise all of your code for this attribute to have  any affect. A security exception will not be thrown until code is executed  that tries to do something that it does not have permission to do.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;The design and nature of the Software  Design Competition also has a number of effects upon the test suite  used on the backend, as well as the test results seen by competitors:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Backend tests may be more    complicated than basic unit tests and use multiple objects containing    multiple asserts.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Backend test results are returned    and presented to the competitor with failure messages only – stack    traces are not made available.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;An ideal unit test is designed to be  as simple as possible to help eliminate the possible causes for failure  when the test is run. However, the Software Design Competition has a  need for a consistent number of unit tests to be performed at each difficulty  level. Because of this, unit tests may be more complicated than is ideal.  It is important to keep in mind that if a unit test has multiple assertions  in it, only the first one will be reported. As a result, a unit test  may continue to fail, even as you fix individual bugs.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Competitors will only have access to  the failure messages retuned from the testing backend. This will be  the only diagnostic information available to you as you develop your  solution to challenges. As the challenges become more difficult, the  failure messages will become less helpful. For example, Level 100 tests  will likely explain the exact method call and parameters that failed,  whereas Level 500 tests may only mention what the test was trying to  accomplish. &lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;You may run into the following types  of failure messages as you progress further into the competition:&lt;/span&gt;&lt;/p&gt; &lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Failure message that indicates    a specific method failed to return the expected results.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Failure message that indicates    a method failed with specified input values.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Failure message that indicates    an exception occurred in a specific method.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Failure message that only    indicates an exception occurred (no other helpful information provided).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Failure message due to incorrect    object inheritance.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Failure message due to missing    interface implementation.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;If you are having difficulty deciphering  a failure message and know which method is causing the problem, try  developing your own unit tests for it to see if you can determine the  root cause for the problem. You may also want to re-consult the specification  provided for the challenge to see if you missed any details pertinent  to the problem at hand. Remember, there is no penalty for revising your  entries and re-submitting them for scoring. However, only your most  recent submission counts, so regression bugs can hurt you if you’re  not careful.&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Debugging  NUnit Tests&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Once you begin to develop unit tests  you may wonder, “How do I test to make sure the tests are correct?”  One tool that you have available is the &lt;b&gt;Visual Studio Debugger&lt;/b&gt;.  Being able to debug the unit tests is useful since it is one of the  easiest ways to exercise our library code. In this section, we will  demonstrate how you can take advantage of the debugger to test your  unit code.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Let’s return to the &lt;i&gt;L100Math&lt;/i&gt;  library that we were working with earlier. Make sure that you have the &lt;i&gt; L100Math&lt;/i&gt; solution file open in Visual Studio and the &lt;i&gt;MathHelperTests.cs&lt;/i&gt;  source file open for viewing.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;There are some differences between the  Visual Studio Express products and the other versions of Visual Studio  that necessitate two different sets of steps to demonstrate debugging.  Please choose the subsection below that applies to you.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;u&gt;Visual Studio Express&lt;/u&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Minimize all open programs    so that your desktop is visible.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Right-click&lt;/b&gt; on the    desktop and select &lt;b&gt;New | Shortcut&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;For the location of the shortcut,    use the following:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;i&gt;"C:Program FilesMicrosoft  Visual Studio 8SDKv2.0GuiDebugdbgclr.exe"&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ol start="4" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;Next&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Use the default name for the    shortcut and select &lt;b&gt;Finish&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;At this point, you should have a shortcut  on the desktop that launches the &lt;b&gt;Microsoft CLR Debugger&lt;/b&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol start="6" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Ensure that the current solution    is built by selecting &lt;b&gt;Build | Build Solution&lt;/b&gt; from the main menu    in Visual Studio.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Double-click on the &lt;i&gt;L100MathTests.nunit&lt;/i&gt;    file in &lt;b&gt;Solution Explorer&lt;/b&gt; to launch the NUnit GUI application.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Launch&lt;/b&gt; the &lt;b&gt;debugger&lt;/b&gt;    from the desktop shortcut.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="9" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;File | Open | File&lt;/b&gt;    from the main menu of the debugger. This will open the &lt;b&gt;Open File&lt;/b&gt;    dialog box.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="10" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Navigate to and &lt;b&gt;open&lt;/b&gt;    the &lt;b&gt;&lt;i&gt;MathHelperTests.cs&lt;/i&gt;&lt;/b&gt; source file.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Place a &lt;b&gt;breakpoint&lt;/b&gt;    at the first line of the &lt;i&gt;TestAdd&lt;/i&gt; method.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="12" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;Tools | Attach    To Process&lt;/b&gt; from the main menu of the debugger.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Locate and &lt;b&gt;select&lt;/b&gt;    the &lt;b&gt;&lt;i&gt;nunit-gui.exe&lt;/i&gt;&lt;/b&gt; process from the list of available processes.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="14" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;Attach&lt;/b&gt; to attach    to the NUnit GUI process. At this point, the assembly containing the &lt;i&gt;   TestAdd&lt;/i&gt; method has not been called yet, so you will see a  symbol    where the breakpoint was set.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Switch back to the NUnit    GUI application and &lt;b&gt;double-click&lt;/b&gt; on the &lt;b&gt;&lt;i&gt;TestAdd&lt;/i&gt;&lt;/b&gt;    method. The breakpoint that you set should be hit and the CLR Debugger    application brought back to the foreground.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="16" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;Debug | Step Into&lt;/b&gt;    from the debugger main menu to enter the &lt;i&gt;MathHelper.Add&lt;/i&gt; method.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Now that you know how to attach to the  NUnit process, the full power of the Microsoft CLR Debugger is at your  fingertips.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;u&gt;Visual Studio Standard or higher&lt;/u&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Place a &lt;b&gt;breakpoint&lt;/b&gt;    at the first line of the &lt;i&gt;TestAdd&lt;/i&gt; method.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="2" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;Right-click&lt;/b&gt; on the &lt;i&gt;   L100MathTests&lt;/i&gt; project in &lt;b&gt;Solution Explorer&lt;/b&gt; and select &lt;b&gt;   Properties&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select the &lt;b&gt;Debug&lt;/b&gt; tab    and fill in the following options:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;&lt;i&gt;Start External Program &lt;/i&gt;&lt;/b&gt; &lt;i&gt;text box&lt;/i&gt;&lt;b&gt;&lt;i&gt;:&lt;/i&gt;&lt;/b&gt; &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;C:Program  FilesNUnit-Net-2.0 2.2.8binnunit-gui.exe&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;&lt;i&gt;Command Line Arguments&lt;/i&gt;&lt;/b&gt; &lt;i&gt; text box&lt;/i&gt;: &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;L100MathTests.dll&lt;/span&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;b&gt;&lt;i&gt;Working Directory&lt;/i&gt;&lt;/b&gt; &lt;i&gt; text box&lt;/i&gt;: &lt;/span&gt;&lt;span style="font-family:Courier New;font-size:100%;color:#339966;"&gt;C:L100MathLibL100MathL100MathTestsbinDebug&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/ul&gt; &lt;ol start="4" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;Debug | Start Debugging&lt;/b&gt;    from the main menu or use the &lt;b&gt;F5&lt;/b&gt; shortcut.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Switch to the NUnit GUI application    and &lt;b&gt;double-click&lt;/b&gt; on the &lt;b&gt;&lt;i&gt;TestAdd&lt;/i&gt;&lt;/b&gt; method. The breakpoint    that you previously set should be hit and a yellow cursor and line will    be shown.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;ol start="6" type="1"&gt;&lt;li&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Select &lt;b&gt;Debug | Step Into&lt;/b&gt;    from the debugger main menu to enter the &lt;i&gt;MathHelper.Add&lt;/i&gt; method.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Now that you know how to attach to the  NUnit process, the full power of the Microsoft Visual Studio Debugger  is at your fingertips.&lt;/span&gt;&lt;/p&gt; &lt;h3&gt;&lt;span style="font-family:Arial;font-size:130%;"&gt;&lt;b&gt;Resources &amp;amp; References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Here are some addition resources that  you may find helpful:&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;NUnit project - &lt;/span&gt;&lt;a href="http://nunit.org/index.php?p=documentation"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://nunit.org/index.php?p=documentation&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Wikipedia TDD - &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://en.wikipedia.org/wiki/Test-driven_development&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Wikipedia unit testing - &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Unit_test"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://en.wikipedia.org/wiki/Unit_test&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;MSDN unit testing article - &lt;/span&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/utfwvs05tmsys.asp"&gt;&lt;span style="font-family:Arial;font-size:100%;color:#0000ff;"&gt;&lt;u&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/utfwvs05tmsys.asp&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7572722583910523291?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7572722583910523291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7572722583910523291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7572722583910523291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7572722583910523291'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/getting-started-with-nunit-richard.html' title='Getting Started with NUnit'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-6206622703241389219</id><published>2008-01-23T02:09:00.001-08:00</published><updated>2008-01-27T22:40:11.965-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Tools'/><title type='text'>How to debug dll by using NUnit</title><content type='html'>&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;strong&gt;Keywords: NUnit, Unit Test, Visual Studio&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;这里是一个精简版使用NUnit来测试一个Class Library的步骤. 这个方法比通过NUnit GUI的菜单File/Open Project方便, 因为后者在调试程序时候, 不得不在Visual Studio的Tools/Attach to Process中为Debuger绑定一个Host程序(Attach NUnit.exe). 然后才能设置断点.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;或者是为VS安装UnitRun -(Resharper tool) 或TestDriven.NET 插件, 也可以很方便地在VS中直接使用NUnit进行测试.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;a href="http://focuswindows.blogspot.com/2008/01/getting-started-with-nunit-richard.html"&gt;另有一个blog&lt;/a&gt;更详细地说明了怎样使用NUnit.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;下面的方法, 不需要任何VS插件, 却可以很方便地调试dll:(适用于&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;span style="TEXT-DECORATION: underline"&gt;Visual Studio Standard or higher, 不适用于Express版)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;div style="MARGIN-LEFT: 2em"&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;1.Place a &lt;strong&gt;breakpoint&lt;/strong&gt; at the first line of the &lt;em&gt;TestAdd&lt;/em&gt; method.&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;strong&gt;2.Right-click&lt;/strong&gt; on the &lt;em&gt;L100MathTests&lt;/em&gt; project in &lt;strong&gt;Solution Explorer&lt;/strong&gt; and select &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;Select the &lt;strong&gt;Debug&lt;/strong&gt; tab and fill in the following options:&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="MARGIN-LEFT: 2em"&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;strong&gt;&lt;em&gt;Start External Program&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;text box&lt;/em&gt; &lt;strong&gt;&lt;em&gt;:&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #339966; FONT-FAMILY: Courier New"&gt;C:\Program Files\NUnit-Net-2.0 2.2.8\bin\nunit-gui.exe 或者 nunit.exe&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="MARGIN-LEFT: 2em"&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;strong&gt;&lt;em&gt;Command Line Arguments&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;text box&lt;/em&gt;:&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #339966; FONT-FAMILY: Courier New"&gt;L100MathTests.dll&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="MARGIN-LEFT: 2em"&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;&lt;strong&gt;&lt;em&gt;Working Directory&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;text box&lt;/em&gt;:&lt;/span&gt; &lt;span style="FONT-SIZE: 0.9em; COLOR: #339966; FONT-FAMILY: Courier New"&gt;C:\L100MathLib\L100Math\L100MathTests\bin\Debug\&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="MARGIN-LEFT: 2em"&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;3. Select &lt;strong&gt;Debug | Start Debugging&lt;/strong&gt; from the main menu or use the &lt;strong&gt;F5&lt;/strong&gt; shortcut.&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;4. Switch to the NUnit GUI application and &lt;strong&gt;double-click&lt;/strong&gt; on the &lt;strong&gt;&lt;em&gt;TestAdd&lt;/em&gt;&lt;/strong&gt; method. The breakpoint that you previously set should be hit and a yellow cursor and line will be shown.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="MARGIN-LEFT: 2em"&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;5.Se&lt;/span&gt;&lt;span style="FONT-SIZE: 0.9em; FONT-FAMILY: Arial"&gt;lect &lt;strong&gt;Debug | Step Into&lt;/strong&gt; from the debugger main menu to enter the &lt;em&gt;MathHelper.Add&lt;/em&gt; method.&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-6206622703241389219?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/6206622703241389219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=6206622703241389219' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6206622703241389219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/6206622703241389219'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/how-to-debug-dll-by-using-nunit.html' title='How to debug dll by using NUnit'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-7384829999089889822</id><published>2008-01-22T20:00:00.001-08:00</published><updated>2008-01-22T20:00:17.389-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Cmd_shell'/><title type='text'>Windows shell script programming</title><content type='html'>&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Keywords: Windows, shell script, bat file&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There are 2 web sites, they are useful for batch program.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.student.oulu.fi/~vtatila/batch_tutorial.html"&gt;http://www.student.oulu.fi/~vtatila/batch_tutorial.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://www.computerhope.com/msdos.htm"&gt;http://www.computerhope.com/msdos.htm&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1315956053498110948-7384829999089889822?l=focuswindows.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://focuswindows.blogspot.com/feeds/7384829999089889822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1315956053498110948&amp;postID=7384829999089889822' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7384829999089889822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1315956053498110948/posts/default/7384829999089889822'/><link rel='alternate' type='text/html' href='http://focuswindows.blogspot.com/2008/01/windows-shell-script-programming.html' title='Windows shell script programming'/><author><name>WadeLiu</name><uri>http://www.blogger.com/profile/17944525849742302736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1315956053498110948.post-3546088748833507849</id><published>2008-01-22T17:52:00.000-08:00</published><updated>2008-01-22T18:41:03.590-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>about class library dll config file</title><content type='html'>&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Keywords: Class library, app configuration file&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;第一: 尽量不要为Class Library建立app.config文件&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;A dll will not have a config file, this is by design, because actually the app config file is per AppDomain while the dll did not have its own appdomain, it is loaded into the Exe's default appdomain by default.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;上面的说明来自网上, 经试验, 确实不应用Visual studio 的向导为Class Library project中增加一个app config文件, 因为在dll的代码中直接使用ConfigurationManager对象是无法获取到ClassLibrary1.dll.config中的信息(假设类库为ClassLibrary1), 它所获取的是该dll的所属exe的app.config的信息.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;测试实例:&lt;br/&gt;下面是ClassLibrary1.dll.config的内容:&lt;br/&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;appSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;="key1"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="value1"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;="key2"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="value2"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;appSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;sectionGroup&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="userSettings"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="TestConfig.Properties.Settings"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"&lt;/span&gt; &lt;span class="attr"&gt;allowExeDefinition&lt;/span&gt;&lt;span class="kwrd"&gt;="MachineToLocalUser"&lt;/span&gt; &lt;span class="attr"&gt;requirePermission&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;sectionGroup&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;userSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TestConfig.Properties.Settings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;setting&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="Setting1"&lt;/span&gt; &lt;span class="attr"&gt;serializeAs&lt;/span&gt;&lt;span class="kwrd"&gt;="String"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;abc&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;setting&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;  &lt;br /&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;TestConfig.Properties.Settings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;userSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;在ClassLibrary1中读取配置文件的代码:&lt;br/&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; DirectUseConfigManager_In_Dll()&lt;br /&gt;        {&lt;br /&gt;            StringBuilder sb=&lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder() ;&lt;br /&gt;            sb.Append(&lt;span class="str"&gt;"key1="&lt;/span&gt; + ConfigurationManager.AppSettings.GetValues(&lt;span class="str"&gt;"key1"&lt;/span&gt;));&lt;br /&gt;            sb.Append(Environment.NewLine);&lt;br /&gt;            sb.Append(&lt;span class="str"&gt;"key2="&lt;/span&gt; + ConfigurationManager.AppSettings.GetValues(&lt;span class="str"&gt;"key2"&lt;/span&gt;));&lt;br /&gt;            sb.Append(Environment.NewLine);&lt;br /&gt;            sb.Append(&lt;span class="str"&gt;"setting1="&lt;/span&gt; + Settings.Default.Setting1);&lt;br /&gt;            sb.Append(Environment.NewLine); &lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; sb.ToString();&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;有一点需要说明的是: 如果你利用Visual Studio的Settings编辑器来编辑类库的App.config, 比如你增加了一个setting, 名为Setting1, 取值为"abc". 你也许会发现, 你的Exe项目在通过调用类库的DirectUseConfigManager_In_Dll(),可以读取到类库的app.config中的Setting1, 其实这只是一个假象. 打开类库的Settings.Designer.cs文件, 你会发现Setting1的有下面的代码.(注意第3行)&lt;br/&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre xml:space="preserve" class="csharpcode"&gt;&lt;br /&gt;        [global::System.Configuration.UserScopedSettingAttribute()]&lt;br /&gt;        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]&lt;br /&gt;        [global::System.Configuration.DefaultSettingValueAttribute(&lt;span class="str"&gt;"abc"&lt;/span&gt;)]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Setting1 {&lt;br /&gt;            get {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; ((&lt;span class="kwrd"&gt;string&lt;/span&gt;)(&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"Setting1"&lt;/span&gt;]));&lt;br /&gt;            }&lt;br /&gt;            set {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"Setting1"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;从上面的代码可以看到, 其实Exe项目还是不能读取ClassLibrary1.dll.conf
