<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_黃偉榮的學習筆記</title><subtitle type="text">軟體的世界變化萬千，小小的我只能在這洪流奮發向上以求立足。</subtitle><id>http://feed.cnblogs.com/blog/u/28823/rss</id><updated>2011-01-30T04:04:45Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/28823/rss"/><entry><id>http://www.cnblogs.com/hwade/archive/2011/01/30/1947715.html</id><title type="text">Web Project的檔案共用小技巧</title><summary type="text">有時Web Project會有一些檔案在不同專案間共同使用，如Javascript檔、圖檔、第三方套件等等，如果每一個專案都放置一份，很容易照成維護上的麻煩(如修改A專案的檔案，忘了複製到B專案)，這時可以調整一下檔案的結構與修改一下專案的設定來解決這問題(這是小弟最近建方案的心得，不一定是最好的)。 資料夾結構 可以在方案下建立一個方案內專案共用的資料夾，專門放置通用的檔案。 通用檔案的版本管...</summary><published>2011-01-29T18:39:00Z</published><updated>2011-01-29T18:39:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2011/01/30/1947715.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2011/01/30/1947715.html"/><content type="html">&lt;p&gt;有時Web Project會有一些檔案在不同專案間共同使用，如Javascript檔、圖檔、第三方套件等等，如果每一個專案都放置一份，很容易照成維護上的麻煩(如修改A專案的檔案，忘了複製到B專案)，這時可以調整一下檔案的結構與修改一下專案的設定來解決這問題(這是小弟最近建方案的心得，不一定是最好的)。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;資料夾結構&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;可以在方案下建立一個方案內專案共用的資料夾，專門放置通用的檔案。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300238567457.png" width="189" height="171"&gt;&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;通用檔案的版本管理&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;通用檔案可以放在方案下，簽出簽入以方案內為主，但缺點是檔案的用共只能分享在方案中的專案間，其實可以將共用檔案存放在一個版本管理的特定路徑下，在用工具做同步，如:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;SVN的 &lt;strong&gt;svn:externals&lt;/strong&gt;  &lt;li&gt;TFS的 工具區設定多資料夾 &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;等方式將方案所需的檔案放在方案資料夾中。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;假設在TFS或SVN中以下列方式建立，shared(通用資料夾)是平行於方案的。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300238584591.png" width="315" height="347"&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在SVN中在Checkout的方案資料夾上增加&lt;strong&gt;svn:externals&lt;/strong&gt;屬性，讓工具簽出方案時一並簽出Shared資料夾，並修改後可簽入。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300239008967.png" width="675" height="314"&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在TFS中工作區增加Shared的Map，讓工具簽出方案時一並簽出Shared資料夾，並修改後可簽入。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/2011013002390270.png" width="630" height="544"&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;以Add As Link方式新增檔案&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在各專案中以Add As Link的方式將檔案加入通用檔案(以Add As Link加入專案的檔案的圖示會多一個連結符號)，當修改時是修改同一份檔案，並可以簽入讓所有方案都使用最新的檔案。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300239053366.png" width="819" height="469"&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;如範例的二個專案中的JS是共用小弟寫多年的檔案，因為都是修改同一份，不會因為複製到不同專案中，因為修改而造成版本的混亂。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/20110130023907216.png" width="406" height="599"&gt;&lt;/strong&gt;&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/en-us/d491911d-97f3-4cf6-87b0-6a2882120acf?SRC=VSIDE" target="_blank"&gt;VSCommands 2010&lt;/a&gt;有提供，Copy Link與Paste Link的功能，可以減少一點點的操作。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;修改專案檔&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Web Project的MS Build預設設定是不複製Link Content到專案中，這樣就以Link加入專案就會出現問題，因為當按下F5執行時，是無法正常執行的，因為找不到檔案，所以要修改MS Build的設定，當發生編譯時，複製檔案到連結檔案的所在。&lt;/p&gt; &lt;p&gt;在*.csproj檔中增加下_CopyWebApplication Target&lt;/p&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br/&gt;&amp;lt;Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;&lt;br/&gt;    &amp;lt;!--增加_CopyWebApplication的Target，因為一個Target只能存在一個地方，所以除了增加自己的設定外，也要包含原始設定--&amp;gt;&lt;br/&gt;    &amp;lt;Target Name="_CopyWebApplication" DependsOnTargets="$(_CopyWebApplicationDependsOn)"&amp;gt;&lt;br/&gt;        &amp;lt;Copy SourceFiles="@(Content)" Condition=" '$(IsDesktopBuild)' != 'false'  And '%(Content.Link)' != ''  " &lt;br/&gt;              DestinationFiles="$(ProjectDir)%(Content.Link)" SkipUnchangedFiles="true" Retries="$(CopyRetryCount)" RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)" /&amp;gt;&lt;br/&gt;        &amp;lt;CallTarget Condition=" '!$(Disable_CopyWebApplication)' And '$(OutDir)' != '$(OutputPath)' And '$(OnAfter_CopyWebApplication)' != ''" &lt;br/&gt;                    Targets="$(OnAfter_CopyWebApplication)" RunEachTargetSeparately="true" /&amp;gt;&lt;br/&gt;    &amp;lt;/Target&amp;gt;&lt;br/&gt;&amp;lt;/Project&amp;gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;此方法僅適用Web Project，不適用Web Site。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;實行結果&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;這方式在小弟的專案實行一陣子了，用起來沒什麼問題，我們的開發環境是&lt;/p&gt;&lt;p&gt;Visual Studio 2010&lt;/p&gt;&lt;p&gt;Visual Studio TFS 2010&lt;/p&gt;&lt;p&gt;本機的Build、TFS的Build、Publish都還沒發現問題，有興趣的朋友可以試試看。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;參考資料&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://svnbook.red-bean.com/en/1.0/ch07s03.html" target="_blank"&gt;&lt;font size="3"&gt;svn:externals說明&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;a href="http://msdn.microsoft.com/zh-tw/library/9f4t9t92(v=VS.100).aspx" target="_blank"&gt;&lt;font size="3"&gt;HOW TO：加入現有項目至專案&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://msdn.microsoft.com/zh-tw/library/ms171462.aspx" target="_blank"&gt;&lt;font size="3"&gt;MSBuild Target&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1947715.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2011/01/30/1947715.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2011/01/30/CommonServiceLocator.html</id><title type="text">IoC的中繼器:CommonServiceLocator</title><summary type="text">IoC(控制反轉)是時下很流行的設計模式，它可以大大的簡少程式之間的相依性，有點像工廠模式，在Class中操作的都是Interface，而Interface與Class的對應與建立實例都是由IoC Framework處理，光是在.Net Framework下的IoC Framework就有近10套，每套都有各自的優缺點，呼叫方式也略有不同，切換IoC Framework是非常麻煩的，或是開發組件(Assembly)，組件也是使用IoC，但是又不能限制使用端用特定款IoC Framework，這時候可以考慮使用IoC的中繼器:CommonServiceLocator來解決這個問題。</summary><published>2011-01-29T18:38:00Z</published><updated>2011-01-29T18:38:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2011/01/30/CommonServiceLocator.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2011/01/30/CommonServiceLocator.html"/><content type="html">&lt;p&gt;IoC(控制反轉)是時下很流行的設計模式，它可以大大的簡少程式之間的相依性，有點像工廠模式，在Class中操作的都是Interface，而Interface與Class的對應與建立實例都是由IoC Framework處理，光是在.Net Framework下的IoC Framework就有近10套，每套都有各自的優缺點，呼叫方式也略有不同，切換IoC Framework是非常麻煩的，或是開發&lt;strong&gt;組件(Assembly)&lt;/strong&gt;，組件也是使用IoC，但是又不能限制使用端用特定款IoC Framework，這時候可以考慮使用IoC的中繼器:CommonServiceLocator來解決這個問題。&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;IoC的文章很多人寫，而且也寫的非常完整與詳細，小弟就不在這裡多述，各位可以參考以下文章:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a href="http://www.dotblogs.com.tw/hatelove/archive/2009/10/02/10894.aspx"&gt;In 91 : [Software Architecture]IoC and DI&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://blog.csdn.net/code6421/archive/2006/09/25/1282139.aspx" target="_blank"&gt;黃忠成 :&amp;nbsp; Inside ObjectBuilder Part1&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;什麼是CommonServiceLocator&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300237129178.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="service locator 2" border="0" alt="service locator 2" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300237131818.jpg" width="129" height="129"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;官方網址:&lt;a href="http://commonservicelocator.codeplex.com/"&gt;http://commonservicelocator.codeplex.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;CommonServiceLocator是放在&lt;a href="http://www.codeplex.com/" target="_blank"&gt;Codeplex&lt;/a&gt;中由Microsoft patterns &amp;amp; practices團隊所設計的小組件，它很輕所有的Code才一百多行，它主要的定義一些Interface，讓我們的程式是呼叫CommonServiceLocator，透過CommonServiceLocator去呼叫IoC Framework，如同中繼器一般，使我們的程式不會綁死於一同IoC Framework，而且有提供主流的IoC Framework用的Provider(就算未提供也可以自己寫)，支援非常的廣泛。&lt;/p&gt; &lt;p&gt;支援的IoC Framework如下:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Castle Windsor  &lt;li&gt;Spring .NET  &lt;li&gt;Unity  &lt;li&gt;StructureMap  &lt;li&gt;Autofac  &lt;li&gt;MEF  &lt;li&gt;LinFu &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;使用方式:&lt;/strong&gt;&lt;/p&gt;//泛型&lt;br/&gt;//第一個Method,也是最常用的Method&lt;br/&gt;ICreditCardService instance = ServiceLocator.Current.GetInstance&amp;lt;ICreditCardService&amp;gt;();&lt;br/&gt;&lt;br/&gt;//第二個多載Method，因為一個Interface，所能有很多個Class實作，如果有設定Key，可以用Key指定要實例的Type&lt;br/&gt;ICreditCardService instance = ServiceLocator.Current.GetInstance&amp;lt;ICreditCardService&amp;gt;("中國信託");&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;//非泛型的&lt;br/&gt;ICreditCardService instance = (ICreditCardService)ServiceLocator.Current.GetInstance(typeof(ICreditCardService));&lt;br/&gt;&lt;br/&gt;ICreditCardService instance = (ICreditCardService)ServiceLocator.Current.GetInstance(typeof(ICreditCardService), "中國信託");&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;//從System.IServiceProvider繼承來的，不過看了幾個Provider，GetService都只是呼叫GetInstance，所以沒什麼不同&lt;br/&gt;ICreditCardService instance = (ICreditCardService)ServiceLocator.Current.GetService(typeof(ICreditCardService));&lt;p&gt;&lt;strong&gt;註冊Provider&lt;/strong&gt;&lt;/p&gt;//先註冊IoC的東西&lt;br/&gt;ContainerBuilder builder = new ContainerBuilder();&lt;br/&gt;builder.RegisterType&amp;lt;OrderService&amp;gt;().As&amp;lt;IOrderService&amp;gt;();&lt;br/&gt;builder.RegisterType&amp;lt;中國信託CreditCardService&amp;gt;().Named&amp;lt;ICreditCardService&amp;gt;("中國信託");&lt;br/&gt;builder.RegisterType&amp;lt;台北富邦CreditCardService&amp;gt;().Named&amp;lt;ICreditCardService&amp;gt;("台北富邦");&lt;br/&gt;&lt;br/&gt;//最後在設定Provider&lt;br/&gt;ServiceLocator.SetLocatorProvider(() =&amp;gt; new MyServiceLocator(builder)); &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;這裡介紹幾個常見的IoC設定方式，詳情請看&lt;a href=":http://commonservicelocator.codeplex.com/" target="_blank"&gt;官方網站&lt;/a&gt;的說明。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;Autofac&lt;/font&gt;的設定&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;到&lt;a href="http://code.google.com/p/autofac/downloads/list" target="_blank"&gt;Autofac網站&lt;/a&gt;下載&lt;a href="http://code.google.com/p/autofac/downloads/detail?name=AutofacContrib-2.3.2.632-NET40.zip&amp;amp;can=2&amp;amp;q="&gt;AutofacContrib&lt;/a&gt;，加入參考AutofacContrib.CommonServiceLocator.dll&lt;/p&gt;ContainerBuilder builder = new ContainerBuilder();&lt;br/&gt;var container = builder.Build();&lt;br/&gt;ServiceLocator.SetLocatorProvider(() =&amp;gt; new AutofacServiceLocator(container));&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;Spring .NET&lt;/font&gt;的設定&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下載:&lt;a href="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=CommonServiceLocator&amp;amp;DownloadId=45064"&gt;CommonServiceLocator.SpringAdapter.zip&lt;/a&gt;，加入參考CommonServiceLocator.SpringAdapter.dll&lt;/p&gt;DefaultListableObjectFactory objectFactory = new DefaultListableObjectFactory(false);&lt;br/&gt;objectFactory.RegisterSingleton(typeof(SimpleLogger).FullName, new SimpleLogger());&lt;br/&gt;objectFactory.RegisterSingleton(typeof(AdvancedLogger).FullName, new AdvancedLogger());&lt;br/&gt;&lt;br/&gt;ServiceLocator.SetLocatorProvider(() =&amp;gt; new SpringServiceLocatorAdapter(objectFactory));&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;Unity&lt;/font&gt;的設定&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下載:&lt;a href="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=CommonServiceLocator&amp;amp;DownloadId=45067"&gt;CommonServiceLocator.UnityAdapter.zip&lt;/a&gt;，加入參考Microsoft.Practices.Unity.ServiceLocatorAdapter.dll&lt;/p&gt;IUnityContainer container = new UnityContainer() &lt;br/&gt;    .RegisterType&amp;lt;ILogger, AdvancedLogger&amp;gt;() &lt;br/&gt;    .RegisterType&amp;lt;ILogger, SimpleLogger&amp;gt;(typeof (SimpleLogger).FullName) &lt;br/&gt;    .RegisterType&amp;lt;ILogger, AdvancedLogger&amp;gt;(typeof (AdvancedLogger).FullName);&lt;br/&gt;&lt;br/&gt;ServiceLocator.SetLocatorProvider(() =&amp;gt; new UnityServiceLocator(container)); &lt;br/&gt;return new UnityServiceLocator(container);&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;StructureMap&lt;/font&gt;的設定&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font style="font-weight: bold"&gt;下載:&lt;a href="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=CommonServiceLocator&amp;amp;DownloadId=45599"&gt;CommonServiceLocator.StructureMapAdapter.zip&lt;/a&gt;，加入參考StructureMapAdapter.dll&lt;/font&gt;&lt;/p&gt;Registry registry = new Registry();&lt;br/&gt;registry.ForRequestedType&amp;lt;ILogger&amp;gt;().TheDefaultIsConcreteType&amp;lt;AdvancedLogger&amp;gt;();&lt;br/&gt;registry.AddInstanceOf&amp;lt;ILogger&amp;gt;(new SimpleLogger()).WithName(typeof(SimpleLogger).FullName);&lt;br/&gt;registry.AddInstanceOf&amp;lt;ILogger&amp;gt;(new AdvancedLogger()).WithName(typeof(AdvancedLogger).FullName);&lt;br/&gt;IContainer container = new Container(registry);&lt;br/&gt;&lt;br/&gt;ServiceLocator.SetLocatorProvider(() =&amp;gt; new StructureMapServiceLocator(container));&lt;img src="http://www.cnblogs.com/hwade/aggbug/1947714.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2011/01/30/CommonServiceLocator.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2011/01/30/UTF8Encoding-And-BOM.html</id><title type="text">UTF8Encoding與BOM</title><summary type="text">前陣子團隊中有用XmlSerializer將物件轉成XML存檔後，上傳給另一家公司，對方卻一直回報我們XML有問題，用文字編輯器看格式都很正確，但用XML的編輯器卻會出錯，發現原來是BOM害的。</summary><published>2011-01-29T18:35:00Z</published><updated>2011-01-29T18:35:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2011/01/30/UTF8Encoding-And-BOM.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2011/01/30/UTF8Encoding-And-BOM.html"/><content type="html">&lt;p&gt;前陣子團隊中有用XmlSerializer將物件轉成XML存檔後，上傳給另一家公司，對方卻一直回報我們XML有問題，用文字編輯器看格式都很正確，但用XML的編輯器卻會出錯，發現原來是BOM害的。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;用Visual Studio開啟，會出現未預期的XML宣告。XML宣告必須是文件中的第一個節點，前面不得有空白字元的錯誤訊息(如圖一)，可是怎麼看都沒有多餘的空白，後來用2進元編輯器開啟，發現檔案前多了一組BOM(Byte order mark)。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300235091675.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-01-30_001222" border="0" alt="2011-01-30_001222" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/20110130023510412.png" width="575" height="59"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;圖一 用Visual Studio開啟檔案所發生的錯誤。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300235129464.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300235139280.png" width="423" height="57"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;圖二 多出的BOM。&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:什麼是BOM&lt;/p&gt; &lt;p&gt;&lt;strong&gt;位元組順序記號(byte-order mark，BOM)&lt;/strong&gt;，是Unicode存放在檔案的最前面，用來記錄讀位元組的順序，如UTF-8是EF BB BF，詳情請看:&lt;/p&gt; &lt;p&gt;&lt;a href="http://zh.wikipedia.org/zh-tw/%E4%BD%8D%E5%85%83%E7%B5%84%E9%A0%86%E5%BA%8F%E8%A8%98%E8%99%9F" target="_blank"&gt;維基百科 - 位元組順記號&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://zh.wikipedia.org/zh-tw/%E5%AD%97%E8%8A%82%E5%BA%8F"&gt;維基百科 - 位元組序&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;這是其中的程式碼片段&lt;/p&gt;var ser = new XmlSerializer(sample.GetType());&lt;br/&gt;using (var memoryStream = new MemoryStream())&lt;br/&gt;{&lt;br/&gt;    //XmlSerializer不給Encoding，其XML宣告會是UTF-16&lt;br/&gt;    var xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);&lt;br/&gt;&lt;br/&gt;    //空命名空間&lt;br/&gt;    XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();&lt;br/&gt;    xsn.Add(String.Empty, String.Empty);&lt;br/&gt;&lt;br/&gt;    ser.Serialize(xmlWriter, sample, xsn);&lt;br/&gt;    var result = Encoding.UTF8.GetString(memoryStream.ToArray());&lt;br/&gt;&lt;br/&gt;    //do something&lt;br/&gt;&lt;br/&gt;    //把檔案存起來&lt;br/&gt;    File.WriteAllText(filePath, result, Encoding.UTF8);&lt;br/&gt;}&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;會照成輸入二次BOM的原因在於第&lt;strong&gt;5&lt;/strong&gt;行與第&lt;strong&gt;17&lt;/strong&gt;行，同時給了UTF8Encoding，但這不是最主要的原因，出錯的主因是二個地方都使用了&lt;font color="#ff0000"&gt;有BOM的UTF8Encoding&lt;/font&gt;&lt;font color="#333333"&gt;，查了MSDN，UTF8Encoding在建構式時，&lt;strong&gt;可以指定要不要輸出BOM&lt;/strong&gt;，而System.Text.Encoding.UTF8是使用要輸出BOM的UTF8Encoding。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300235148889.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/201101/201101300235169054.png" width="404" height="218"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;圖三 MSDN的UTF8Encoding的說明。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;System.Text.Encoding.UTF8的原始碼&lt;/p&gt;public static Encoding UTF8&lt;br/&gt;{    &lt;br/&gt;    get&lt;br/&gt;    {&lt;br/&gt;        if (utf8Encoding == null)&lt;br/&gt;        {&lt;br/&gt;            utf8Encoding = new UTF8Encoding(true);&lt;br/&gt;        }&lt;br/&gt;        return utf8Encoding;&lt;br/&gt;    }&lt;br/&gt;}&lt;p&gt;而System.Text.Encoding下的幾個靜態屬性UTF7、UTF8、Unicode、UTF32都是使用BOM為true的建構式，所以想不要BOM的話，請改用 &lt;strong&gt;&lt;font size="4"&gt;new UTF8Encoding(false)&lt;/font&gt;&lt;/strong&gt;。&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;NOTE:&lt;/p&gt;&lt;p&gt;我同時也看了File.WriteAllText的原始碼，其實是我們雞婆，因為File.WriteAllText的多載，其中File.WriteAllText(string path, string contents)，所用的預設Encoding就是new UTF8Encoding(false)，所以我們不指定Encoding反而沒事。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;參考資料&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/zh-tw/library/31d6tdy7.aspx" target="_blank"&gt;UTF8Encoding 類別&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1947713.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2011/01/30/UTF8Encoding-And-BOM.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2011/01/30/1947711.html</id><title type="text">Temporary Post Used For Theme Detection (d4b0aefa-c88e-4957-bba7-b367d1bfa042 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)</title><summary type="text">This is a temporary post that was not deleted. Please delete this manually. (3cc2719a-c1ed-43a1-9fce-d2eb7cfd0299 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)</summary><published>2011-01-29T18:28:00Z</published><updated>2011-01-29T18:28:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2011/01/30/1947711.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2011/01/30/1947711.html"/><content type="html">&lt;p&gt;This is a temporary post that was not deleted. Please delete this manually. (3cc2719a-c1ed-43a1-9fce-d2eb7cfd0299 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1947711.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2011/01/30/1947711.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2010/11/26/codedui_searchcontrol.html</id><title type="text">寫CodedUI時如何尋找控制項的小技巧</title><summary type="text">在用CodedUI寫自動化測試時，我不喜歡用工具產生的代碼(相關資訊可參考手工製Coded UI Test(Visual Studio 2010新的UI自動化測試))，寫久了有一些經驗，例如找到控制項的一些的小技巧。 工具 尋找控制項我也是用Visual Studio 2010內建的CodedUITestBuilder.exe，不過一般的情況下CodedUITestBuilder.exe必需搭配...</summary><published>2010-11-25T16:42:00Z</published><updated>2010-11-25T16:42:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2010/11/26/codedui_searchcontrol.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2010/11/26/codedui_searchcontrol.html"/><content type="html">&lt;p&gt;在用CodedUI寫自動化測試時，我不喜歡用工具產生的代碼(相關資訊可參考&lt;a href="http://www.dotblogs.com.tw/wadehuang36/archive/2010/05/19/15328.aspx"&gt;手工製Coded UI Test(Visual Studio 2010新的UI自動化測試)&lt;/a&gt;)，寫久了有一些經驗，例如找到控制項的一些的小技巧。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;工具&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;尋找控制項我也是用Visual Studio 2010內建的CodedUITestBuilder.exe，不過一般的情況下CodedUITestBuilder.exe必需搭配測試專案的UIMap.uitest使用，有點麻煩，不過還好它有提供獨立執行的方法。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="CodedUITestBuilder.exe的執行畫面" border="0" alt="CodedUITestBuilder.exe的執行畫面" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_c4165aad-b0d1-425c-b1f8-64da6f1b6eef.png" width="226" height="63"&gt;&lt;/p&gt; &lt;p&gt;圖1 CodedUITestBuilder.exe的執行畫面&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;在CMD中下&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\CodedUITestBuilder.exe" &lt;strong&gt;/standAlone&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;多一個參數&lt;strong&gt;/standAlone&lt;/strong&gt;就可以單獨執行，也加入Visual Studio的External Tools中，方便日常的呼叫。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="External Tools視窗" border="0" alt="External Tools視窗" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_7cb9d1b9-4129-4566-964e-e9bae6fead90.png" width="461" height="478"&gt;&lt;/p&gt; &lt;p&gt;圖二 External Tools視窗&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;尋找控制項&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;使用CodedUITestBuilder的UIMap功能，使用的方式有二種。&lt;/p&gt; &lt;ol&gt; &lt;li&gt;按下 &lt;strong&gt;Windows key + U&lt;/strong&gt;，會自動選取到游標所在的控制項，適用在不方便滑鼠拖曳的情況下  &lt;li&gt;滑鼠拖曳下圖紅色框中的Icon，到控制項上方 &lt;/li&gt;&lt;/ol&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="拖曳用的Icon" border="0" alt="拖曳用的Icon" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_f1712c5b-4119-467c-9de0-c6bf2364c7b7.png" width="226" height="63"&gt;&lt;/p&gt; &lt;p&gt;圖三 拖曳用的Icon&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="選到控制項的晝面" border="0" alt="選到控制項的晝面" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_a5bc805a-8950-41de-9221-84b1717514f4.png" width="618" height="109"&gt;&lt;/p&gt; &lt;p&gt;圖四 選到控制項的晝面&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;選擇到控制項後，會出現控制項的說明視窗，裡面有控制項的各個屬性值與階層，可以用來做為寫CodedUI的搜尋條件。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="控制項的說明視窗" border="0" alt="控制項的說明視窗" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_8e587028-119c-4afc-af74-6d6031a06683.png" width="658" height="332"&gt;&lt;/p&gt; &lt;p&gt;圖五 控制項的說明視窗&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;像Name=q，Code就可以這樣寫&lt;/p&gt;//假設已經開啟了IE且網址在www.google.com上&lt;br/&gt;BrowserWindow window = BrowserWindow.Locate("Google");            &lt;br/&gt;&lt;br/&gt;HtmlEdit input = new HtmlEdit(window);&lt;br/&gt;input.SearchProperties[HtmlEdit.PropertyNames.Name] = "q";&lt;br/&gt;input.Text = "黃偉榮";&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="控制項視窗的屬性值，都可以做為搜尋條件" border="0" alt="控制項視窗的屬性值，都可以做為搜尋條件" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_3cd7277e-bc9f-4ffc-a13e-d2af9cea870b.png" width="632" height="323"&gt;&lt;/p&gt;&lt;p&gt;圖六 控制項視窗的屬性值，都可以做為搜尋條件&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;階層問題&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;之前有遇到問題，條件都下對，就是找不到控制項，後來發現可能是階層問題，可以試著一層一層的去找到控制項。&lt;/p&gt;&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="控制項都可以將父視窗傳進去，然後可以只搜尋子控制項" border="0" alt="控制項都可以將父視窗傳進去，然後可以只搜尋子控制項" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/CodedUI_14090/image_36f0e38f-cea6-4d7c-806a-507393af3e0b.png" width="897" height="84"&gt;&lt;/p&gt;&lt;p&gt;圖七 控制項都可以將父視窗傳進去，然後可以只搜尋子控制項&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;NOTE:&lt;/p&gt;&lt;p&gt;如果嘗試幾次都失敗，可以叫出產生器，去看產生的CodedUI是如何去找到控制項。&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1888308.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2010/11/26/codedui_searchcontrol.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2010/11/26/FeaturePacks2.html</id><title type="text">Visual Studio 2010 Feature Packs 2之Silverlight自動化測試</title><summary type="text">在Visual Studio 2010上市沒多久後，很高興它推出了Coded UI的自動化測試，那時我的專案是跑Silverlight，要錄制時出現不支援的錯誤，只好又乖乖的自己當人工測試機，不過前幾天看到微軟推出Visual Studio 2010 Feature Packs 2套件，其中有一項功能是Create coded UI tests for Silverlight 4 applicat...</summary><published>2010-11-25T16:38:00Z</published><updated>2010-11-25T16:38:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2010/11/26/FeaturePacks2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2010/11/26/FeaturePacks2.html"/><content type="html">&lt;p&gt;在Visual Studio 2010上市沒多久後，很高興它推出了Coded UI的自動化測試，那時我的專案是跑Silverlight，要錄制時出現不支援的錯誤，只好又乖乖的自己當人工測試機，不過前幾天看到微軟推出&lt;a href="http://msdn.microsoft.com/vstudio/ff655021.aspx" target="_blank"&gt;Visual Studio 2010 Feature Packs 2&lt;/a&gt;套件，其中有一項功能是Create coded UI tests for Silverlight 4 applications，就興高彩烈安裝玩一翻。&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;在2010/11/23日，截筆前Visual Studio 2010 Feature Packs 2必需要&lt;strong&gt;MSDN Subscribers&lt;/strong&gt;才能下載，什麼沒有&lt;strong&gt;MSDN Subscribers，&lt;/strong&gt;這我也辦法，只能期待微軟把這功能加到Visual Studio 2010 SP1中，或看沒有沒人分享吧。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Visual Studio 2010 Feature Packs 2的新功能(僅介紹測試)&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Coded UI與Test Manager的動作錄制與執行支援Silverlight。  &lt;li&gt;Coded UI與Test Manager的動作錄制與執行支援Firefox 3.5、3.6。  &lt;li&gt;Coded UI編輯器。 &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Silverlight自動化測試&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;要Silverlight可以自動化測試還有點麻煩，有三個條件。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Host只支援IE。  &lt;li&gt;必需要Silverlight 4.0以上。  &lt;li&gt;必需要加入參考Microsoft.VisualStudio.TestTools.UITest.Extension.SilverlightUIAutomationHelper.dll組件。 &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Microsoft.VisualStudio.TestTools.UITest.Extension.SilverlightUIAutomationHelper.dll&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;安裝好Visual Studio 2010 Feature Packs 2後組件的位址預設在:&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;C:\Program Files (x86)\Common Files\microsoft shared\VSTT\10.0\UITestExtensionPackages\SilverlightUIAutomationHelper\Microsoft.VisualStudio.TestTools.UITest.Extension.SilverlightUIAutomationHelper.dll&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;但專案不可以一直都掛載組件，組件的下載的流量與或安全性問題，每次要上線前都要刪除組件，或每次要測試時都加入這個組件，會很煩吧，所以可以從MSBuild下手，打開Project檔如*.csproj，打開後找到&lt;/p&gt;&amp;lt;Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension.SilverlightUIAutomationHelper, Version=10.0.30319.381, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /&amp;gt;&lt;p&gt;加上Condition=" '$(Configuration)' == 'Debug' "，讓組件只有在Debug的模式下才被參考，Release時不會，加入後的結果如下。&lt;/p&gt;&amp;lt;Reference Condition=" '$(Configuration)' == 'Debug' " Include="Microsoft.VisualStudio.TestTools.UITest.Extension.SilverlightUIAutomationHelper, Version=10.0.30319.381, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /&amp;gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;NOTE:&lt;/p&gt;&lt;p&gt;其實有點不懂為什麼MSDN中的文件&lt;a href="http://msdn.microsoft.com/library/gg313838.aspx#AddDll" target="_blank"&gt;How to: Set Up Your Silverlight Application for Testing&lt;/a&gt;，MSBuild要寫的那麼麻煩，要自訂Property，每一次切換還要打開專案檔，切換Property。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;範例&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://kmip0g.blu.livefilestore.com/y1pmj1_0vMAnPzgSh_L9z7yHNYh_7snTnGNRdddI98WNMTq5ZjMAj36xFwDfVKdQc1XCaplAp_BOawX9y5RBQ2WuH0uHSeOT9OV/SilverlighAutoTest.7z?download&amp;amp;psid=1" target="_blank"&gt;下載&lt;/a&gt;&lt;/p&gt;&amp;lt;Grid x:Name="LayoutRoot"&amp;gt;&lt;br/&gt;    &amp;lt;RadioButton Content="紅色" Height="16" Margin="12,14,22,270" Name="RBRed" Background="Red" Click="OnColorButtomClick" /&amp;gt;&lt;br/&gt;    &amp;lt;RadioButton Content="綠色" Height="16" Margin="12,51,22,233" Name="RBGreen" Background="Green"  Click="OnColorButtomClick" /&amp;gt;&lt;br/&gt;    &amp;lt;RadioButton Content="藍色" Height="16" Margin="12,32,22,252" Name="RBBlue" Background="Blue"  Click="OnColorButtomClick" /&amp;gt;&lt;br/&gt;&amp;lt;/Grid&amp;gt;public partial class MainPage : UserControl&lt;br/&gt;{&lt;br/&gt;    public MainPage()&lt;br/&gt;    {&lt;br/&gt;        InitializeComponent();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    private void OnColorButtomClick(object sender, RoutedEventArgs e)&lt;br/&gt;    {&lt;br/&gt;        this.LayoutRoot.Background = (sender as Control).Background;&lt;br/&gt;    }       &lt;br/&gt;}&lt;p&gt;範例很簡單只是三個RadioButton，被Click時切換背景色，錄制RadioButton的切換，選擇Silverlight中綠色的RadioButton，驗證Selected是否為真，工具的可驗證的屬性有點少，不過事實上是工具尚未支援，用Code寫幾乎所有的屬性都可以取得，可參考&lt;a href="http://www.dotblogs.com.tw/wadehuang36/archive/2010/05/19/15328.aspx"&gt;手工製Coded UI Test(Visual Studio 2010新的UI自動化測試)&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.dotblogs.com.tw/wadehuang36/1011/Visual-Studio-2010-F_6D88/image_4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://files.dotblogs.com.tw/wadehuang36/1011/Visual-Studio-2010-F_6D88/image_thumb_1.png" width="665" height="337"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;圖一 選取Silverlight的Control並加入Assertion&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果沒有加入組件會出現圖二的錯誤訊息，所以改用Release模式Build，組件是沒加入的。&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.dotblogs.com.tw/wadehuang36/1011/Visual-Studio-2010-F_6D88/image_8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://files.dotblogs.com.tw/wadehuang36/1011/Visual-Studio-2010-F_6D88/image_thumb_3.png" width="500" height="263"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;圖二 沒有加入組件的錯誤訊息&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;終於有編輯器了，以前錄好了想改不是改XML(誰會改阿)，就是重錄，現在小變動下，可以用編輯器微調。&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.dotblogs.com.tw/wadehuang36/1011/Visual-Studio-2010-F_6D88/image_10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://files.dotblogs.com.tw/wadehuang36/1011/Visual-Studio-2010-F_6D88/image_thumb_4.png" width="1035" height="278"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;圖三 Coded UI Editor&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;參考&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/vstudio/ff655021.aspx" target="_blank"&gt;Visual Studio 2010 Feature Packs 2&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1888306.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2010/11/26/FeaturePacks2.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2010/11/26/Moles.html</id><title type="text">Moles - Isolation framework for .NET(假.Net)介紹</title><summary type="text">Moles是前陣子91大推薦我用的Mock的Framework，它跟Moq與Rhino.Mocks這類的套件不同，Moq與Rhino.Mocks這類的Mock是對Interface或Abstract Class做Mock，而Moles是Mock整個CLR(Common Language Runtime)，破除Moq等Mock套件的限制，非Interface或Abstract Class也可以Moc...</summary><published>2010-11-25T16:37:00Z</published><updated>2010-11-25T16:37:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2010/11/26/Moles.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2010/11/26/Moles.html"/><content type="html">&lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/projects/moles/" target="_blank"&gt;Moles&lt;/a&gt;是前陣子&lt;a href="http://www.dotblogs.com.tw/hatelove/" target="_blank"&gt;91&lt;/a&gt;大推薦我用的Mock的Framework，它跟&lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;Moq&lt;/a&gt;與Rhino.Mocks這類的套件不同，Moq與Rhino.Mocks這類的Mock是對Interface或Abstract Class做Mock，而Moles是Mock整個CLR(Common Language Runtime)，破除Moq等Mock套件的限制，非Interface或Abstract Class也可以Mock，而且還可以對Static Method來Mock，如DateTime.Now或File.Open等等Static Method，使原本在開發時不用為了方便測試而過度設計(如小弟之前為了方便測試，把DateTime又加了一層DateTimeProvider，當我看到這Framework後，就覺得我之前的作法非常的無聊，可參考&lt;a href="http://www.dotblogs.com.tw/wadehuang36/archive/2010/09/10/datetimestub.aspx" target="_blank"&gt;Unit Test小技巧 : DateTime的Stub&lt;/a&gt;)。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;•什麼是Mock&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Mock簡單來說就是作一個假的東西，通常用在單元測試，因為寫單元測試時，難免沒辦法抽的很乾淨，多少會呼叫到別的Method，如寫訂單的處理，其中有呼叫到信用卡API，在寫單元測試不需要也盡可能不要呼叫到信用卡API，所以用Mock把信用卡API變成假的信用卡API，讓訂單的測試可以獨立，Mock的用法與概念當然不只這樣，詳情可以參考:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Will保哥的&lt;a href="http://blog.miniasp.com/category/Unit-Testing.aspx" target="_blank"&gt;ASP.NET MVC 單元測試系列&lt;/a&gt;  &lt;li&gt;In 91的&lt;a href="http://www.dotblogs.com.tw/hatelove/category/2823.aspx" target="_blank"&gt;測試系列&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;Mock與Stub都是用來作假物件，只是二個有實作上的差異，簡單來說，Mock是用動態產生的(如用Moq產生)，Stub是已經寫好的(如為了測試實作一個Interface)，本文統一都叫作Mock，雖然Moles感覺比較像Stub。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;•Moq與Moles比較&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Moq的Mock原理是動態產生Class，所以它才只能對Interface或Abstract Class，這類可繼承的型別，如對Interface就是動態產生一個實作Interface所有成員的Class，在用Setup來指定成員的內容或回傳值，多半會搭配&lt;a href="http://zh.wikipedia.org/zh-tw/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC" target="_blank"&gt;IoC&lt;/a&gt;，讓程式在呼叫其他類別時，改為呼叫Mock的程式。&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;大部分Mock的Framework如Moq與Rhino Mocks的底層都是使用&lt;a href="http://www.castleproject.org/dynamicproxy/index.html"&gt;Castle DynamicProxy&lt;/a&gt;，來動態產生Class。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Moles的Mock原理是，在CLR上在建立一個自己的Runtime，測試時是在MoleRuntime上執行，所以原本是直接呼叫如DateTime.Now，改為呼叫Mock的程式。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_thumb_1.png" width="487" height="289"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;圖一 MoleRuntime的假想圖&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Moq與Moles都有適合的使用時機與限制，可參考圖二。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_3.png" width="551" height="172"&gt;&lt;/p&gt; &lt;p&gt;圖二 使用Mole與一般Mock的差異 來源:&lt;a href="http://research.microsoft.com/en-us/projects/pex/molesmanual.docx" target="_blank"&gt;Microsoft Moles Reference Manual&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;•安裝Moles&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Moles&lt;/p&gt; &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/en-us/b3b41648-1c21-471f-a2b0-f76d8fb932ee" target="_blank"&gt;Visual Studio 2010 Moles - Isolation Framework for .NET(x86)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/en-us/22c07bda-ffc9-479a-9766-bfd6ccacabd4" target="_blank"&gt;Visual Studio 2010 Moles - Isolation Framework for .NET(x64)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Pex And Moles&lt;/p&gt; &lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/downloads/d2279651-851f-4d7a-bf05-16fd7eb26559/default.aspx" target="_blank"&gt;Pex - Automated Whitebox Testing for .NET(x86)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;x64版目前只在&lt;strong&gt;MSDN Suscribers&lt;/strong&gt;中下載&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;Pex是一個Code的分析工具，可以產生相關的單元測試，都是同一個團隊開發，他們把二套Framework綁在一起，個人試用的結果，很有趣，但實用性不高。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;•實作DateTime.Now的Mock&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1.新增測試專案&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;2.在測試專案中的參考上按右鍵，選Add Moles Assembly for mscorlib，產生mscorlib.moles檔&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_90db8352-7884-4b8e-80f1-a904c939536c.png" width="398" height="170"&gt;&lt;/p&gt; &lt;p&gt;圖三 新增mscorlib.moles檔&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;當專案中有.moles檔時，編譯會產生其對應的組件&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_a296f0c9-7df3-4a1a-969a-67cca55a1699.png" width="401" height="261"&gt;&lt;/p&gt; &lt;p&gt;圖四 mscorlib.moles檔與其對應的組件&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;NOTE:&lt;/p&gt; &lt;p&gt;在舊版的Moles中，mscorlib.moles檔的新增是在&lt;strong&gt;新增項目&lt;/strong&gt;時自行輸入組件名稱，新版直接在參考中右鍵新增*.moles，方便很多。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_2409baf1-88f7-494d-8edb-5b39902bb84b.png" width="810" height="383"&gt;&lt;/p&gt; &lt;p&gt;圖五 新增.moles已取消從新增項目中新增的方式，因為找不到圖了借用&lt;a href="http://charlesbc.blogspot.com/" target="_blank"&gt;程湘&lt;/a&gt;大的圖片一用。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;mscorlib&lt;/strong&gt;是.Net Framework是最基本的函式庫，俗稱&lt;strong&gt;Base Class Library(BCL)&lt;/strong&gt;，也就是把專案中的所有參考都刪除，剩下可以用的型別就是在&lt;strong&gt;mscorlib.dll&lt;/strong&gt;中的型別，DateTime也是其一，而所有不同類型專案的&lt;strong&gt;mscorlib.dll&lt;/strong&gt;一定都相同，如&lt;strong&gt;WebApplication&lt;/strong&gt;與&lt;strong&gt;Silverlight&lt;/strong&gt;的&lt;strong&gt;mscorlib.dll&lt;/strong&gt;是一致的(這小弟我沒記錯是這樣，如果說錯了請見諒)。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;如果想要Mock其他組件在其他組件上按右鍵新增該組件的.moles檔。&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_1948b10c-ad6b-4022-801e-df3f94fb4f09.png" width="406" height="233"&gt;&lt;/p&gt; &lt;p&gt;圖六 新增其他Moles組件&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;3.於TestMethod中撰寫DateTime的測試，且Mock DateTime並驗證。&lt;/p&gt;[TestMethod]&lt;br/&gt;[HostType("Moles")]&lt;br/&gt;public void TestMethod1()&lt;br/&gt;{&lt;br/&gt;    System.Moles.MDateTime.NowGet = () =&amp;gt; { return new DateTime(2010, 1, 1); };&lt;br/&gt;&lt;br/&gt;    Assert.AreEqual(new DateTime(2010, 1, 1), DateTime.Now);&lt;br/&gt;}&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在TestMethod上增加[HostType("Moles")]，讓Visual Studio知道這一個TestMethod，是要用MoleRuntime執行，Mock的方式是用Delegate，如圖四Moles會建立&lt;strong&gt;mscorlib&lt;/strong&gt;的Mock用組件，其邏輯如下:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Namespace:最後加上Moles &lt;li&gt;Type:在前加上M &lt;li&gt;Property:後方加上Get或Set &lt;li&gt;Method:後方加上參數的型別 &lt;li&gt;Instance:在AllInstances下操作 &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;所以System.DateTime.Now的Mock在System.Moles.MDateTime.NowGet，範例中DateTime.Now就改為Mock的值，而不是現在時間。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;4.增加MoledType宣告。&lt;/p&gt;[assembly: Microsoft.Moles.Framework.MoledType(typeof(DateTime))]&lt;p&gt;在檔案的最上方或&lt;strong&gt;AssemblyInfo.cs&lt;/strong&gt;中加上MoledType的宣告，每一個要Mock的Type都要增加。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;5.執行測試，並通過測試。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;•已知問題&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我在使用Moles版本&lt;strong&gt;0.94.51023.0&lt;/strong&gt;時，有遇到一個問題，就是MoleRuntime無法正確取得測試專案的app.config，我也有在MSDN中詢問別人，得知的訊息是Bug，可參考&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/pex/thread/aa170904-a31d-4180-873c-ab78f37a5894" target="_blank"&gt;Can't get data via ConfigurationManager.AppSettings on HostType("Moles")&lt;/a&gt;，但山不轉路轉，聰明的方法沒有，笨死人的解決方法到有，MoleRuntime只會抓自己的app.config，所以只要將資料寫在MoleRuntime的app.config中測試時就可以正常讀取資料，只是設定就沒辦法很方便的xCopy，且會所有專案共用一個app.config，最後我只想到切換專案時，手動更換檔案。&lt;/p&gt;&lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/Moles_10C2E/image_53fe2e5e-4de2-475d-9e0c-d179f5193314.png" width="335" height="86"&gt;&lt;/p&gt;&lt;p&gt;圖七 各測試專案需要的app.config&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;Moles的執行檔案路徑在&lt;/p&gt;&lt;p&gt;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\Microsoft.Moles.VsHost.x86.exe&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;•其他範例&lt;/strong&gt;&lt;/p&gt;//測試時只用一組固定的Guid&lt;br/&gt;System.Moles.MGuid.NewGuid = () =&amp;gt;&lt;br/&gt;{&lt;br/&gt;    return new Guid("FFEB1621-5016-4F28-94AE-5DB72FC8A23B");&lt;br/&gt;};           &lt;br/&gt;&lt;br/&gt;//測試時不需要真的讀實體檔案&lt;br/&gt;System.IO.Moles.MFile.ReadAllTextString = (filePath) =&amp;gt;&lt;br/&gt;{&lt;br/&gt;    return "測試內容";&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;System.Net.Mail.Moles.MSmtpClient.AllInstances.SendMailMessage = (smtp, message) =&amp;gt;&lt;br/&gt;{&lt;br/&gt;    //測試時不真的寄Email&lt;br/&gt;};&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;•參考資料&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/projects/moles/" target="_blank"&gt;Moles - Isolation framework for .NET&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://charlesbc.blogspot.com/2010/10/7-moles.html" target="_blank"&gt;程湘之間 - 單元測試(7): 使用 Moles 增加可測試性&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;Moq&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx" target="_blank"&gt;Rhino.Mocks&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1888305.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2010/11/26/Moles.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2010/10/20/1857068.html</id><title type="text">[小技巧]Entity Framework強型別Include</title><summary type="text">在Entity Framework中如果不設定為Lazy Loading Enable=true，勢必要自己處理關聯資料的載入，如:用Load或Include的，但因為Include的參數是用string，個人很討厭沒有IntelliSense，且用String改了TableName後，工具不易找到錯誤，所以小弟我寫一個Extension Method來擴展。NOTE:這個方法暫時不適用Colle...</summary><published>2010-10-20T14:00:00Z</published><updated>2010-10-20T14:00:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857068.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857068.html"/><content type="html">&lt;p&gt;在Entity Framework中如果不設定為Lazy Loading Enable=true，勢必要自己處理關聯資料的載入，如:用Load或Include的，但因為Include的參數是用string，個人很討厭沒有IntelliSense，且用String改了TableName後，工具不易找到錯誤，所以小弟我寫一個Extension Method來擴展。&lt;/p&gt;//原弱型別的寫法&lt;br/&gt;AdventureWorksLT2008R2Entities context = new AdventureWorksLT2008R2Entities();&lt;br/&gt;var customer = context.Customer.Include("SalesOrderHeader").ToList();&lt;br/&gt;&lt;br/&gt;//擴展的強型別寫法&lt;br/&gt;AdventureWorksLT2008R2Entities context = new AdventureWorksLT2008R2Entities();&lt;br/&gt;var customer = context.Customer.Include(x =&amp;gt; x.SalesOrderHeader).ToList();&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;這個方法暫時不適用Collection後又在關聯，如上一個例子SalesOrderHeader是Collection，無法這樣下x.SalesOrderHeader.SalesOrderDetail，為什麼是暫時，因為小弟還沒想出好的寫法，用x.SalesOrderHeader[0].SalesOrderDetail或x.SalesOrderHeader.First().SalesOrderDetail嗎，感覺挺醜的。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;Source Code&lt;/strong&gt;&lt;/p&gt;public static IQueryable&amp;lt;T&amp;gt; Include&amp;lt;T&amp;gt;(this ObjectSet&amp;lt;T&amp;gt; source, Expression&amp;lt;Func&amp;lt;T, object&amp;gt;&amp;gt; path) where T : class&lt;br/&gt;{&lt;br/&gt;    //偷吃步的作法，如:Expression為x=&amp;gt;x.Customer.CustomerAddress,ToString後直接從第一個.分割，取後面的Customer.CustomerAddress&lt;br/&gt;    string spath = path.Body.ToString();&lt;br/&gt;    spath = spath.Substring(spath.IndexOf('.') + 1);&lt;br/&gt;    return source.Include(spath);&lt;br/&gt;}&lt;p&gt;上面的Code比較偷懶，應該要分析一下Expression比較正統&lt;/p&gt;public static IQueryable&amp;lt;T&amp;gt; Include&amp;lt;T&amp;gt;(this ObjectSet&amp;lt;T&amp;gt; source, Expression&amp;lt;Func&amp;lt;T, object&amp;gt;&amp;gt; path) where T : class&lt;br/&gt;{&lt;br/&gt;    StringBuilder pathBuilder = new StringBuilder();&lt;br/&gt;&lt;br/&gt;    MemberExpression pro = path.Body as MemberExpression;&lt;br/&gt;    while (pro != null)&lt;br/&gt;    {&lt;br/&gt;        //Exprssion有點像鏈結串列，從Statemant的後方往前連結，如: x=&amp;gt; x.Customer.CustomerAddress&lt;br/&gt;        //path.Body是CustomerAddress&lt;br/&gt;        //CustomerAddress的Expression是Customer&lt;br/&gt;        //Customer的Expression是x&lt;br/&gt;        pathBuilder.Insert(0, "." + pro.Member.Name);&lt;br/&gt;        pro = pro.Expression as MemberExpression; &lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    return source.Include(pathBuilder.ToString(1, pathBuilder.Length-1));&lt;br/&gt;}&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我沒有做錯誤檢查，想說有錯Entity Framework也會丟Exception，自己就不多事了。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;圖1 Model關聯圖&lt;/p&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/hwade/Windows-Live-Writer/EntityFrameworkInclude_127D8/image_1c21378d-8db5-4ed7-a764-b7c5721aa788.png" width="746" height="688"&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1857068.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857068.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2010/10/20/1857067.html</id><title type="text">C#仿Oracle Decode，將ValueType對應成String</title><summary type="text">在寫Page，有時會有int、bool等等要轉成文字輸出，如: &lt;%: item.Enable ? "啟用" : "停用" %&gt;，用? : 處理雖然方便，但如果要轉換的String加上二個以上，就非常難處理，可是Page的這三個&lt;%: %&gt;、&lt;%= %&gt;、&lt;%# %&gt;語法，不能用if或switch，因為有用過Oracle，很喜歡它的Decode函式，...</summary><published>2010-10-20T13:59:00Z</published><updated>2010-10-20T13:59:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857067.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857067.html"/><content type="html">&lt;p&gt;在寫Page，有時會有int、bool等等要轉成文字輸出，如: &amp;lt;%: item.Enable ? "啟用" : "停用" %&amp;gt;，用? : 處理雖然方便，但如果要轉換的String加上二個以上，就非常難處理，可是Page的這三個&amp;lt;%: %&amp;gt;、&amp;lt;%= %&amp;gt;、&amp;lt;%# %&amp;gt;語法，不能用if或switch，因為有用過Oracle，很喜歡它的Decode函式，所以我就自己寫一組Extension Method來處理。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;使用範例&lt;/strong&gt;&lt;/p&gt;&amp;lt;%--item.State的Type是int--%&amp;gt;&lt;br/&gt;&amp;lt;%: item.State.Decode("未知","無法使用","等待執行","就緒","執行中") %&amp;gt;&lt;br/&gt;&lt;br/&gt;&amp;lt;%--item.Enable的Type是bool?--%&amp;gt;&lt;br/&gt;&amp;lt;%: item.Enable.Decode("停用","啟用","未設定") %&amp;gt;&lt;br/&gt;&lt;br/&gt;&amp;lt;%--item.Enable的Type是int,但值不連續--%&amp;gt;&lt;br/&gt;&amp;lt;%: item.State.Decode(new Dictionary&amp;lt;int, string&amp;gt; {{100,"處理中"}, {200,"成功"}, {300,"失敗"} })%&amp;gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;程式說明&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我的Extension Method對像是用&lt;a href="http://msdn.microsoft.com/zh-tw/library/s1ax56ch.aspx" target="_blank"&gt;ValueType&lt;/a&gt;，為什麼用ValueType呢?，因為ValueType是bool、int、long、float甚至enum的基類(也就是C#中的struct)，這樣就有多型的效果，程式也可以少寫一點，然後我也有寫Nullable的對應，當是null時會對應到預設Meaage，又因為值可能是不連續的，如:100、200、300，不是0、1、2，所以總共有四個多載。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果值是連續的可以使用這二個Method&lt;/p&gt;public static string Decode(this ValueType value, params string[] messages)&lt;br/&gt;{&lt;br/&gt;    //大部分的ValueType都可以轉成int&lt;br/&gt;    int key = Convert.ToInt32(value);&lt;br/&gt;&lt;br/&gt;    //不在Array範圍中的用最後一個Message&lt;br/&gt;    if (key &amp;gt;= messages.Length || key &amp;lt; 0)&lt;br/&gt;    {&lt;br/&gt;        return messages.LastOrDefault();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    return messages[key];&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;public static string Decode&amp;lt;T&amp;gt;(this Nullable&amp;lt;T&amp;gt; value, params string[] messages) where T : struct&lt;br/&gt;{&lt;br/&gt;    if (value.HasValue)&lt;br/&gt;    {&lt;br/&gt;        return Decode(value.Value, messages);&lt;br/&gt;    }&lt;br/&gt;    else&lt;br/&gt;    {&lt;br/&gt;        //沒有值就用最後一個Message&lt;br/&gt;        return messages.LastOrDefault();&lt;br/&gt;    }&lt;br/&gt;}&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果值不是連續的可以使用這二個Method&lt;/p&gt;public static string Decode(this ValueType value, IDictionary&amp;lt;int, string&amp;gt; messages, string defaultMessage = null)&lt;br/&gt;{&lt;br/&gt;    //大部分的ValueType都可以轉成int&lt;br/&gt;    int key = Convert.ToInt32(value);&lt;br/&gt;&lt;br/&gt;    //判斷有沒有Key&lt;br/&gt;    if (messages.ContainsKey(key))&lt;br/&gt;    {&lt;br/&gt;        return messages[key];&lt;br/&gt;    }&lt;br/&gt;    else&lt;br/&gt;    {&lt;br/&gt;        //有預設message用預設message，沒預設message用最後一個message&lt;br/&gt;        if (defaultMessage == null)&lt;br/&gt;        {&lt;br/&gt;            return messages.Values.LastOrDefault();&lt;br/&gt;        }&lt;br/&gt;        else&lt;br/&gt;        {&lt;br/&gt;            return defaultMessage;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;public static string Decode&amp;lt;T&amp;gt;(this Nullable&amp;lt;T&amp;gt; value, IDictionary&amp;lt;int, string&amp;gt; messages, string defaultMessage = null) where T : struct&lt;br/&gt;{&lt;br/&gt;    if (value.HasValue)&lt;br/&gt;    {&lt;br/&gt;        return Decode(value.Value, messages);&lt;br/&gt;    }&lt;br/&gt;    else&lt;br/&gt;    {&lt;br/&gt;        //沒有值就用最後一個Message&lt;br/&gt;        if (defaultMessage == null)&lt;br/&gt;        {&lt;br/&gt;            return messages.Values.LastOrDefault();&lt;br/&gt;        }&lt;br/&gt;        else&lt;br/&gt;        {&lt;br/&gt;            return defaultMessage;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;NOTE:&lt;/p&gt;&lt;p&gt;我有想過把不連續的Method，this的Type改成object，讓所有object都可以使用，不過我剛好都沒有像A、B、C要對應成其他文字的需求，如果你有需要在自行修改吧。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;測試案例&lt;/strong&gt;&lt;/p&gt;enum TestEnum&lt;br/&gt;{&lt;br/&gt;    AA,&lt;br/&gt;    BB,&lt;br/&gt;    CC,&lt;br/&gt;    DD&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;[TestMethod, Owner("Wade")]&lt;br/&gt;public void U__DecodeExtension_Decode()&lt;br/&gt;{&lt;br/&gt;    var defaultMessage = "Test";&lt;br/&gt;    var message1 = new string[] { "A", "B", "C", "D" };&lt;br/&gt;    var message2 = new Dictionary&amp;lt;int, string&amp;gt; { { 10, "A" }, { 20, "B" }, { 30, "C" }, { 40, "D" } };&lt;br/&gt;&lt;br/&gt;    Assert.AreEqual("B", true.Decode(message1));&lt;br/&gt;    Assert.AreEqual("A", false.Decode(message1));&lt;br/&gt;    Assert.AreEqual("A", 0.Decode(message1));&lt;br/&gt;    Assert.AreEqual("B", 1.Decode(message1));&lt;br/&gt;    Assert.AreEqual("D", 4.Decode(message1));&lt;br/&gt;    Assert.AreEqual("D", (-1).Decode(message1));&lt;br/&gt;    Assert.AreEqual("B", ((byte)1).Decode(message1));&lt;br/&gt;    Assert.AreEqual("D", 10.Decode(message1));&lt;br/&gt;    Assert.AreEqual("D", (10f).Decode(message1));&lt;br/&gt;    Assert.AreEqual("B", (1L).Decode(message1));&lt;br/&gt;    Assert.AreEqual("A", (0L).Decode(message1));&lt;br/&gt;    Assert.AreEqual("A", TestEnum.AA.Decode(message1));&lt;br/&gt;    Assert.AreEqual("B", TestEnum.BB.Decode(message1));&lt;br/&gt;&lt;br/&gt;    Assert.AreEqual("D", true.Decode(message2));&lt;br/&gt;    Assert.AreEqual("D", false.Decode(message2));&lt;br/&gt;    Assert.AreEqual("A", 10.Decode(message2));&lt;br/&gt;    Assert.AreEqual("B", 20.Decode(message2));&lt;br/&gt;    Assert.AreEqual("D", 40.Decode(message2));&lt;br/&gt;    Assert.AreEqual("D", (-1).Decode(message2));&lt;br/&gt;    Assert.AreEqual("A", (10f).Decode(message2));&lt;br/&gt;&lt;br/&gt;    Assert.AreEqual("Test", true.Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("Test", false.Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("A", 10.Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("B", 20.Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("D", 40.Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("Test", (-1).Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("A", ((byte)10).Decode(message2, defaultMessage));&lt;br/&gt;    Assert.AreEqual("A", (10f).Decode(message2, defaultMessage));&lt;br/&gt;&lt;br/&gt;    Assert.AreEqual("D", (new Nullable&amp;lt;int&amp;gt;()).Decode(message1));&lt;br/&gt;    Assert.AreEqual("A", (new Nullable&amp;lt;int&amp;gt;(0)).Decode(message1));&lt;br/&gt;    Assert.AreEqual("D", (new Nullable&amp;lt;bool&amp;gt;()).Decode(message1));&lt;br/&gt;    Assert.AreEqual("B", (new Nullable&amp;lt;bool&amp;gt;(true)).Decode(message1));&lt;br/&gt;&lt;br/&gt;    Assert.AreEqual("D", (new Nullable&amp;lt;int&amp;gt;()).Decode(message2));&lt;br/&gt;    Assert.AreEqual("A", (new Nullable&amp;lt;int&amp;gt;(10)).Decode(message2));&lt;br/&gt;    Assert.AreEqual("D", (new Nullable&amp;lt;int&amp;gt;(40)).Decode(message2));&lt;br/&gt;&lt;br/&gt;}&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://lwltqw.blu.livefilestore.com/y1pKhgC_GfYfBag7inPH8FuS4-xd7q_sWMMsL4qpsu0j9rF1zxr1v0UsvRiVJXLoTzFJaKP8loPm9qP0keJijrcCxmgy6nMZ0rF/DecodeExtenstion.cs?download&amp;amp;psid=1" target="_blank"&gt;&lt;font size="5"&gt;原始碼下載&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;參考資料&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/zh-tw/library/s1ax56ch.aspx" target="_blank"&gt;Value Types (C# Reference)&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1857067.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857067.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/hwade/archive/2010/10/20/1857065.html</id><title type="text">Visual Studio 單元測試的3種Initialize與Cleanup</title><summary type="text">Visual Stuido的單元測試有3種Initialize與Cleanup，讓開發測試時，可以在TestMethod執行前做一些初始化，結束後做一些清除，而這3種Initialize與Cleanup各針對了不同時期，如:我猜鮮少人知道的Assembly的Initialize與Cleanup，是在一個測試專案的所有TestMethod執行前呼叫Initialize，與一個測試專案所有TestMe...</summary><published>2010-10-20T13:58:00Z</published><updated>2010-10-20T13:58:00Z</updated><author><name>黃偉榮</name><uri>http://www.cnblogs.com/hwade/</uri></author><link rel="alternate" href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857065.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857065.html"/><content type="html">&lt;p&gt;Visual Stuido的單元測試有3種Initialize與Cleanup，讓開發測試時，可以在TestMethod執行前做一些初始化，結束後做一些清除，而這3種Initialize與Cleanup各針對了不同時期，如:我猜鮮少人知道的&lt;strong&gt;&lt;font color="#800000"&gt;Assembly&lt;/font&gt;&lt;/strong&gt;的&lt;strong&gt;Initialize&lt;/strong&gt;與&lt;strong&gt;Cleanup&lt;/strong&gt;，是在一個測試專案的所有TestMethod執行前呼叫Initialize，與一個測試專案所有TestMethod結束後呼叫Cleanup。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AssemblyInitialize與AssemblyCleanup&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在一個測試專案的所有TestMethod執行前呼叫Initialize，與一個測試專案的所有測TestMethod結束後呼叫Cleanup，而一個測試專案中，只能有一個AssemblyInitialize與AssemblyCleanup，且只執行一次，通常用在整個專案都要使用情況，如:資料庫的掛載與卸除。&lt;/p&gt;//包AssemblyInitialize與AssemblyCleanup的Class，一定要有TestClass，而是不是static無所謂&lt;br/&gt;[TestClass]&lt;br/&gt;public /*static*/ class TestHelper&lt;br/&gt;{&lt;br/&gt;    //Method名稱可以隨便打，但一定要是static，且有一個參數context&lt;br/&gt;    [AssemblyInitialize]&lt;br/&gt;    public static void AssemblyInitialize(TestContext context)&lt;br/&gt;    {&lt;br/&gt;        //一個測試專案的最初始化&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    //Method名稱可以隨便打，但一定要是static&lt;br/&gt;    [AssemblyCleanup]&lt;br/&gt;    public static void AssemblyCleanup()&lt;br/&gt;    {&lt;br/&gt;        //一個測試專案的結束&lt;br/&gt;    }&lt;br/&gt;}&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;NOTE:&lt;/p&gt;&lt;p&gt;如果有二個測試專案&lt;/p&gt;&lt;p&gt;TestProjectA有&lt;/p&gt;&lt;p&gt;----AssemblyInitializeA&lt;/p&gt;&lt;p&gt;----AssemblyCleanupA&lt;/p&gt;&lt;p&gt;----Test1&lt;/p&gt;&lt;p&gt;----Test3&lt;/p&gt;&lt;p&gt;TestProjectB有&lt;/p&gt;&lt;p&gt;----AssemblyInitializeB&lt;/p&gt;&lt;p&gt;----AssemblyCleanupB&lt;/p&gt;&lt;p&gt;----&lt;strong&gt;Test2&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;因為執行測試的順序可以依名稱排序，所以照Test1、Test2、Test3執行，呼叫執行的順序為&lt;/p&gt;&lt;p&gt;----&lt;strong&gt;AssemblyInitializeA&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;----Test1&lt;/p&gt;&lt;p&gt;----&lt;strong&gt;AssemblyInitializeB&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;----Test2&lt;/p&gt;&lt;p&gt;----Test3&lt;/p&gt;&lt;p&gt;----AssemblyCleanupA&lt;/p&gt;&lt;p&gt;----AssemblyCleanupB&lt;/p&gt;&lt;p&gt;同時間如果有多個測試專案，要注意可能會交叉執行&lt;strong&gt;Initialize&lt;/strong&gt;。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ClassInitialize與ClassCleanup&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在執行一個TestClass下的所有TestMethod執行前與執行後呼叫，而每一個TestClass只能有一個ClassInitialize與ClassCleanup，每一個TestClass只呼叫一次，已在Visual Studio在單元測試檔案的範本中，只要拿掉註解就可以使用。&lt;/p&gt;[TestClass]&lt;br/&gt;public class ProgramTest&lt;br/&gt;{&lt;br/&gt;    ..........&lt;br/&gt;&lt;br/&gt;    //在Test1與Test2執行前呼叫，Method名稱可以隨便打，但一定要是static，且有一個參數context &lt;br/&gt;    [ClassInitialize]&lt;br/&gt;    public static void ClassInitialize(TestContext testContext)&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    //在Test1與Test2執行後呼叫，Method名稱可以隨便打，但一定要是static&lt;br/&gt;    [ClassCleanup]&lt;br/&gt;    public static void ClassCleanup()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    ..........&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;    [TestMethod]&lt;br/&gt;    public void Test1()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    [TestMethod]&lt;br/&gt;    public void Test2()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;}&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;NOTE:&lt;/p&gt;&lt;p&gt;也有交叉執行&lt;strong&gt;Initialize&lt;/strong&gt;問題。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;strong&gt;TestInitialize與TestCleanup&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在一個TestClass下的TestMethod，每一次執行前與呼叫後呼叫，而每一個TestClass只能有一個TestInitialize與TestCleanup，每一個TestMethod只呼叫一次，已在Visual Studio在單元測試檔案的範本中，只要拿掉註解就可以使用，可以將每一個TestMethod通用的初始化與清除，寫在這裡。&lt;/p&gt;[TestClass]&lt;br/&gt;public class ProgramTest&lt;br/&gt;{&lt;br/&gt;    ..........&lt;br/&gt;&lt;br/&gt;    //在Test1或Test2執行前呼叫，Method名稱可以隨便打，但一定要是static&lt;br/&gt;    [TestInitialize]&lt;br/&gt;    public static void TestInitialize()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    //在Test1或Test2執行後呼叫，Method名稱可以隨便打，但一定要是static&lt;br/&gt;    [ClassCleanup]&lt;br/&gt;    public static void TestCleanup()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    ..........&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;    [TestMethod]&lt;br/&gt;    public void Test1()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    [TestMethod]&lt;br/&gt;    public void Test2()&lt;br/&gt;    {&lt;br/&gt;        ..........&lt;br/&gt;    }&lt;br/&gt;}&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;參考資料&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/zh-tw/library/ms243147.aspx" target="_blank"&gt;[MSDN]單元測試架構&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;img src="http://www.cnblogs.com/hwade/aggbug/1857065.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/hwade/archive/2010/10/20/1857065.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
