<?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/47263/rss</id><updated>2012-01-30T08:21:55Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/47263/rss"/><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/30/2332133.html</id><title type="text">Windows phone 应用开发[13]-源码保护</title><summary type="text">关于源代码的保护.Windows phone在2010年10月份发布第一个RTM版本时. 相信国内最早进入Windows phone开发者都应该知道.在2010年11月Windows phone刚刚发布一个多月时.国外的一个网址为winmobile7.apphab.com的网站不知用什么方法获得了微软官方MarketPlace应用的直接下载地址，当时直接导致很多WP7的游戏和应用的.XAP安装包被泄露出去.当然那个时候应用量才3000多个.这对于刚刚推出Windows phone平台不久即遭到开发者知识产权保护漏洞.那时开发者还不多.但也在一定程度照成开发者对于微软平台安全性遭到质疑和不信任.</summary><published>2012-01-30T08:20:00Z</published><updated>2012-01-30T08:20:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/30/2332133.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/30/2332133.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;关于源代码的保护.Windows phone在2010年10月份发布第一个RTM版本时. 相信国内最早进入Windows phone开发者都应该知道.在2010年11月Windows phone刚刚发布一个多月时.国外的一个网址为&lt;a href="https://ssl.zxproxy.com/browse.php?u=0d7e11861605Oi8vd2lubW9iaWxlNy5hcHBoYWIuY29tLw%3D%3D&amp;amp;b=6"&gt;winmobile7.apphab.com&lt;/a&gt;的网站不知用什么方法获得了微软官方MarketPlace应用的直接下载地址，当时直接导致很多WP7的游戏和应用的.XAP安装包被泄露出去.当然那个时候应用量才3000多个.这对于刚刚推出Windows phone平台不久即遭到开发者知识产权保护漏洞.那时开发者还不多.但也在一定程度照成开发者对于微软平台安全性遭到质疑和不信任.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Windows phone同样也是采用XAP安装包.而XAP其实可以通过强制修改文件格式转换成.rar.即可以通过解压工具获取XAP打包的DLL文件.通过逆向工程反编译工具.NET REflector是可以查看到源代码的.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;当然官方团队意识到这个问题.很快完善修补该漏洞.并对于.XAP安装包中的文件可被直接破解反编译的问题.对开发者提出可以使用Dotfuscator这类的代码混淆工具来保护自己的源代码.即使XAP在第三方情况被恶意破解泄露.但也不会至源码会被直接暴漏出来.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;针对这个问题微软官方很快就在2010年11月6日就宣布PreEmptive Solutions 合作推出 &lt;/font&gt;&lt;a href="http://www.preemptive.com/windowsphone7.html"&gt;&lt;font face="Consolas"&gt;Runtime Intelligence for Windows Phone&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;，这是一款面向 Windows Phone 7 的应用统计与分析工具.在2011年PreEmptive Solutions也相继推出专门针对Windows phone 应用程序源码混淆的免费工具&lt;a href="http://www.preemptive.com/windowsphone7.html" target="_blank"&gt;PreEmptive Protection For Windows phone 7&lt;/a&gt;.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;本篇将从Dotfuscator工具的角度来切入Windows phone应用的源码保护.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;1&amp;gt;源码保护现状&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;源码保护这个已经不是什么新鲜主题..NET CLR的出现.衍生出Native Code和Managed Code[一说托管代码].执行在 .Net CLR 环境下的应用程序都是属于 Managed Code 的范围，而 Managed Code 在编译时会先编译成 MSIL (Microsoft Intermediate Language)，实际执行时交由 JIT (Just-In-Time) 编译成机器码之后执行，而由于架构上的变更，MSIL (也就是我们的 .Net exe、dll 档案等) 是比较容易被反编译.[该段落引用自&lt;/font&gt;&lt;a href="http://www.wikipedia.org/" target="_blank"&gt;&lt;font face="Consolas"&gt;Wikipedia&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;].NET代码被编译成IL代码，而不是ARM汇编.对于没有没进行源码混淆的应用程序Souce Code泄露的风险明显增大.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实对于SouceCode保护.并不仅是Windows phone平台所面临的问题. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Android平台采用的是Java语言开发.Jave和.NET平台一样.在各自环境执行时.并不会将代码直接便异常机器码.而是编译成一种叫java字节码的中间语言.一般的java程序编译完成后是一个完整的Jar包.Android则使用DEX。你可以通过诸如&lt;/font&gt;&lt;a href="http://code.google.com/p/dex2jar/"&gt;&lt;font face="Consolas"&gt;dex2jar&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;这样的工具将DEX文件转换成jar文件，然后使用诸如&lt;/font&gt;&lt;a href="http://java.decompiler.free.fr/?q=jdgui"&gt;&lt;font face="Consolas"&gt;JD-GUI&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;这样的工具反编译成Java代码。其风险和Windows Phone平台是类似的.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;iPhone/iPad使用Objective-C语言，并且将代码直接编译成机器码。因此反编译会有较大的困难。然而，市场上依然存在一些专业反向工程工具，例如&lt;/font&gt;&lt;a href="http://www.hex-rays.com/products/ida/index.shtml"&gt;&lt;font face="Consolas"&gt;IDA&lt;/font&gt;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;目前主流平台对比可见.各个平台情况也是参差不齐.&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;2&amp;gt;Dotfuscator构建源码混&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;PreEmptive Solutions在没有和MS合作之前,Dotfuscator代码混淆工具还需要额外的申请.官方需要一到两天的审核时间.现在只需要到&lt;font face="Consolas"&gt;PreEmptive Solutions官网上找到Windows phone对应的主页:&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;PreEmptive Solutions For Windows phone：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.preemptive.com/windowsphone7.html"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;http://www.preemptive.com/windowsphone7.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&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="2012-01-29_1744424" border="0" alt="2012-01-29_1744424" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619454316.png" width="363" height="484" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;现在申请流程已经大大简化了.基本在申请成功后可以收到官方发过来的一封说明邮件如下:&lt;/font&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="2012-01-29_174950" border="0" alt="2012-01-29_174950" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619459365.png" width="644" height="171" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;邮件中提供对应的软件下载地址.对应S/N注册码,该S/N码会在软件安装提示输入:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-29_175729" border="0" alt="2012-01-29_175729" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619467446.png" width="609" height="202" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;安装完成后可以看到 切换并选择对应assemblies集合:&lt;/font&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="2012-01-29_181124" border="0" alt="2012-01-29_181124" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120130161946860.png" width="410" height="332" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;采用默认设置运行可见操作主页面&lt;/font&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="2012-01-30_143924" border="0" alt="2012-01-30_143924" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619475037.png" width="644" height="482" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;这时创建一个用于测试Windows Phone Application 命名为:SouceCodeProtect_Demo.在MainPage页面添加一个简单的TextBox和Button按钮.在按钮事件处理TextBox用户输入处理方法如下:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;      &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Confirm_BT_Click(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;            &lt;span &gt;string&lt;/span&gt; userInputText = &lt;span &gt;this&lt;/span&gt;.UserInput_TB.Text.Trim();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;string&lt;/span&gt;.IsNullOrEmpty(userInputText))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;                MessageBox.Show(&lt;span &gt;"Please Input Basic Message Text!"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.UserInput_TB.Focus();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;            &lt;span &gt;else&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;                MessageBox.Show(&lt;span &gt;"You have been Input "&lt;/span&gt; + userInputText);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;运行效果如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-30_150439" border="0" alt="2012-01-30_150439" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619478450.png" width="268" height="484" /&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="2012-01-30_150458" border="0" alt="2012-01-30_150458" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619481581.png" width="268" height="484" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这时有了一个简单功能的Windows phone 应用程序.当然此处的目的为了测试演示的目的.这时如果我们要把这个应用程序上线官方MarketPlace.一般情况需要发布一个Release版本的XAP安装包.&lt;/font&gt;&lt;font face="Consolas"&gt;找到对应SouceCodeProtect_Demo.xap 强制修改xap为rar格式并解压可以见到XAP打包的文件列表如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-30_152053" border="0" alt="2012-01-30_152053" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619488026.png" width="707" height="154" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;此时当前DLL并没有任何代码保护措施. 如果当前发布的应用程序的XAP安装意外流出.或是遭到第三方强制破解.如果通过逆向工程反编译工具.NET REflector查看对应SourceCodeProtect_Demo.DLL可以看到:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-30_152605" border="0" alt="2012-01-30_152605" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201301619492826.png" width="625" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;我们的核心代码就会向密码中明文一样在没有任何保护措施的情况下被暴露出来.这时该如何保护自主知识产权的源代码呢.?&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;积极采用云平台.把重要逻辑放到云端:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如果Windows phone在做客户端工作.你也可以考虑将部分重要的逻辑放到云端，例如Windows Azure之上，尤其是那些需要很多计算资源的逻辑，例如电影编码。手机是一个客户端，性能和存储空间都有限，有部分功能不适用于在手机上进行。事实上，Windows Phone自带的一部分功能，例如朗读文本，就需要通过微软的云服务才能完成。将逻辑放在云端还有一个好处就是，各种各样的客户端都能够通过访问服务的方式使用该功能，而不需要针对每个客户端写专门的代码。像部署在Windows Azure这样的云平台上的服务，客户端无法直接取得程序，只能通过服务暴露出的接口间接地访问云端的程序逻辑，因此也不存在反编译问题。当然，这样做也有坏处，例如可能需要用户支付网络流量相关费用，而且有时候网络传输可能有点慢.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;使用高级编程语言特性:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;C#这样的语言有一些高级语言功能，例如lambda expression和yield return。使用这样的功能不仅使得写代码变得方便，同时也会增加逆向工程反编译的难度。因为很多使用高级语言功能撰写的代码会在编译时由编译器自动转化成一些比较繁琐，读起来比较累的代码。大多数逆向工程反编译工具只能产生这些由编译器生成的代码，而看不到你的原始代码。&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;使用源代码混淆工具:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当然从成本和开发者可控的角度而言.通常的做法就是版本发布后考虑将源代码进行混淆。这会使得反向工程后的源代码很难被读懂。在.NET平台上，可以使用诸如&lt;/font&gt;&lt;a href="http://www.preemptive.com/products/dotfuscator/overview"&gt;&lt;font face="Consolas"&gt;Dotfuscator&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;这样的工具.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如何使用Dotfuscator工具执行源代码混淆操作?&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;...&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2332133.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/30/2332133.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/29/2331263.html</id><title type="text">Windows phone 应用开发[12]-Pex 构建自动化白盒测试[下]</title><summary type="text">本篇承接于上篇Windows phone 应用开发[11]-Pex 构建自动化白盒测试[上] .大概了解Pex作为自动化白盒测试工具工作方式.以及提出参数化单元测试的概念.为开发人员减少手动编写大量独立路径下单元测试时间.Pex允许开发人员编写单独的参数化测试方法，并根据测试方法的逻辑分支自动生成测试数据及Assert语句。虽然开发人员还是需要手动编写单元测试，但是Pex可以确保对代码进行了充分的...</summary><published>2012-01-29T08:42:00Z</published><updated>2012-01-29T08:42:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/29/2331263.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/29/2331263.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;本篇承接于上篇&lt;/font&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/19/2327580.html"&gt;&lt;font face="Consolas"&gt;Windows phone 应用开发[11]-Pex 构建自动化白盒测试[上]&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; .大概了解Pex作为自动化白盒测试工具工作方式.以及提出参数化单元测试的概念.为开发人员减少手动编写大量独立路径下单元测试时间.Pex允许开发人员编写单独的参数化测试方法，并根据测试方法的逻辑分支自动生成测试数据及Assert语句。虽然开发人员还是需要手动编写单元测试，但是Pex可以确保对代码进行了充分的测试.并能通过Pex自动修复Bug.添加测试项目.其中的Moles组件可用于模拟框架中包括静态成员在内的几乎所有成员，大幅提高了对测试的支持程度.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;本篇来探索一些Pex 在Windows phone Application应用程序中使用.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;首先在Visual Studio 2010中构建一个Windows phone 应用程序BasicWinPhoneComponent_Demo.并实现一个简单分类列表显示.Well.定义一个标准的ViewModel执行数据绑定.&amp;#160;&amp;#160; Viewmodel代码如下:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; MainPage_ViewModel:BasicViewModel&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        ObservableCollection&amp;lt;CatalogInfo&amp;gt; catalogInfoCol = &lt;span &gt;new&lt;/span&gt; ObservableCollection&amp;lt;CatalogInfo&amp;gt;();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; ObservableCollection&amp;lt;CatalogInfo&amp;gt; CatalogInfoCol&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;            get { &lt;span &gt;return&lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogInfoCol; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;            set&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.catalogInfoCol = &lt;span &gt;value&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;                &lt;span &gt;base&lt;/span&gt;.NotifyPropertyChangedEventHandler(&lt;span &gt;&amp;quot;CatalogInfoCol&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; LoadCatalogInfoDemoData()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.catalogInfoCol.Clear();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.catalogInfoCol.Add(&lt;span &gt;new&lt;/span&gt; CatalogInfo() { CatalogTitle=&lt;span &gt;&amp;quot;Music &amp;amp; Video&amp;quot;&lt;/span&gt;,CatalogContent=&lt;span &gt;&amp;quot;Base Catalog Title&amp;quot;&lt;/span&gt; });&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.catalogInfoCol.Add(&lt;span &gt;new&lt;/span&gt; CatalogInfo() { CatalogTitle = &lt;span &gt;&amp;quot;Book &amp;amp; Libray&amp;quot;&lt;/span&gt;,CatalogContent=&lt;span &gt;&amp;quot;Basic Book&amp;quot;&lt;/span&gt; });&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;     }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在MainPage Code-Behind执行数据绑定代码如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt; &lt;span &gt;private&lt;/span&gt; MainPage_ViewModel mainPage_ViewModel = &lt;span &gt;null&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        &lt;span &gt;void&lt;/span&gt; MainPage_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;this&lt;/span&gt;.mainPage_ViewModel == &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.mainPage_ViewModel = &lt;span &gt;new&lt;/span&gt; MainPage_ViewModel();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.mainPage_ViewModel.LoadCatalogInfoDemoData();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.DataContext = mainPage_ViewModel;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;运行效果:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-21_112747" border="0" alt="2012-01-21_112747" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642199870.png" width="268" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;一个基础功能实现完成后.现在要对ViewModel中代码做基本的UT.安装完PEX之后直接右键点击可以看到如下操作选项Run Pex 和PEX:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_152753" border="0" alt="2012-01-19_152753" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642197079.png" width="378" height="225" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先Run Pex即时生成测试用例 如果是安装后.首次运行Run Pex 在Windows phone Application中.会提示:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_100304" border="0" alt="2012-01-19_100304" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642192967.png" width="540" height="181" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;该窗体提示选择当前构建UT所基于的测试框架.PEX的扩展允许下载并支持Nunit MBUnit、或Xunit.Net测试框架.当前根据官方说明PEX会自动检测当前应用程序类型.根据不同应用会在测试框架选择项中给出指定测试框架.当然针对Silverlight、Windows phone应用标准的还是Silverlight Unit Test FrameWork[SUTF]框架. 如果没有安装Silverlight Toolkit或是修改了默认的安装目录.这里还需要手动指定当前框架安装路径.在前几篇中提到SUTF&amp;#160; windows phone版本测试框架需要两个核心的DLL:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;&lt;span &gt;//Silverlight Unit Test FrameWork For Windows phone Version DLL&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;Microsoft.Silverlight.Testing.dll&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以把该DLL文件拷贝到一个独立的目录下并初始化路径:.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_105212" border="0" alt="2012-01-19_105212" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642204952.png" width="540" height="181" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;点击Ok 出现问题提示无法Assembly Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll 这个DLL. 在目录中删除掉该DLL.点击OK.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-21_121337" border="0" alt="2012-01-21_121337" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642204146.png" width="488" height="177" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;PEX 目前需要单独解析DLL.需要重新指定Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll文件映射.PEX自动解析成功后 Run PEX在创建测试用例过程中出现异常:.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_100545" border="0" alt="2012-01-29_100545" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642218639.png" width="644" height="220" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;谈到这个问题.这里有必要解释一下Run Pex和Pex-&amp;gt;Create Parameterized Unit Test 两种运行Pex方式之间的区别.如果独立运行Run Pex 选项操作时我们能发现它没有像Pex-&amp;gt;Create Parameterized Unit Test 选项一样，需要独立创建一个单元测试项目.实现测试代码与宿主源代码之间的分离. 但当你执行Run Pex时你可以在Visual Studio 左下角状态栏下.可以看到Run Pex时其实把创建这个单元测试项目交给Pex内部来做.这一方面能够为测试用例构建驱动环境. 同时能够实现在无需开发人员维护测试用例代码情况下即时run Pex方式运行代码块的UT. 查找Bug并通过Pex自动修复.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;那二者区别在哪呢?&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;其实这个问题上篇&lt;/font&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/19/2327580.html"&gt;&lt;font face="Consolas"&gt;Windows phone 应用开发[11]-Pex 构建自动化白盒测试[上]&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; 中Pex构建参数化单元测试中提到.只是没有联系到run Pex. Pex-&amp;gt;Create Parameterized Unit Test 目的其实通过创建一个手写的参数化单元测试，Pex完全自动地分析代码，来决定相关的测试输入。其结果就是生成一个有着高度代码覆盖的传统单元测试.而Run Pex运行的Ut效果是即时.开发人员在无需维护测试代码前提下就能看到当前代码块Ut测试结果. 其实二者内部的原理并无差异. Run Pex其实在内部创建一个代码不可见的参数化单元测试项目在此基础之上构建测试用例.多次执行而获得即时测试结果.而Pex-&amp;gt;Create Parameterized Unit Test 则可见的把当前测试代码放到当前解决方案中.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;那现在遇到什么问题?&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Event：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;&amp;quot;could not create an instance of BasicWinPhoneComponent_Demo.ViewModels.MainPage_ViewModel&amp;quot;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Message：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Click on 'Edit Factory', or, as a workaround, create a parameterized test that constructs the value from simpler values.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到在构建单元测试用例时.无法创建MainPage_ViewModel实例.导致整个Run Pex在构建测试用例驱动环境时中断执行. 是否觉得上面步骤还不够具体详细. 因为我们始终在执行Run Pex时.不知道Pex内部是如何工作的? well.这时选中”Cound not Create an Instance …”测试Event事件:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_105525" border="0" alt="2012-01-29_105525" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642216720.png" width="644" height="221" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到在右栏Detail 下有一个Ignore操作.目的忽视当前错误继续在Pex创建ViewModels实例.:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_110034" border="0" alt="2012-01-29_110034" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120129164221134.png" width="598" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;点开折叠的节点.可以清晰看到内部Pex在执行Run Pex时内部执行整个流程步骤.可以看到Run PEx 时PEx 内部执行流程如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Pex 执行流程:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Create Pex Project –&amp;gt; Create Test Project –&amp;gt; Create Visual Studio Unit TEst Silverlight Project …&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先创建一个Pex Project. 在Pex Project基础上创建一个普通的测试项目Test Project.其中这14操作中1-6步是用来创建测试项目.7-10是为当前测试项目添加构建测试用例驱动环境所需的引用.11-13步为当前测试项目添加指定的测试文件,. 带黄色长方块即是要忽视的操作&amp;quot;，执行:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_110524" border="0" alt="2012-01-29_110524" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642221803.png" width="644" height="215" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;需要基于一个独立的测试项目来承载测试用例.创建:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_110646" border="0" alt="2012-01-29_110646" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642229361.png" width="644" height="480" /&gt;:&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当执行Ignore操作第四步Create ViualStudio Unit Test Silverlight Project时.出错. 具体信息如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Update result: &#xD;
        &lt;br /&gt;failed to generate project CSharp\Silverlight\Silverlight Unit Test Project.zip, Could not find template for new project&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到在创建普通单元测试项目时找不到对应Silverlight unit Test Framework Windows phone模板.well.这是查看Pex And Moles&lt;a href="http://research.microsoft.com/en-us/projects/pex/releasenotes.aspx" target="_blank"&gt;官方Realse Note&lt;/a&gt;记录,针对这个模板支持的问题可以找到如下说明:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&lt;font style="font-weight: bold"&gt;v0.92.50603.1, 06/07/2010&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;ul&gt;&#xD;
    &lt;li&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Highlights&lt;/strong&gt;&lt;/font&gt; &#xD;
&#xD;
      &lt;ul&gt;&#xD;
        &lt;li&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Rex integrates Pex. &lt;/strong&gt;&lt;/font&gt;&lt;a href="http://research.microsoft.com/rex"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Rex&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;&lt;strong&gt; is a tool that explores regular expression. It's algorithms have been integrated into the whitebox exploration engine of Pex. As a result, Pex is much smarter about generating strings that match a Regex.IsMatch call. &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;&#xD;
&#xD;
        &lt;li&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Preparable Types. It is possible to register a lazy setup method for a type. This method has to be static and will be invoked by Pex before any method of the given type is executed. This is a great way to mole parts of your system on demand. &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;&#xD;
&#xD;
        &lt;li&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font color="#000000"&gt;Silverlight and Silverlight for Windows Phone support (Alpha).&lt;/font&gt;&lt;/strong&gt; &lt;strong&gt;Right-click on any Silverlight project and hit 'Run Pex'. Pex will run your Silverlight code on the desktop CLR and start generating tests for it. The unit tests can be executed using the Silverlight unit test framework from&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://silverlight.codeplex.com/"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;http://silverlight.codeplex.com&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/font&gt; &lt;/li&gt;&#xD;
      &lt;/ul&gt;&#xD;
    &lt;/li&gt;&#xD;
  &lt;/ul&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到在2010/7/6日版本更新的Realse Note中.提到这个版本已经支持Silverlight中运行Pex实现白盒自动化测试.Pex针对silverlight中.cs文件，默认使用VisualStudioUnitTestSilverlight框架。[assembly: PexAssemblySettings(TestFramework = &amp;quot;VisualStudioUnitTestSilverlight&amp;quot;)].很多在Silverlight 中做过Ut的同学应该知道.PEX会针对Silverlight应用程序会也会创建一个对应桌面版的Silverlight Project.而针对Silverlight Unit TEst FrameWork测试结果也会自动显示Windows PC端的IE浏览器中:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="图片1" border="0" alt="图片1" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642235282.png" width="644" height="324" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;那针对 Windows Phone Application应用程序呢? 针对这个问题质询官方Pex And Moles团队对Windows phone支持的建议.得到回复如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;&amp;quot;hi Peli:&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;I am working on testing WP7 application.&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;I found a very excellent tool &amp;quot;Silverlight Unit Test Framework&amp;quot; to do unit test.&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;But, I want to do some automated tests for each function by inputting random data (like stress test).&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;There is a tool called &amp;quot;Pex&amp;quot; (&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://research.microsoft.com/en-us/projects/pex/"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;http://research.microsoft.com/en-us/projects/pex/&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt; ) that can do that things for me, but it seems not support WP7 right now.&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;So, is there exist a tool like &amp;quot;Pex&amp;quot; can do stress test on WP7?&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;Peli Reply:&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;Hi kaichen,&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;I am a developer from the Pex project. Unfortunately, Pex does not support Silverlight or Silverlight for Phone currently. We have no immediate plans to support this runtime in the short term.&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;You can post other questions on Pex at: &lt;/strong&gt;&lt;/font&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/pex/threads/"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;http://social.msdn.microsoft.com/Forums/en-US/pex/threads/&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;.&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;Cheers, Peli&lt;/font&gt; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&amp;quot;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well. you see! &lt;strong&gt;Pex目前并不支持Windows phone 应用程序自动化白盒测试&lt;/strong&gt;.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;So.通过以上出现的问题.知道.Pex出现问题的地方在于.在Windows phone Application 中Run Pex时 Pex中并没有一个支持Windows Phone的framework作为extension 内置模板.导致创建测试应用程序失败.如果能够Run Pex能够在Silverlight和Windows phone 应用程序之间随意选择切换.就更好了.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在&lt;/font&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html"&gt;&lt;font face="Consolas"&gt;Windows phone 应用开发[9]-单元测试&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;中我提到采用默认的Visual Studio Test框架可以在建立测试用例完成后 指定测试用例输出的应用程序. 这是否能够提供一种解决Pex在Windows phone 中实现的思路呢,这点正如园友&lt;a href="http://home.cnblogs.com/u/215508/"&gt;sinodragon21&lt;/a&gt;在&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html#2296092"&gt;Windows phone应用开发[9]-单元测试评论中&lt;/a&gt;提出想法一致:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如果我们采用Pex自动化白盒测试工具.可以看到其实Pex的工作相对通过Windows phone Test Project模板创建单元测试项目. Pex的目的主要在于通过参数化单元测试构建测试用例.而目前的问题在于.在构建这些测试用例驱动环境时无法创建对应Windows phone 测试项目. so. 如果二者能够完美的结合.可以通过PEx自动探索分析代码逻辑流，自动产生测试数据和单元测试用例。这时我们需要需要为Pex写一个支持Windows Phone的framework作为extension（假定它叫做VisualStudioUnitTestWindowsPhoneSilverlight），在&amp;quot;Run Pex&amp;quot;时可以选择该framework，最后生成XXX.Tests是Windows Phone工程，而不是PC版的silverlight工程.使其Pex通过SUTF测试结果能够在Windows phone模拟器中输出.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这时首先在Solution中添加一个Windows phone Test project 测试项目 命名为BuildCompontentDemo.Tests.该模板可以通过在Online Template中搜索Windows phone Test找到:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_141506" border="0" alt="2012-01-29_141506" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642236428.png" width="644" height="446" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;创建完成手动添加Silverlight unit Test Framework框架两个核心DLL的引用:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_141818" border="0" alt="2012-01-29_141818" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642247018.png" width="431" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.这时找到源程序BasicWinPhoneCompontent_Demo.中ViewModel 通过Pex-&amp;gt;Create Parameterized Unit Test 选项对应参数化测试用例.输出把该用例代码指定输出到对应的刚刚创建的Windows phone TEst Project 上BuildCompontentDemo.Tests中来:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-29_114244" border="0" alt="2012-01-29_114244" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642241511.png" width="644" height="215" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在Add New Test Project中可以看到Pex只能创建自己内置模板内对应Windows phone Test Project .而无法想普通测试的方式在建立测试用例后可以指定测试用例代码输出项目类似:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_142616" border="0" alt="2012-01-19_142616" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642252972.png" width="577" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Pex并没有暴露类似Visual Studio默认带有测试框架可以指定测试用例输出项目的的操作. so. 针对这个思路目前基于现有的Windows phone测试模板还是一条Dead Way.问题还是在于Pex自身.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.至此问题已经非常明朗.如果要在Windows phone 采用PEX自动化白盒工具构建单元测试.问题还是集中Pex自身.从开发者角度来说基本是无法行通的.至少从目前尝试的角度没有行通.当然也欢迎其他的园友有好的思路和想法均可以评论中提出.共同探讨实践.但是作为开发者单一从使用工具的角度来说.这些工作并不适合寻求所谓的”突破”。因为官方在构建PEx版本时就没有打算支持Windows Phone的运行时.而目前的问题多集中于Pex自身.所以这些工作应该官方官方团队来做. 如果执意使用该工具.在我看来Pex所有带来的自动化的简便.远大于解决当前问题付出代价要高,这样的性价比远比另寻其他工具要来的简便实在.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;即使解决该问题.也难免在团队协作推广和使用过程遇到问题.光有流程和意识,而在实践中缺乏必要可控方法是很难推广和落地一项新技术的.当然这里更没有探讨所谓的成本,所以关于PEX在Windows phone自动化白盒测试推荐各位以尝试探索的精神去解决.并不推荐在实际项目推广应用.前提是解决该问题,但PEX在自动化白盒测试中设计理念还是值得深入理解的。&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/font&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如上真实记录Pex在Windows phone探索过程.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;当然官方也给出一些关于PEX很有意思一个应用Pex4Fun:&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;Pex4Fun在线地址:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;Pex4Fun Online Demo :&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://pex4fun.com/"&gt;&lt;font size="2"&gt;&lt;strong&gt;http://pex4fun.com/&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&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="2012-01-29_161912" border="0" alt="2012-01-29_161912" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642253005.png" width="537" height="354" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Pex4Fun这个应用是微软研究院.推出一款Web通过C# /VB/F#语言在线编程.其实你也应该能看出来这里用到Pex那一部分.Pex为何能够自动化建立白盒的UT.最终一点就是PEX能够完全自动地分析代码行为，来决定相关的测试输入.有了PEX作支撑这就不难理解这个在线编译工具强大了吧.当然针对Pex4Fun也推出对应Windows phone 应用:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;Pex4Fun For Windows phone：&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;Pex4Fun :&lt;a href="http://www.windowsphone.com/en-US/apps/db980958-7c4a-e011-854c-00237de2db9e"&gt;http://www.windowsphone.com/en-US/apps/db980958-7c4a-e011-854c-00237de2db9e&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&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="2fa104fe-26a2-416f-8d7c-67336dd2f46c" border="0" alt="2fa104fe-26a2-416f-8d7c-67336dd2f46c" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642254990.png" width="292" height="484" /&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="779ae31b-6675-47d1-8f79-0b7e6ea37f00" border="0" alt="779ae31b-6675-47d1-8f79-0b7e6ea37f00" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642263071.png" width="292" height="484" /&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="0017871e-dd1b-4553-a98a-0b94e6d34636" border="0" alt="0017871e-dd1b-4553-a98a-0b94e6d34636" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201291642266692.png" width="292" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;同类型的应用目前在Windows phone平台很少见.原来我在查看应用MSDN Library Reader就考虑到.如果能够在手机应用C#多种语言实现随时随意写Code.同时随时随顶在手机编译运行.该多么Cool.果不其然.Pex4Fun就做了这样的工作.它类似2012年初微软推出Visual Studio开发人员成就系统.可以在线写代码赚取积分进入排行榜.另外不得不说的是.里面还有各种各样的考题和考题对应的需求说明文档.这对开发人员来说真的很不错的一个应用.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Pex4Fun是目前唯一Pex在Windows phone以功能形式出现的应用.但我一直很疑惑该应用在使用Pex功能是如何实现的.? 如果是纯客户端意义.倒觉得意义不大.但该项目非开源.so并不知内部其实现过程.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;关于Pex在Windows phone构建白盒自动化测试整个过程如上.如有疑问请在评论提出.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;本篇演示的源代码下载地址:&lt;a href="http://files.cnblogs.com/chenkai/BasicWinPhoneComponent_Demo.rar"&gt;/Files/chenkai/BasicWinPhoneComponent_Demo.rar&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2331263.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/29/2331263.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/19/2327580.html</id><title type="text">Windows phone 应用开发[11]-Pex 构建自动化白盒测试[上]</title><summary type="text">昨天一位园友sinodragon21在Windows phone应用开发[9]-单元测试评论中.提出关于Windows phone 单元测试中能否使用微软的Pex自动化生成工具生成单元测试用例.和单元测试质量即代码覆盖率统计问题.很有价值. 针对这两个问题.首先需要解释.关于Windows phone 中单元测试现状.针对Windows phone应用程序Unit Test 官方并没有在IDE提...</summary><published>2012-01-19T10:59:00Z</published><updated>2012-01-19T10:59:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/19/2327580.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/19/2327580.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;昨天一位园友&lt;/font&gt;&lt;a href="http://home.cnblogs.com/u/215508/" target="_blank"&gt;&lt;font face="Consolas"&gt;sinodragon21&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;在&lt;/font&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html#2296092" target="_blank"&gt;&lt;font face="Consolas"&gt;Windows phone应用开发[9]-单元测试评论中&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;.提出关于Windows phone 单元测试中能否使用微软的Pex自动化生成工具生成单元测试用例.和单元测试质量即代码覆盖率统计问题.很有价值.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;针对这两个问题.首先需要解释.关于Windows phone 中单元测试现状.针对Windows phone应用程序Unit Test 官方并没有在IDE提供对应的测试框架,目前开发者社区使用比较广泛框架是MS Windows phone 产品组&lt;/font&gt;&lt;a href="http://www.jeff.wilcox.name/" target="_blank"&gt;&lt;font face="Consolas"&gt;Jeff.wilcox&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;维护的Silverlight Unit Test Framework[SUTF] Windows phone版本.详见Blog:&lt;/font&gt;&lt;a href="http://www.jeff.wilcox.name/2010/05/sl3-utf-bits/"&gt;&lt;font face="Consolas"&gt;Updated Silverlight Unit Test Framework bits for Windows Phone and Silverlight 3&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; . 但这个版本始终作为个人形式对开发者发布.并没有以正式的官方渠道向Windows phone开发者推送，所以官方对此并没有提供指定的维护和开发者社区支持.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;至此官方也就没有提供自动化测试工具道理. 类似Android 平台自动化Monkeyrunner之外还有更多选择.而Windows phone自动化测试只能靠开发者自己想办法.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;那么关于SUTF 中Code Converage代码覆盖率呢? 针对这个问题 特别咨询SUTF WP版本维护作者Jeff.Wilcox.得到回复信息如下:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;HI Jeff,              &lt;br /&gt;how to take code coverage from SilverLight Unit test framework for WP7?&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;jeffwilcox Reply:&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;        &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;Code coverage is not available, it was a feature that was cut before              &lt;br /&gt;shipping for 2010 from the toolkit.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;     &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在2010年发布SUTF版本时已经去掉对Code Converage支持. so.既然如此是否真的就此定论了.? Now 现在提到Pex and Moles.还是不甘心.打算动手在应用程序中亲自验证.本篇并不打算立即采用Pex在SUTF进行验证.有必要系统了解Pex and Moles.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;1&amp;gt;构建Pex测试环境&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Well.关于Pex And Moles其实可以分为两个部分.其一Pex-全称是[Program EXploration]是微软研究院的一个关于白盒测试自动生成工具.原来开发人员只能通过指定路径编写独立的测试用例.PEX通过分析代码来自动生成测试用例。对于程序里面的每一行代码，PEX都会尽可能地生成合适的输入值来达到提高覆盖率的目标。同时PEX还会分析代码中的分支，生成覆盖更多分支的测试代码（输入数据）；PEX在执行代码的同时会监控和分析代码的控制流和数据流，了解程序的行为。每运行完单一个测试以后，PEX会选择一条在前面的测试中没有覆盖到的路径，并且尝试执行它.本篇主要来讲到的是PEX.&lt;/font&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="pex-testing" border="0" alt="pex-testing" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859127552.png" width="204" height="125" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;PEX自动化生成用例并执行UT返回测试结果的过程.大大减少开发人员手动编写大量测试用例情况发生.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;关于PEX and Moles可通过如下链接了解更多:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;PEX And Moles：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/projects/pex/" target="_blank"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Pex and Moles - Isolation and White box Unit Testing for .NET&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Download Page:          &lt;br /&gt;&lt;/strong&gt;&lt;a href="http://research.microsoft.com/en-us/projects/pex/downloads.aspx" target="_blank"&gt;&lt;strong&gt;Pex and Moles – Download Page Link&lt;/strong&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Get Start Online PDF Document:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/projects/pex/digger.pdf"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;http://research.microsoft.com/en-us/projects/pex/digger.pdf&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;找到下载页面.PEX现在有3个Flavor，支持2个版本的Visual Studio，分别是VSTS2010和VSTS2008，这3个版本的PEX在功能上存在区别，这主要因为下载受众群体不同,一般用户只能使用到PEX功能.本篇所有演示都是基于Visual Studio 2010. 基于MSDN订阅权限下载PEX And Moles完整版本.&lt;/font&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="2012-01-18_190501" border="0" alt="2012-01-18_190501" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859129155.png" width="742" height="168" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;安装完成后.可以打开Visua Studio 立即创建一个Console Application命名为BasicConsolePexComponent_Demo,在此先不要把焦点放在PEX原理实现上.来快速体验一下PEX.首先需要在Program类中顶一个转换字符串的方式.作为测试用例的宿主程序.创建如下:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;/// Test Case Convert String To Upper&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;/// &amp;lt;param name=&amp;quot;inputString&amp;quot;&amp;gt;Input String&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;/// &amp;lt;returns&amp;gt;Converted String&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; ConvertStringToUpper(&lt;span &gt;string&lt;/span&gt; inputString)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; convertString = &lt;span &gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (!&lt;span &gt;string&lt;/span&gt;.IsNullOrEmpty(inputString))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; &lt;span &gt;char&lt;/span&gt;[] convertCharArray = inputString.ToCharArray();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (convertCharArray.Length &amp;gt; 0)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; &lt;span &gt;int&lt;/span&gt; count = 0;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; &lt;span &gt;foreach&lt;/span&gt; (&lt;span &gt;char&lt;/span&gt; currentChar &lt;span &gt;in&lt;/span&gt; convertCharArray)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 17: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (count % 2 == 0)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 18: &lt;/span&gt; convertString += currentChar;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 19: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 20: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 21: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 22: &lt;/span&gt; &lt;span &gt;return&lt;/span&gt; convertString;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 23: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well一般情况下.关于如何建立单元测试应用程序,一般如果没有PEX之前.可能作为开发人员更多的是根据该方法实现.创建一个新的Test测试项目.构建对应测试用例.实现对该方法的UT.其实这个过程已经Visual Studio内置了这些工作已经自动创建.只需右键点击就能看到Create Unit Test选项:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_141603" border="0" alt="2012-01-19_141603" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859121946.png" width="376" height="251" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;点击后能发现.其实Create Unit TEst为了避免测试框架和测试用例污染源代码本身.一般情况要对单元测试用例和源代码执行分离.也就是创建一个新的单独测试项目.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_141211" border="0" alt="2012-01-19_141211" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859131913.png" width="577" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;此时在执行测试之前需要做一些设置点击Settings按钮:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_141311" border="0" alt="2012-01-19_141311" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859137420.png" width="577" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;需要设置创建默认文件以及对应测试类和测试方法名称.点击ok.如果没有设置对应测试项目名称会如下提示:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_141347" border="0" alt="2012-01-19_141347" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859131531.png" width="445" height="159" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;修改完成后开始创建.创建过程可能会有如下提示:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_141420" border="0" alt="2012-01-19_141420" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859137910.png" width="566" height="264" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;创建前提示主要提到两点.需要为测试项目BasiceConsolePexComponent_Demo设置InternalsVisible属性可用.这是设置其实内在的原因是.对一个组件或模块进行单元测试时.单元测试用例需要调用定义在测试组件或模块中的Internal成员对象时. 需要跨程序集访问.而Modifier的Internal类型成员默认设置仅限于当前程序集访问.而对宿主程序而言需要暴露给测试程序集调用.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;另外一点在很多情况下，我们需要将最终的程序集以强命名的形式发布。为此，我们修改Lib项目设置，开启&amp;quot;Sign the assembly”开关，并创建一个密钥文件.不能通过编译，具体的错误信息为：“Friend assembly reference 'Test' is invalid. Strong-name signed assemblies must specify a public key in their InternalsVisibleTo declarations.”,针对需要指定的不是程序名的强命名，而是指定对程序集进行签名时采用的公钥.把公钥指定到&lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx"&gt;InternalsVisibleToAttribute&lt;/a&gt;特性中即可.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;点击ok.看一下项目结构:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_143556" border="0" alt="2012-01-19_143556" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859142337.png" width="389" height="327" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;多了一个测试项目和该项对应Program方法测试类.now构建好了测试项目.在回到宿主程序Program类中对字符串转换操作的方法见一个UT.找到该方法名右键依然可见Create Unit Test选项点击看到:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_142616" border="0" alt="2012-01-19_142616" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859142304.png" width="577" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到针对方法做UT时会把该UT的应用程序的输出默认为刚才创建的测试项目:AutomationConsole.Test.点击ok.找到测试项目下ProgramProgramTestHelper类可以看到增加一个测试方法如下：&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;///A test for ConvertStringToUpper&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;///&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; [TestMethod()]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; ConvertStringToUpperTestConvertString_Test1()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; Program target = &lt;span &gt;new&lt;/span&gt; Program(); &lt;span &gt;// TODO: Initialize to an appropriate value&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; inputString = &lt;span &gt;string&lt;/span&gt;.Empty; &lt;span &gt;// TODO: Initialize to an appropriate value&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; expected = &lt;span &gt;string&lt;/span&gt;.Empty; &lt;span &gt;// TODO: Initialize to an appropriate value&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; actual;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; actual = target.ConvertStringToUpper(inputString);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; Assert.AreEqual(expected, actual);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; Assert.Inconclusive(&lt;span &gt;&amp;quot;Verify the correctness of this test method.&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到该测试方法命名依然采用默认命名方式.方法内代码实现关于调用Program类中字符串转换大写操作的方法ConvertStringToUpper. 分别定义三个变量的字.其实从变量名称完全可以看出这是一个默认的测试用例.要想改UT达到想做.只需修改对应变量参数的值来匹配.InputString作为方法参数输入.经过测试用例会会生成对应期望值和方法执行实际值.最后通过对期望值和实际比对获得对应测试结果.直接运行 可以看到测试结果如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_144542" border="0" alt="2012-01-19_144542" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859146416.png" width="752" height="189" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well因为两个测试用例都没做了修改没有实际值传入所以都是Inconcluetive测试结果不确定.现在看看这种传统方式下一Visual Studio Unit TEst框架为主UT编写开发人员要重复做哪些工作.?首先要重复手动编写大量的UT测试用例.目的是在给定的方法中为每个执行路径手写独立测试. 而且针对这种无法避免的要创建一个独立的测试项目.其实在实际编码中.并不是所有模块都需要即时建立UT.可能需求发生变更.从开发人员角度来说创建一个笨重测试项目这意味更多精力发在测试代码维护上.可能我们更需要一种既能够创建对应测试项目同时也能即时看到当前版本Code UT效果.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Now.UT属于白盒测试的范畴.如果能够有一个很好白盒测试工具能够封装这些重复的行为.并能够重复执行UT测试用例.让开发人员从Ut的过多细节和维护中解放出来关注更核心的业务逻辑.Pex and moles就是这样的一个工具.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;2&amp;gt;Pex 构建白盒测试&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;虽然本篇幅没有核心焦点放到Pex实现原理上.但关于Pex and Moles其实分为两块整理官方原文翻译如下[直译]:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;ul&gt;&#xD;
    &lt;li&gt;&#xD;
      &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Pex&amp;#160;&amp;#160; Pex 是一个 Visual Studio 外接程序，用于补充 .NET Framework 应用程序上的单元测试。 Pex 在 Visual Studio 代码编辑器中查找对应程序方法的输入和输出值。 PEx将这些值另存为将具有高代码覆盖率的小型测试套件。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
    &lt;/li&gt;&#xD;
&#xD;
    &lt;li&gt;&#xD;
      &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;Moles&amp;#160;&amp;#160; Moles 允许开发人员将任何 .NET 方法替换为委托。 Moles 通过使用 Detour 和 Stub 提供隔离来支持单元测试。 因为 Moles 在方法级别工作，所以当目标 API 不支持它时，它提供替代项进行模拟。 SharePoint 是一个受益于隔离的常见 API 示例，但不直接支持模拟。Moles 还可用于错误植入，因为它使得开发人员在测试下向代码中注入任意行为变得轻松.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
    &lt;/li&gt;&#xD;
  &lt;/ul&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Pex核心是给开发人员一个手写的参数化单元测试，Pex完全自动地分析代码，来决定相关的测试输入。其结果就是生成一个有着高度代码覆盖的传统单元测试，另外，Pex还会建议开发人员如何去修复所发现的Bug.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;安装完Pex and Moles工具后.打开Visual Studio 可以看到右键选项中多了:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_152753" border="0" alt="2012-01-19_152753" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859148891.png" width="378" height="225" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Run Pex 和Pex 下Create Parameterized Unit Tests两个可操作选项.针对Pex测试效果.首先在Programe类添加一个字符串合并操作方法代码如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;/// Test Case Spilt String And Merge Operator&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;/// &amp;lt;param name=&amp;quot;firstname&amp;quot;&amp;gt;First Name&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;/// &amp;lt;param name=&amp;quot;lastname&amp;quot;&amp;gt;Last Name&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; &lt;span &gt;/// &amp;lt;returns&amp;gt;Merge String&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; SpiltStringToMerge(&lt;span &gt;string&lt;/span&gt; firstname, &lt;span &gt;string&lt;/span&gt; lastname)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; mergeString = &lt;span &gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; &lt;span &gt;char&lt;/span&gt;[] firstNameArray = firstname.ToCharArray();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; &lt;span &gt;char&lt;/span&gt;[] lastNameArray = lastname.ToCharArray();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; &lt;span &gt;int&lt;/span&gt; count = 0;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; &lt;span &gt;foreach&lt;/span&gt; (&lt;span &gt;char&lt;/span&gt; currentChar &lt;span &gt;in&lt;/span&gt; firstNameArray)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (count % 2 == 0)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; mergeString += currentChar + lastNameArray[count];&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 17: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 18: &lt;/span&gt; &lt;span &gt;return&lt;/span&gt; mergeString;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 19: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;注意该方法的输入参数firstname和lastname在方法内都没有判断是否空字符串或是Null而且里面涉及字符数组的操作.针对该方法采用Pex方式执行UT操作.右键调集选中Run Pex 提示如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_153430" border="0" alt="2012-01-19_153430" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859159730.png" width="466" height="189" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;注意我们当前类是在Program类下.该类的签名如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt;&lt;span &gt;class&lt;/span&gt; Program&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;提示的意思当前类型不可见.无法通过Pex方式创建UT,需要把当前类的签名改成公开 虚类型即可:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;partial&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; Program&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在来运行Run Pex 弹出执行 结果窗体如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_154740" border="0" alt="2012-01-19_154740" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859158825.png" width="644" height="184" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到Pex在没有创建一个独立单元测试项目和对应测试类情况.自动对当前方法进行白盒测试封装.运行测试109 Runs次.创建了7个测试用例. PEx会监视当前类，并且运行这个方法.执行多次测试.其中有三次测试失败的.并Sunmmary/Exception 提出具体测试参数和出现的异常信息.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;点击对应失败的测试用例.可以在右侧弹出对应异常堆栈详细信息.:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_155250" border="0" alt="2012-01-19_155250" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859157156.png" width="644" height="259" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;点击DEtails可以看到执行该测试用例的代码和对应异常信息:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_155427" border="0" alt="2012-01-19_155427" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859168202.png" width="644" height="279" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;在查看异常详情右侧窗口中.可以执行如下操作:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_155609" border="0" alt="2012-01-19_155609" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859167090.png" width="644" height="38" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Save Test保存当前PEX的测试用例为普通单元测试用例.点击保存:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_155734" border="0" alt="2012-01-19_155734" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859166185.png" width="598" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如果在此之前没有创建对应Pex测试项目会提示当前测试用例输出.或是提示创建一个新的测试项目:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-19_155905" border="0" alt="2012-01-19_155905" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859177547.png" width="644" height="215" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;上面Project Under Test是待测试的宿主项目.而下面是需要创建新的测试项目设置.点击OK创建一个新的测试项目.这里在RunPex时并没有强制开发人员强制建立一个新的测试项目.但是这里SAve 目的是在于如果觉得当前测试代码可以留存做以后回归测试.PEX也是支持测试代码保存的.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;add Precondition是用来通过Pex自动添加代码来避免错误的发生.而All Exception则允许次异常在当前应用程序中出现.send to如果你的项目采用TFS版本控制.sendto操作会吧所有信息发到文本或剪切板中.这里所有的信息包括Detail和STack Trace 如果TFS里配置WorkItem,PEX会自动发送对应的WorkItem中.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well现在既然存在异常.通过Add PreCondition来通过Pex来修正.会看到如下菜单:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_160539" border="0" alt="2012-01-19_160539" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859179466.png" width="598" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这个窗体中上半部分告诉开发人员PEX在当前会做哪些操作.操作会修改哪些方法等.下半部分则是PEX具体的添加的修复代码.可以看到对firstname输入参数因当前NullException异常所以添加了是否非Null的判断。点击Apply可以看到原来代码中添加一段判断代码 完整如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; SpiltStringToMerge(&lt;span &gt;string&lt;/span&gt; firstname, &lt;span &gt;string&lt;/span&gt; lastname)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;// &amp;lt;pex&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (firstname == (&lt;span &gt;string&lt;/span&gt;)&lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;throw&lt;/span&gt; &lt;span &gt;new&lt;/span&gt; ArgumentNullException(&lt;span &gt;&amp;quot;firstname&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; &lt;span &gt;// &amp;lt;/pex&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; mergeString = &lt;span &gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;char&lt;/span&gt;[] firstNameArray = firstname.ToCharArray();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;char&lt;/span&gt;[] lastNameArray = lastname.ToCharArray();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; &lt;span &gt;int&lt;/span&gt; count = 0;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; &lt;span &gt;foreach&lt;/span&gt; (&lt;span &gt;char&lt;/span&gt; currentChar &lt;span &gt;in&lt;/span&gt; firstNameArray)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (count % 2 == 0)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; mergeString += currentChar + lastNameArray[count];&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; &lt;span &gt;return&lt;/span&gt; mergeString;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 17: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&amp;lt;pex&amp;gt;标签之间注释就是PEX修复是添加的代码.如果觉得PEX代码不够美化.开发人员也完全可以手工修改.自此你会看到PEX帮开发人员找到一个Bug并尝试不在维护UT代码的情况下并修复该异常.&lt;/font&gt;&lt;font face="Consolas"&gt;well.当然如上演示只是PEX作为白盒测试工具的丰富功能一个特性.其实刚开始看官方给出解释最吸引我莫过于它支持写参数化单元测试[Parameterized Unit Test].方式.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;3&amp;gt;Pex参数化单元测试&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在Pex中针对白盒测试提出参数化单元测试的概念-Parameterized Unit Test。Dang我们通过PEX实现更多模块的UT操作.确保所有单个模块能够按照程序设计预期执行. 其实实际效果并非如此.PEX通过一个指令一个指令地分析.NET代码，解释代码执行时的动作，然后“以一种完全自动的方式，计算出那些能触发边角代码的相关测试输入。”&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;PEX在执行和分析代码行为时.只是得到代码最基本代码模块行为简单异常类似NullException.但是实际上开发人员并没有写过一个关于所有模块集成起来之后完整测试用例. 无法预期当前软件的行为.PEX提供参数化的单元测试提供一种强大的方式来评估当前代码在集成后是否如预期一样行为.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;找到上次增加SpiltStringToMerge字符串合并操作方法做实例.创建参数化单元测试:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_170850" border="0" alt="2012-01-19_170850" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859174449.png" width="653" height="65" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;找到该方法选中右键点击可以看到Pex-&amp;gt;Create Parameterized Unit Tests选项:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-19_171118" border="0" alt="2012-01-19_171118" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859186052.png" width="644" height="321" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如果原来没有创建对应的PEX测试项目会提示创建一个新的Test Project.与宿主程序分离.可以看到增对测试文件目标PEX增加多重过滤项. 在Test Project项目输出上如果没有创建Test Project则创建.当然针对创建的测试项目可以指定不同的测试框架.PEX中集成了NUnit/Visual Studio Unit TEst/MbUnit V系列等.让开发人员以自己最熟悉的测试框架来维护测试代码.Pex还基于&lt;a href="http://research.microsoft.com/pex/wiki/book.html#Microsoft.ExtendedReflection"&gt;扩展反射可管理子协议API&lt;/a&gt; （Extended Reflection managed profiling API）对监测应用程序的集成提供了支持.在创建看一下设置项Settings:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_171629" border="0" alt="2012-01-19_171629" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859186019.png" width="644" height="321" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以设置默认创建的命名空间和测试类下默认PexMethod测试方法.这里采用默认方式创建:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_171955" border="0" alt="2012-01-19_171955" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859186302.png" width="644" height="215" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;创建成功后Solution目录:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-19_172228" border="0" alt="2012-01-19_172228" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859196825.png" width="388" height="295" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;打开ProgramTest.cs文件可以看到这个PEX自动生成的参数化单元测试方法:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; [PexClass(&lt;span &gt;typeof&lt;/span&gt;(Program))]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; [PexAllowedExceptionFromTypeUnderTest(&lt;span &gt;typeof&lt;/span&gt;(InvalidOperationException))]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; [PexAllowedExceptionFromTypeUnderTest(&lt;span &gt;typeof&lt;/span&gt;(ArgumentException), AcceptExceptionSubtypes = &lt;span &gt;true&lt;/span&gt;)]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; [TestClass]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;partial&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; ProgramTest&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;/// &amp;lt;summary&amp;gt;Test stub for SpiltStringToMerge(String, String)&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; [PexMethod]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; SpiltStringToMerge(&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; [PexAssumeUnderTest]Program target,&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; firstname,&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; lastname&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; )&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; result = target.SpiltStringToMerge(firstname, lastname);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; &lt;span &gt;return&lt;/span&gt; result;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 17: &lt;/span&gt; &lt;span &gt;// TODO: add assertions to method ProgramTest.SpiltStringToMerge(Program, String, String)&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt; 18: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt; 19: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;其实关于PEX参数化单元测试的概念.其实它就是一个带有参数并通过调用宿主测试程序简单测试方法.其实这里很多人都很疑惑怎么和传统创建单元测试方法和PEX参数化方法区别在哪呢?其实昨天我在看到这时也很困惑很久.后来在官方找了很多资料.总算是找到一点权威的论述:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;A unit test is a method without parameters represents a test case which typically executes. a method of a class-under-test with fixed arguments and verifies that it returns the.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
  &lt;font face="Consolas"&gt;&#xD;
    &lt;p&gt;&lt;br /&gt;&lt;strong&gt;expected result. A parameterized unit test (PUT) is the straightforward generalization。of a unit test by allowing parameters. PUTs make statements about the code’s behavior.&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
    &lt;p&gt;&lt;br /&gt;&lt;strong&gt;for an entire set of possible input values, instead of just a single exemplary input value.&lt;/strong&gt;&lt;/p&gt;&#xD;
  &lt;/font&gt;&lt;/blockquote&gt;&#xD;
&lt;font face="Consolas"&gt;&#xD;
  &lt;p&gt;相对传统创建的单元测试一般情况参数都是指定固定的参数值.并在执行后会预期函数中返回对应的结果.PEX参数化单元测试概念则不同.在PEX中单元测试的参数可以输入任何可能的参数用来验证程序代码执行中所有可能的行为.你大概明白PEX提出这个概念的目的了吧.也就是说PEX在执行的时候会分析PEX参数化单元测试代码方式来查看宿主程序代码的行为.当然这个过程需要集成宿主程序的代码.而相对于传统固定参数值.PEX单元测试参数可以是任意的.这样更便于测试过程中测试宿主程序代码可能出现崩溃的几率和行为.&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;当前已经创建PEX对应的测试项目.在回到宿主横须Program类中.再次运行Run PEX:&lt;/p&gt;&#xD;
&#xD;
  &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="2012-01-19_152753" border="0" alt="2012-01-19_152753" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859197349.png" width="378" height="225" /&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;出了能看到原来Pex Test Results窗体测试结果.注意这时PEX内部根据测试需要会在测试项目对应测试ProgramTEst类中.创建普通测试方法[TestMethod]同时也会创建PEX下参数化单元测试. 创建普通测试的数量和测试结果中测试用例的数量是一致的.如果TestReaults.PEX使用7个用例那么在ProgramTest.SpiltStringToMerme.g.cs文件中肯定会有相同数量的普通测试方法存在.PEX参数化单元测试方法则放在ProgramTest.cs文件中.&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;如果你觉得这个过程不明显.或是想了解一些PEX工作处理过程.可以选中右键可以PEX-&amp;gt;Delete Generated Unit Tests操作:&lt;/p&gt;&#xD;
&#xD;
  &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="2012-01-19_182301" border="0" alt="2012-01-19_182301" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859196236.png" width="649" height="227" /&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;其实该操作的目的会自动删除ProgramTest.SpiltStringToMerme.g.cs文件中所有的普通测试方法[TestMethod]也就是当前使用测试用例.然后找到该方法在运行Run PEX./运行玩后可以找到对应测试实例的Save Test方式在把指定的测试用例保存到ProgramTest.SpiltStringToMerme.g.cs文件中.well 这里保存第一个通过的测试用例 低级Save TEst:&lt;/p&gt;&#xD;
&#xD;
  &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="2012-01-19_183133" border="0" alt="2012-01-19_183133" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859197283.png" width="598" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;Apply.完成后.会看到ProgramTest.SpiltStringToMerme.g.cs文件中多了一个普通测试方法.同时在Test Result窗体中发现每个测试的图标不再包含一个磁盘位图而是一个对号.:&lt;/p&gt;&#xD;
&#xD;
  &lt;div &gt;&#xD;
    &lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;partial&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; ProgramTestTest&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; [TestMethod]&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; [PexGeneratedBy(&lt;span &gt;typeof&lt;/span&gt;(ProgramTestTest))]&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; SpiltStringToMerge355()&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;string&lt;/span&gt; s;&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; ProgramTest s0 = &lt;span &gt;new&lt;/span&gt; ProgramTest();&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; Program s1 = &lt;span &gt;new&lt;/span&gt; Program();&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; s = &lt;span &gt;this&lt;/span&gt;.SpiltStringToMerge(s0, s1, &lt;span &gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span &gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; Assert.AreEqual&amp;lt;&lt;span &gt;string&lt;/span&gt;&amp;gt;(&lt;span &gt;&amp;quot;&amp;quot;&lt;/span&gt;, s);&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; Assert.IsNotNull((&lt;span &gt;object&lt;/span&gt;)s0);&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&#xD;
    &lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; }&lt;/pre&gt;&#xD;
  &lt;/div&gt;&#xD;
  &lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
  &lt;p&gt;这样有选择的方式让开发人员很轻松能够保存在不同版本需求变动生成的测试用例/.而且是可选择的.当然在添加过程往往会提示一些命名上问题例如如下提示:&lt;/p&gt;&#xD;
&#xD;
  &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="2012-01-19_183143" border="0" alt="2012-01-19_183143" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201191859207250.png" width="498" height="310" /&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;这是因为现在PEX现在对中文GB2312格式支持存在乱码的问题. 当然在创建是PEX为了防止访问路径过长.就限制在PEX所有文件命名长度.&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;其实到这里很多人依然对PEX 参数化单元测试的概念依然有些困惑.这个概念其实很简单.但在实际运用你会发现它的实际用途的好处.如果你熟悉并常用的单元测试.但还不理解PEX中参数化单元测试概念.可以从以下几个方向去考虑[仅作参考]：&lt;/p&gt;&#xD;
&#xD;
  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
    &lt;p&gt;&lt;strong&gt;理解参数化单元测试的方向:&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
    &lt;p&gt;&lt;strong&gt;[1]:当时你手写普通的单元测试.思考以下你要测试代码的行为.在构建单元测试时你的需要多少个独立参数传入.?&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
    &lt;p&gt;&lt;strong&gt;[2]:目前尚不清楚确切的数字可能会是什么.但在测试过程它是很重要的,因PEX角度来说开发人员永远有时间来即时创建和维护测试代码.&lt;/strong&gt;&lt;/p&gt;&#xD;
  &lt;/blockquote&gt;&#xD;
&lt;/font&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当然更多还请参考官方的资料:&lt;/font&gt;&lt;a href="http://research.microsoft.com/en-us/projects/pex/default.aspx"&gt;&lt;font face="Consolas"&gt;http://research.microsoft.com/en-us/projects/pex/default.aspx&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;4&amp;gt;Pex小结&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;本篇PEX 自身应用角度来阐述PEX相对传统单元测试所具有的特点.作为一个白盒的测试工具.开发人员常在程序开发过程中.需求往往也是不断变化的.当然也无法避免未来开发过程中.或进入代码维护阶段是.所需要面对代码修正的问题.&lt;/font&gt;&lt;font face="Consolas"&gt;为了每次都能保证软件代码工作都正确无误.而且即时在需求发生变更需要添加新功能时.也能保证原有功能正常运行.使用可控的测试导向的开发模式是必行的.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当然作为开发人员要在开发过程手工编写大量的测试用例并维护笨重测试的代码.这会在一定程度上导致项目开发进度延缓。这也是很多开发人员忽视UT一个原因之一.但现在PEX白盒测试工具.可以把测试流程完全的自动化.把开发人员从单元测试的需求中解脱出来专注于核心业务开发之上.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;本篇并没有急于在Windows phone Application 中验证PEX是否可行.但是PEX透露出来关于测试理念确实很有深入的价值.稍后会在下篇副中无论成功还是失败.演示Windows phone应用程序中使用PEX整个过程.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如有问题请在评论中提出.本篇所有源代码下载地址如下:&lt;a href="http://files.cnblogs.com/chenkai/BasicConsolePexComponent_Demo.rar"&gt;/Files/chenkai/BasicConsolePexComponent_Demo.rar&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2327580.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/19/2327580.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/13/2321722.html</id><title type="text">Git Tool Part 2</title><summary type="text">针对Git的使用.在Git中文操作指南手册中.讲解大量关于GiT的细节操作.可是对于从SVN或是TFS转换的很多开发人员来说.很多并没有更多学习周期时间.那么如何才能短时间内抓住Git核心枝干.短时间内快速进入Git并在代码中集成使用工具呢.? 由于Git中富含大量的Git 命令.细节太多.本来打算在本篇中介绍一些Git通过命令的方式基本操作.等写了大概四分之一.发现完全和最初写这篇文章初衷完全背...</summary><published>2012-01-13T07:51:00Z</published><updated>2012-01-13T07:51:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/13/2321722.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/13/2321722.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;针对Git的使用.在Git中文操作指南手册中.讲解大量关于GiT的细节操作.可是对于从SVN或是TFS转换的很多开发人员来说.很多并没有更多学习周期时间.那么如何才能短时间内抓住Git核心枝干.短时间内快速进入Git并在代码中集成使用工具呢.? &lt;/font&gt;&lt;font face="Consolas"&gt;由于Git中富含大量的Git 命令.细节太多.本来打算在本篇中介绍一些Git通过命令的方式基本操作.等写了大概四分之一.发现完全和最初写这篇文章初衷完全背离了.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实本篇的目的很简单.与其陷入在在长长的篇幅中介绍Git Command基本用法 还不如直接采用Windows 平台开发人员最熟悉的GUI界面工具操作更为直观.Git原理理论和操作用法也是非常系统.如果你觉得有必要建立一个系统知识结构.当然也有很好的资源可以当做日常查看手册:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Git 系统资源:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Git中文操作指南 Download Link[&lt;/strong&gt;&lt;/font&gt;&lt;a title="http://vdisk.weibo.com/s/1UJq4" href="http://vdisk.weibo.com/s/1UJq4"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;http://vdisk.weibo.com/s/1UJq4&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;]&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Git Command指令在线文档: [&lt;a href="http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/index.html"&gt;http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/index.html&lt;/a&gt;]&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&amp;lt;&amp;lt;Git Community Book中文版&amp;gt;&amp;gt;：[&lt;a href="http://gitbook.liuhui998.com/"&gt;http://gitbook.liuhui998.com/&lt;/a&gt;]&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;注:如上在线文档或图书版权源作者拥有.本文只是添加引用.如转载请注明出处.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;作为Windows 平台开发人员最常用的开发工具莫过于Visual Studio系列.但是可惜的Git作为从Linux平台的舶来品..NET开发人员更习惯于使用用户界面，所以在进行日常任务的时候更习惯使用操作基于具有IDE的界面.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;作为一个Visual Studio用户.在使用Visual SouceSafe/Team Foundation Server、Subversion或甚至Mercurial的过程中.已经建立了使用源码控制习惯.更多的开发人员希望在Solution解决方案目录中就直观看到自己的SouceCode被版本管理工具所控制着.无论在代码修改或添加都能直接获得状态反馈.所以在Visual Studio使用Git需求就一直成为Git一块”硬伤”.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;如何在Visual STudio系列开发工具中使用Git版本控制工具?&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;1&amp;gt;Visual Studio 构建Git部署环境&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Well，谈到这里在上章节中&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/11/2319775.html" target="_blank"&gt;Git Tool Part 1&lt;/a&gt;中提到能够适用Windows 平台的Git工具主要具有两个模拟*nix like运行环境的工具：&lt;a href="http://www.cygwin.com/"&gt;cygwin&lt;/a&gt;，&lt;a href="http://www.mingw.org/wiki/MSYS"&gt;msys&lt;/a&gt;；Git在&lt;a href="http://www.cygwin.com/"&gt;cygwin&lt;/a&gt;，&lt;a href="http://www.mingw.org/wiki/MSYS"&gt;msys&lt;/a&gt;下都有相应的移植版本.不过就使用体验来说个人觉得msys平台下的&lt;a href="http://code.google.com/p/msysgit/"&gt;msysGit&lt;/a&gt;最好用.在GUI图形工具上有Git extentions ，还是TortoiseGit.更加倾向于前者.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Linux开源社区也考虑到很多Windows平台开发人员的需求.在后来工具支持上推出可以Visual Studio系列开发工具集成Git版本控制系统 插件-&lt;a href="http://code.google.com/p/gitextensions/" target="_blank"&gt;Gitextensions&lt;/a&gt;.这是目前Visual Studio系列开发工具唯一支持Git具有GUI操作界面的插件.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;至此在Visual Studio IDE开发工具构建Git版本控制工具组合就诞生了:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Visual Stuido Git版本控制工具组合:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Git 命令行(&lt;a href="http://code.google.com/p/msysgit/" target="_blank"&gt;MsysGit&lt;/a&gt;) + &lt;a href="http://code.google.com/p/gitextensions/" target="_blank"&gt;Git Extensions&lt;/a&gt; + &lt;a href="http://visualstudiogallery.msdn.microsoft.com/63a7e40d-4d71-4fbb-a23b-d262124b8f4c" target="_blank"&gt;Git Source Control Provider&lt;/a&gt; [Only Support Visual Studio 2010]&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Git 命令行一般采用BitBash工具来直接采用命令操作.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Git Extensions：则是直接Visual Studio 开发工具中集成Git GUI操作工具.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Git Souce Control Provider:为Visual STudio 提供Git版本控制支持.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;首先安装&lt;font face="Consolas"&gt;MsysGit可以在[&lt;a title="http://code.google.com/p/msysgit/" href="http://code.google.com/p/msysgit/"&gt;http://code.google.com/p/msysgit/&lt;/a&gt;]下载到最新的FullInstall版本.安装步骤请参考GitHub上Wiki[&lt;a href="https://github.com/msysgit/msysgit/wiki/InstallMSysGit"&gt;https://github.com/msysgit/msysgit/wiki/InstallMSysGit&lt;/a&gt;].默认编辑工具是Vim/&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;因Git Extensions工具是基于Git 命令行,可以在安装MsysGit之后通过[&lt;a href="http://code.google.com/p/gitextensions/"&gt;http://code.google.com/p/gitextensions/&lt;/a&gt;]下载安装;在安装过程中因已经安装MsysGit版本[可选也可不选].所以只需选择集成KDiff3工具即可:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-12_105926" border="0" alt="2012-01-12_105926" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550342430.png" width="513" height="402" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;另外关于Git Extension传输协议 选择:&lt;/font&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="2012-01-12_110037" border="0" alt="2012-01-12_110037" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550359333.png" width="513" height="402" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;OpenSSH 客户端，提供 Git 访问 ssh 协议的版本库.Git自身支持多种协议.在此选择默认安装OpenSSH.在GitExtension安装完成后.通过Start-&amp;gt;Git Extension安装目录.打开Git Extension.找到Setting设置设置选项页Git:&lt;/font&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="2012-01-12_182007" border="0" alt="2012-01-12_182007" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550352331.png" width="644" height="476" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;一般情况如果安装顺序没有问题.安装Git Extension工具后都会自动找到对应Git命令行工具安装路径,git命令行工具有两种，一种是 cygwin 下命令行，一种是 msysGit 命令行，git extensions 可以配置使用哪一种命令行工具。因Git Extension是基于命令行操作的.在执行请检查该设置是否指向正确Git命令行安装工具路径.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;最后需要安装&lt;a href="http://visualstudiogallery.msdn.microsoft.com/63a7e40d-4d71-4fbb-a23b-d262124b8f4c" target="_blank"&gt;Git Source Control Provider&lt;/a&gt;,打开Visual STudio 2010开发工具.找到Tools-&amp;gt;Extension Manager选择Online Gallery选项页搜索:&lt;a href="http://visualstudiogallery.msdn.microsoft.com/63a7e40d-4d71-4fbb-a23b-d262124b8f4c" target="_blank"&gt;Git Source Control Provider&lt;/a&gt; 看到：&lt;/font&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="2012-01-12_110722" border="0" alt="2012-01-12_110722" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550359790.png" width="644" height="446" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;下载安装.当然也可以不用打开Visual Studio 也可以通过[&lt;a href="http://visualstudiogallery.msdn.microsoft.com/63a7e40d-4d71-4fbb-a23b-d262124b8f4c" target="_blank"&gt;Git Source Control Provider&lt;/a&gt;]地址直接下载安装即可.安装完成后找到Tools-&amp;gt;Options-&amp;gt;Souce Control选项中把Git Souce Control Provider作为默认版本控制工具:&lt;/font&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="2012-01-12_111126" border="0" alt="2012-01-12_111126" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550361152.png" width="644" height="421" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;至此在Visual Studio 2010搭建好了Git版本控制需要环境.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;2&amp;gt;Git在Visual Studio 基本操作&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;构建好Git在Visual Studio 2010开发工具版本控制.通过一个具体的Windows phone Application 来演示一下Git基本操作，首先在硬盘上开辟一个独立的文件夹CodeDevelopment：在该项目源码放在该目录下 新建解决方案如下.看看初始状态：&lt;/font&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="2012-01-12_184449" border="0" alt="2012-01-12_184449" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120113155036804.png" width="317" height="287" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在初始状态下并没有继承Git版本控制.如果在Setting目录下设置Git.可以通过右键点击文件可以看到Git操作的选项:&lt;/font&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="2012-01-12_184655" border="0" alt="2012-01-12_184655" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550367183.png" width="320" height="443" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;如要对某个项目执行Git版本控制管理.只需到此项目所在的目录创建一个仓库.也就是Git-New Repotiory操作，执行完成后能在项目目录下看到多了Git文件目录:&lt;/font&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="2012-01-12_185008" border="0" alt="2012-01-12_185008" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550379658.png" width="606" height="134" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;初始化后，在当前目录下会出现一个名为 .git 的目录，所有 Git 需要的数据和资源都存放在这个目录中。不过目前，仅仅是按照既有的结构框架初始化好了里边所有的文件和目录，但我们还没有开始跟踪管理项目中的任何一个文件.和.git同处一个目录的所有文件，现在就纳入了这个版本库的范围之内.可以在改目录下执行Git命令.也能够看到Visual STudio多了两个View窗口:&lt;/font&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="2012-01-12_110900" border="0" alt="2012-01-12_110900" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550375165.png" width="644" height="328" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;当创建完一个仓库发现解决方案的代码文件并没有类似SVN或TFS发生状态变化-即通过文件前小图标标识状态.不知道为何这可能Git Extension一个Bug.这时只有通过重启VS工具才能看到文件跟踪的状态:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-12_185737" border="0" alt="2012-01-12_185737" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550373496.png" width="346" height="256" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;well.是否可TFS和SVN体验一致.Well来看看库当前状态右键点击项目找到Git-&amp;gt;GitBesh通过Git指令:Git Status执行&lt;/font&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="2012-01-12_190147" border="0" alt="2012-01-12_190147" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550389002.png" width="681" height="256" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;这说明你现在的工作目录相当干净。换句话说，当前没有任何跟踪着的文件，也没有任何文件在上次提交后更改过。此外，上面的信息还表明，当前目录下没有出现任何处于未跟踪的新文件，否则 Git 会在这里列出来。最后，该命令还显示了当前所在的分支是 master，这是默认的分支名称.在没有进入代码修改之前.可以提交解决方案最原始的版本.通过右键点击解决方案找到Git-&amp;gt;Commit执行第一次版本提交:&lt;/font&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="2012-01-12_190505" border="0" alt="2012-01-12_190505" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550386461.png" width="229" height="312" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;执行后看到Commit页面,因现在文件都没有添加到Git暂存区.所以如果直接提交会提示：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-12_190844" border="0" alt="2012-01-12_190844" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550397508.png" width="494" height="191" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;所以在执行操作之前可以把所有文件添加到Git暂存区，添加MEssage 直接提交:&lt;/font&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="2012-01-12_190857" border="0" alt="2012-01-12_190857" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550392458.png" width="644" height="471" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;点击提交Commit按钮 提交成功:&lt;/font&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="2012-01-12_190904" border="0" alt="2012-01-12_190904" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550391869.png" width="585" height="369" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;现在在代码修改Mainpage页面PageTitle为chenkai.后再次提交.就能直接看到修改的差异:&lt;/font&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="2012-01-12_191320" border="0" alt="2012-01-12_191320" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120113155040723.png" width="644" height="471" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;关于我们创建没有做任何操作直接执行提交操作时提示. 其实是说明Git在执行提交操作必要的流程.在工作目录下面的所有文件都不外乎这两种状态：已跟踪或未跟踪。已跟踪的文件是指本来就被纳入版本控制管理的文件，在上次快照中有它们的记录，工作一段时间后，它们的状态可能是未更新，已修改或者已放入暂存区。而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照，也不在当前的暂存区域.文件在整个Git版本控制状态周期：&lt;/font&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="2012-01-12_192239" border="0" alt="2012-01-12_192239" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550415641.png" width="644" height="407" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git的暂存区是在版本未在提交之前存储位置.从上图可以看出.整个提交流程目录变化位置:工作目录-&amp;gt;暂存区-&amp;gt;版本库.暂存区的目的相当于实际编码和真正提交到Git执行版本追踪之间一个缓冲地带.这有什么好处呢.?很简单.暂存区的文件可以任意的在工作目录和版本库实现自由的交互.这样设计目的用户在操作过程可能会出错.暂存区也就给了用户撤销原来操作的可能.在文件没有进行任何操作之前一般通过Git Add指令吧文件添加到暂存区.在执行Commit操作时文件状态就有暂存区提交成为Git版本受控制的版本库中.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在Commit页面可以看到一个键便捷的操作:&lt;/font&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="2012-01-12_193018" border="0" alt="2012-01-12_193018" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120113155041624.png" width="318" height="38" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;实现从工作目录到暂存区文件批量操作.其实Stage的操作内部封装就是Git add指令.当然也可以通过AddFiles 执行这种批量操作:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-12_193647" border="0" alt="2012-01-12_193647" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550414179.png" width="227" height="177" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;当然在Git中执行提交操作依然可以跳过暂存区操作.尽管使用暂存区域的方式可以精心准备要提交的细节，但有时候这么做略显繁琐。Git 提供了一个跳过使用暂存区域的方式，只要在提交的时候，给 &lt;code&gt;git commit&lt;/code&gt; 加上 &lt;code&gt;-a&lt;/code&gt; 选项，Git 就会自动把所有已经跟踪过的文件暂存起来一并提交：这就是从工作目录-&amp;gt;版本库直接操作.可以打开命令行:&lt;/font&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="2012-01-12_193359" border="0" alt="2012-01-12_193359" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550426098.png" width="681" height="214" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;可以看到，提交后它会告诉你，当前是在哪个分支（master）提交的，本次提交的完整 SHA-1 校验和是什么（&lt;code&gt;463dc4f&lt;/code&gt;），以及在本次提交中，有多少文件修订过，多少行添改和删改过.提交成功后.看一下文件状态:&lt;/font&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="2012-01-12_193908" border="0" alt="2012-01-12_193908" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550429653.png" width="346" height="252" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;由原来的加号变锁.标识当前所有的文件已经第一次提交到版本库.如果当前再次修改MainPage.xaml则可以看到文件状态发生改变:&lt;/font&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="2012-01-13_103118" border="0" alt="2012-01-13_103118" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550421572.png" width="347" height="252" /&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="2012-01-13_103519" border="0" alt="2012-01-13_103519" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550437079.png" width="344" height="263" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;红色对勾标识当前文件已经发生了修改.而浅黄色的感叹号.标识当前文件状态由工作目录已经存放暂存区等待提交.假如我们在正常编译操作.执行多次提交.可能某一次版本提交时会出现手工操作失误.比如在这次版本提交以往提交某些文件，或是忘记修改某些文件.可能需要撤消刚才所做的某些操作,请注意，有些操作并不总是可以撤消的，所以请务必谨慎小心，一旦失误，就有可能丢失部分工作成果。可以使用 &lt;code&gt;--amend&lt;/code&gt; 选项重新提交.:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;$ git commit --amend&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动，直接运行此命令的话，相当于有机会重新编辑提交说明，而所提交的文件快照和之前的一样,如果刚才提交时忘了暂存某些修改，可以先补上暂存操作，然后再运行 &lt;code&gt;--amend&lt;/code&gt; 提交:&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;$ git commit -m &lt;span &gt;'initial commit'&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;$ git add forgotten_file&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;$ git commit --amend &lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;ok.现在修改MainPage.xaml。在把这个文件追加上一个版本中添加Add Files操作后执行Git命令如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_104539" border="0" alt="2012-01-13_104539" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550436489.png" width="681" height="214" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well顺利提交.有时我们通过Git Extension集成的命令通过Add Files 方式把当前所有工作的目录的文件添加到暂存区.也就是添加Git版本跟踪. 可能为了减轻操作的负担.对于有些应用程序编译中自动生成的文件.类似日志.或编译的文件并不需要Git版本管理.需要把这些文件从暂存区剔除掉.取消暂存区文件.可以执行如下Git命令:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt; git reset HEAD &amp;lt;file文件名称&amp;gt;...&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在我们执行提交多次可以Git Extension中查看提交的版本.当然也可以通过命令Git Log方式查看同样的效果:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_105536" border="0" alt="2012-01-13_105536" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550441407.png" width="644" height="420" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到最后一次提交版本Message.总共提交三次版本.当然也可以在Git History看到图形化的提交历史版本:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_105915" border="0" alt="2012-01-13_105915" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550443325.png" width="644" height="254" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当我们修改完成之后.在编辑过程达到一个满意的过程.,git 是分布式版本系统，都有一个 git 版本库的拷贝，为了和远程其他版本库同步，需要进行同步操作.同步操作一般分为拉取pull.另外一个推送Push.针对Git的服务器.如果比较大的组织结构可以企业内部构建自己的Git服务器.如果是小型团队.完全没有必要这么麻烦.现在依然很好第三方托管服务类似GitHub. &lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先需要建立一个&lt;a href="https://github.com/" target="_blank"&gt;GitHub&lt;/a&gt;账号.就不多说了打开后能看到操作流程如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_112735" border="0" alt="2012-01-13_112735" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550453816.png" width="644" height="273" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;因已经配置过Git环境.所以直接创建一个Create Repository：&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-13_113014" border="0" alt="2012-01-13_113014" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550454306.png" width="644" height="448" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;填写项目名称.描述和HomePage是可选项.当然最关键是可以设置GitHub托管的项目是否公开或私密状态.创建库Repository完成可以看到具体操作Git指令的流程如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-13_113405" border="0" alt="2012-01-13_113405" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550462288.png" width="644" height="397" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先需要见车Git Bash是否设置对应的全局的用户名和Email:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_113512" border="0" alt="2012-01-13_113512" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550467554.png" width="644" height="476" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;设置完成后需要在GitHub针对托管的项目添加一个公钥，如果没有公钥则可以通过Bit Extension工具自动生成一个匹配的公钥和私钥文件并保存在本地,带卡Bit Extension 找到：&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_113633" border="0" alt="2012-01-13_113633" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550478045.png" width="644" height="420" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;打开操作General 生成一对公私密钥,并保存本地硬盘目录中:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_113814" border="0" alt="2012-01-13_113814" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550472123.png" width="500" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;保存上面的公钥字符串和公钥key&lt;/font&gt;&lt;a href="http://www.haogongju.net/tag/%E6%96%87%E4%BB%B6"&gt;&lt;font face="Consolas"&gt;文件&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;为public文件，密钥为private.ppk文件.保存完成后需要到GitHub控制面版页面把该公钥添加上去:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_114110" border="0" alt="2012-01-13_114110" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120113155048977.png" width="644" height="299" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;添加成功后.在指令操作流程页面就可以GitHub对外公开该项目访问路径:git@github.com:chenkai/GitBaseOperator_Demo.git,对于Github上对外访问路径格式一般是：一般是 &lt;strong&gt;git@github.com:yourName/yourProject.git &lt;/strong&gt;格式. 这时我们可以把已经修改的应用程序通过Visual Studio 中Git Push到GitHub上:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_141814" border="0" alt="2012-01-13_141814" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550489865.png" width="226" height="168" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这时会提示一个窗体:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_115335" border="0" alt="2012-01-13_115335" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550485371.png" width="644" height="326" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;首先点击Manage添加默认的添加项目信息. 找到 Default Pull:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_115245" border="0" alt="2012-01-13_115245" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550498370.png" width="644" height="314" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;添加远程的Github项目信息.并save，在选择Remote REspositories设置对应项目Reposity的基本信息并Save:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_115156" border="0" alt="2012-01-13_115156" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550491369.png" width="644" height="314" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;关闭窗体回到Push主页面就会看到对应默认项目是BitBaseOperator_Demo.ok此时点击Push开始推送代码到Github上:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_115402" border="0" alt="2012-01-13_115402" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550508827.png" width="644" height="326" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;确定.在调用Git.Exe是需要允许其对外访问输入yes:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_115438" border="0" alt="2012-01-13_115438" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550501826.png" width="644" height="199" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;开始推送 如果提示出错类似如下:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_140050" border="0" alt="2012-01-13_140050" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550517092.png" width="644" height="406" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;提示当前权限不允许操作.远程连接中断.好吧这个问题折腾我好久.后来在官方社区看到解决方法.其实这主要是GitBash通过cmd命令进入命令行输入界面的。正确的操作是，在git附带的bash（GitBash可以在开始菜单的git目标里面找到）里面运行命令，就可以一切正常。当然如果觉得这种界面操作麻烦也可以根据官方给出的纯指令的方式操作吧代码Push到GitHub上操作流程如下或是参加如下小白解决方案[&lt;a href="http://help.github.com/win-set-up-git/"&gt;ttp://help.github.com/win-set-up-git/&lt;/a&gt;]:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;github的&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://help.github.com/linux-set-up-git/"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;官方文档&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;#1. Check for SSH keys.&#xD;
$ cd ~/.ssh&#xD;
#2. Backup and remove existing SSH keys.&#xD;
$ lsLists all the subdirectories in the current directory&#xD;
$ mkdir key_backupmakes a subdirectory called &amp;quot;key_backup&amp;quot; in the current directory&#xD;
$ cp id_rsa* key_backupCopies the contents of the id_rsa directory into key_backup&#xD;
$ rm id_rsa*&#xD;
#3. Generate a new SSH key.&#xD;
$ ssh-keygen -t rsa -C &amp;quot;your_email@youremail.com&amp;quot;&#xD;
#4. Add your SSH key to GitHub.&#xD;
#5. Test everything out.&#xD;
$ ssh -T &lt;/strong&gt;&lt;/font&gt;&lt;a href="mailto:git@github.com"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;git@github.com&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/pre&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;Git Bash中执行push令如下:&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;pre&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Push指令：&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;$ git remote add origin git@github.com:testinguser/yourproj.git&#xD;
$ git push origin master&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;font face="Consolas"&gt;&amp;#160;&lt;/font&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;font face="Consolas"&gt;在实际操作还有另外一种情况.也会导致这种情况出错.出错的原因是因为公私密钥保存位置不在默认目录下.导致在Push时提示需要提示提供公钥.&lt;/font&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;font face="Consolas"&gt;所以在并不推荐使用工具的方式生成密钥，如果要保存最好不要自定义保存目录:&lt;/font&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&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="2012-01-13_113901" border="0" alt="2012-01-13_113901" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550512010.png" width="500" height="484" /&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&gt;&amp;#160;&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;font face="Consolas"&gt;当然最好的方式就是官方给出通过Bit Bash指令工具自动生成.操作流程如下:&lt;/font&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&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="2012-01-13_151707" border="0" alt="2012-01-13_151707" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550521105.png" width="681" height="438" /&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先通过自己的电子邮件生成对应的公私密钥.保存和存储指令一律采用默认为空的方式保存默认目录下.注意这个默认目录在User创建成功可以通过如下指令测试是否连接GitHub成功&amp;quot;：&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;ssh -T git@github.com&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;测试成功成功后.在来通过Visual STudio 中Git集成Push到GitHub上:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_151135" border="0" alt="2012-01-13_151135" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550523023.png" width="585" height="369" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;you see Push成功.GitHub也能看到对应目录和Code.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.当我们通过GitHub首先第三方代理时.通过和其他开发人员或第三方团队时很方便.随时随地就可以把代码Commit或是Pull一个版本，这样分布式结构完全体现Git的威力.ok加入Team另外一个成员修改Github上源码并Commit一个完整版本.现在Pull下来一个最新SouceCode.在Visual Studio中：执行Pull:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_153213" border="0" alt="2012-01-13_153213" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550536894.png" width="644" height="346" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;分支选择以主干Master. 合并策略Merge默认以GitHub SouceCode为基准覆盖本地.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_153231" border="0" alt="2012-01-13_153231" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550534037.png" width="585" height="369" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Pull 成功.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如果在GitHub看到不错的项目可以通过本地找到指定目录Clone本地:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-13_153918" border="0" alt="2012-01-13_153918" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131550538464.png" width="274" height="309" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Clone操作执行本地源码:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2012-01-13_162502" border="0" alt="2012-01-13_162502" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201131629068593.png" width="517" height="349" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;…&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Git操作的细节太多了. 我这个短短的篇幅中是无法写完的.只能列举一些在Visual Studio最基本的应用.展示一下Git作为版本控制工具强项.权当抛砖引玉.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;3&amp;gt;Git小结&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Git作为很好的分布式的版本控制工具.在版本控制能够优雅实现多种类型模式和Team的协作模式.机动灵活处理了版本控制各种问题.当然这篇文章我写了两天.主要是要重现Git大量细节操作太费时费力了.写的很累.篇幅毕竟有限.不能全面覆盖.只能抛砖引玉.对于Windows平台的用户来 这种分布式控制版本控制工具.与强大Visual Studio集成.对Windows 平台开发人员和日常团队管理来说也是”福音”,极力推荐.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以参考上篇:&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/11/2319775.html"&gt;Git Tool Part 1&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2321722.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/13/2321722.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/11/2319775.html</id><title type="text">Git Tool Part 1</title><summary type="text">最近来了一些newguys，版本控制工具全部开始迁移到Git上来.原来都是老CVS或SVN的用户. 所以打算把内部Wiki上比较两篇粗糙Git的入门文章操作重写一遍.在本篇中全面解析git概念和基础使用方法. 在写的这篇文章时.在思考.应该如何快速切入理解Git的基本使用?相对Linux操作系统下分布式版本控制工具.很多操作中都直接采用命令的方式来做.可更多Windows 开发人员习惯的是直观的用户操作界面.复杂的指令是Git在Linux本身具有的特点.而Windows 上UI不足也可以使用工具加以弥补.图形化工具(无论是 git extentions ，还是TortoiseGit)，都只不.</summary><published>2012-01-11T10:06:00Z</published><updated>2012-01-11T10:06:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/11/2319775.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/11/2319775.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;最近来了一些newguys，版本控制工具全部开始迁移到Git上来.原来都是老CVS或SVN的用户. 所以打算把内部Wiki上比较两篇粗糙Git的入门文章操作重写一遍.在本篇中全面解析git概念和基础使用方法.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在写的这篇文章时.在思考.应该如何快速切入理解Git的基本使用?相对Linux操作系统下分布式版本控制工具.很多操作中都直接采用命令的方式来做.可更多Windows 开发人员习惯的是直观的用户操作界面.复杂的指令是Git在Linux本身具有的特点.而Windows 上UI不足也可以使用工具加以弥补.图形化工具(无论是 git extentions ，还是TortoiseGit)，都只不过是命令行的封装。就功能而言，命令行全部可以做到;但命令行能做的，他们不一定可以做到。命令行更加原生、本色，跨越平台之间局限.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;so。本篇就以git 命令行操作方式逐步切入.至于一些图形化工具会在下篇讲到.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;1&amp;gt;Git基础概念&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git&amp;#8212;The Stupid Content Tracker-俗称傻瓜内容跟踪器.Linus Benedict Torvalds-Linus之父在官方的Wiki中自嘲的取了这个名字.官方给出解释如下:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;I'm an egotistical bastard, and I name all my projects after myself. First &lt;/strong&gt;&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/wiki/Linux"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;, now git.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git最初是用于Linux内核开发的一个版本控制工具.从2002年起，Linux 内核一直使用&lt;a href="http://www.bitkeeper.com/"&gt;BitKeeper&lt;/a&gt;来进行版本管理，但是在2005年BitKeeper和Linux 内核开源社区的合作关系结束，BitKeeper再也不能免费使用了，这迫使Linus决定开发一个开源界自已的版本控制系统.与常用的版本控制CVS、Subversion等均不同.它采用分布式的版本库控制方式.相对于CVS或SVN. Git并不需要服务器端软件的支持.Git的速度很快.它的本地操作速度和本地文件系统在一个级别，远程仓库的操作速度和SFTP文件传输在一个级别.至于如何实现的可以看看Git内部实现机制.&lt;strong&gt;&lt;a href="http://www.advogato.org/person/apenwarr/diary/371.html" target="_blank"&gt;Git is the next Unix&lt;/a&gt;.&lt;/strong&gt;这对于诸如 Linux kernel 这样的大项目来说自然很重要。 Git 最为出色的是它的合并跟踪[merge tracing]能力.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git最初的开发动力来自于&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/wiki/BitKeeper"&gt;&lt;font face="Consolas"&gt;BitKeeper&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;和&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/wiki/Monotone_(%E8%BB%9F%E9%AB%94)"&gt;&lt;font face="Consolas"&gt;Monotone&lt;/font&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href="http://zh.wikipedia.org/wiki/Git#cite_note-1"&gt;&lt;font face="Consolas"&gt;[2]&lt;/font&gt;&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;&lt;a href="http://zh.wikipedia.org/wiki/Git#cite_note-2"&gt;&lt;font face="Consolas"&gt;[3]&lt;/font&gt;&lt;/a&gt;&lt;/sup&gt;&lt;font face="Consolas"&gt;。 Git最初只是作为一个可以被其他前端比如&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/w/index.php?title=Cogito_(software)&amp;amp;action=edit&amp;amp;redlink=1"&gt;&lt;font face="Consolas"&gt;Cogito&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; 或 &lt;/font&gt;&lt;a href="http://zh.wikipedia.org/w/index.php?title=StGIT&amp;amp;action=edit&amp;amp;redlink=1"&gt;&lt;font face="Consolas"&gt;StGIT&lt;/font&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href="http://zh.wikipedia.org/wiki/Git#cite_note-3"&gt;&lt;font face="Consolas"&gt;[4]&lt;/font&gt;&lt;/a&gt;&lt;/sup&gt;&lt;font face="Consolas"&gt;包装的后端而开发的。不过，后来Git内核已经成熟到可以独立地用作版本控制&lt;sup&gt;&lt;a href="http://zh.wikipedia.org/wiki/Git#cite_note-4"&gt;[5]&lt;/a&gt;&lt;/sup&gt;。很多有名的软件都使用Git来进行版本控制&lt;sup&gt;&lt;a href="http://zh.wikipedia.org/wiki/Git#cite_note-5"&gt;[6]&lt;/a&gt;&lt;/sup&gt;，其中有&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/wiki/Linux%E5%86%85%E6%A0%B8"&gt;&lt;font face="Consolas"&gt;Linux内核&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;、&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/wiki/X.Org%E6%9C%8D%E5%8A%A1%E5%99%A8"&gt;&lt;font face="Consolas"&gt;X.Org服务器&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;和&lt;/font&gt;&lt;a href="http://zh.wikipedia.org/wiki/OLPC"&gt;&lt;font face="Consolas"&gt;OLPC&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;内核开发.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;2&amp;gt;Git基础使用&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实如果你是一个原来使用过CVS到SVN.或是也经历从VSS迁移到TFS.你会发现版本控制管理模式从集中向分散演变.这也是因为现在的很多开发团队变得越来越分散，原来微软的Visual SourceSafe和Team Foundation Server这样的集中式源代码控制系统很难保持其吸引力.而Git作为分布式版本控制工具.逐渐在.NET 社区开始广泛使用.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;了解Git一些基础概念.如下篇幅来了解Git在实际项目中使用.在使用Git之前需要安装对应Git工具.相对于Windows 平台.可选安装软件有两个:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Windows 安装工具:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Windows平台有两个模拟*nix like运行环境的工具：&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://www.cygwin.com/"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;cygwin&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;，&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://www.mingw.org/wiki/MSYS"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;msys&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;；Git在&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://www.cygwin.com/"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;cygwin&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;，&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://www.mingw.org/wiki/MSYS"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;msys&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;下都有相应的移植版本.工具下载：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;TortoiseGit-[&lt;a href="http://code.google.com/p/tortoisegit/downloads/list"&gt;http://code.google.com/p/tortoisegit/downloads/list&lt;/a&gt;]&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Msysgit-[&lt;a href="http://code.google.com/p/msysgit/downloads/list"&gt;http://code.google.com/p/msysgit/downloads/list&lt;/a&gt;]&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;注:前者是与Windows 资源管理器整合的Git管理工具.后者是Git的功能软件.个人觉得msys平台下的&lt;a href="http://code.google.com/p/msysgit/"&gt;msysGit&lt;/a&gt;最好用.推荐使用.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;本篇Git操作演示均采用MsysGit工具.安装过程没什么可提的.在设置Git Setup时:&lt;/font&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="2012-01-10_175618" border="0" alt="2012-01-10_175618" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805519519.png" width="517" height="402" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;由于windows平台的换行符（CRLF）和Linux(*nix)平台的换行符（LF）不同，那么在windows下开发最好选&amp;#8220;Checkout as-is, commit as-is&amp;#8221;这个选项，这样，Git就不会修改你代码的换行符风格。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;安装完成后需要配置Git.在Linux下，可以在命令行里直接使用&lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-config.html"&gt;git config&lt;/a&gt;进行配置, 而在windows下则要先打开&amp;#8220;Git Bash&amp;#8221;，进入msysGit命令行界面，再用&lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-config.html"&gt;git config&lt;/a&gt;命令进行相应的配置操作.打开Git Bash.首先需要配置的UserName用户名和Email.这回在每次Git操作日志出现:&lt;/font&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="2012-01-11_113017" border="0" alt="2012-01-11_113017" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805526978.png" width="681" height="242" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git的配置信息分为全局和项目两种，上面命令中带了&amp;#8220;--global"参数，这就意味是在进行全局配置，它会影响本机上的每个一个Git项目.为了演示目的这里首先建立一个用来测试操作的仓库,首先在默认路径下创建一个仓库目录.并在该目录下创建一个仓库:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-11_114044" border="0" alt="2012-01-11_114044" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805528896.png" width="681" height="242" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;mkDir创建一个测试仓库目录demogitdir，Cd 则是进入该目录. git init 指令在当前目录下创建一个测试操作的仓库.有了可操作的仓库.可以添加一个任意内容的文件到仓库并提交:&lt;/font&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="2012-01-11_114758" border="0" alt="2012-01-11_114758" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120111180552815.png" width="681" height="284" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;echo 则是把&amp;#8221;hello git tool&amp;#8221;内容写入到sayhello.txt文件中. git add则是把该文件添加暂存区. 通过git commit指令则提交到默认的当前的仓库中.可以通过Git Log查看当前的提交记录.也可以在记录中看到Git设置的用户名和Email.:&lt;/font&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="2012-01-11_115246" border="0" alt="2012-01-11_115246" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805535766.png" width="681" height="214" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在log能看到Commit 后根据一段&amp;#8220;8223db3b064a9826375041c8fea020cb2e3b17d1&amp;#8221; SHA1串.Git通过对提交内容进行 SHA1 Hash运算，得到它们的SHA1串值，作为每个提交的唯一标识。根据一般的密码学原理来说，如果两个提交的内容不相同，那么它们的名字就不会相同；反之，如果它们的名字相同，就意味着它们的内容也相同.现在修改一下刚创建的文件内容 并提交到仓库中,在来查看该文件与第一个保存版本之间存在的不同:&lt;/font&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="2012-01-11_135940" border="0" alt="2012-01-11_135940" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120111180554683.png" width="681" height="256" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在原来基础上添加字符串chenkai modify.这时可以提交并查看当前git 状态和日志.有具体的库.在回过头看看GitConfig具体的配置.在Git bash中可以通过cat /Head指令获取当前库GitConfig中配置 比如获取刚才设置用户名和Email:&lt;/font&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="2012-01-11_141150" border="0" alt="2012-01-11_141150" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805549778.png" width="681" height="228" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;很多刚操作对git config配置不熟悉.可以直接找到对应根目录下GitConfig文件直接修改也可以达到同样的效果.当然也可以通过git config &amp;#8211;list获取全部配置信息.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;通过如上Git 一些指令操作是即使你不了解Git原理前提下 是否有了一个感性的认识.如下来挖掘Git设计原则和工作原理.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;3&amp;gt;Git演变历程&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实要理解Git这个版本控制工具由来过程.以及演变到今天具有分布式特点.从版本控制最原始角度来分析.它突显特点最容易理解的角度.开发人员最容易在使用工具往往注重学会它如何去使用 而忽略这些建立功能背后所解决问题.如果我们能够从Git本身设计原则上看到解决问题.就自然会理解Git版本工具优势特点在哪里.才不会在使用过程纯粹为了使用Git而学习.同样要在使用过程中理解其演变过程.知其所以然.用起来才能游刃有余.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;什么版本控制?&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;版本控制是一种记录若干文件内容变化，以便将来查阅特定版本修订情况的系统&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;严格意义来说版本控制文件可以是任何文本文件.而我们突出是对源代码文本文件版本控制管理.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在最原始版本控制中.习惯用复制整个项目目录的方式来保存不同的版本，或许还会改名加上备份时间以示区别.这样的方式很简单.但存在问题也不少.&lt;strong&gt;容易混淆工作目录.版本之间没有交互实现版本指教差异跟踪等&lt;/strong&gt;.未解决这个问题在最开始设计多种本地版本控制系统，大多都是采用某种简单的数据库来记录文件的历次更新差异,具体构成:&lt;/font&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="18333fig0101-tn" border="0" alt="18333fig0101-tn" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805543649.png" width="404" height="340" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;最流行的一种叫做 &lt;strong&gt;rcs&lt;/strong&gt;，现今许多计算机系统上都还看得到它的踪影。甚至在流行的 Mac OS X 系统上安装了开发者工具包之后，也可以使用 rcs 命令。它的工作原理基本上就是保存并管理文件补丁（patch）。文件补丁是一种特定格式的文本文件，记录着对应文件修订前后的内容变化。所以，根据每次修订后的补丁，rcs 可以通过不断打补丁，计算出各个版本的文件内容。这个特点甚至影响后来的CVS和SVN设计.现在依然能够在SVN中看到，版本之间需要作出补丁包.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;虽然解决了能够通过数据控制版本之间变化.但在实际操作又要面对新问题-&lt;strong&gt;如何让在不同系统上的开发者协同工作&lt;/strong&gt;？于是，&lt;strong&gt;集中化的版本控制系统（ Centralized Version Control Systems，简称 CVCS&lt;/strong&gt; ）应运而生。这类系统，诸如 CVS，Subversion 以及 Perforce 等，都有一个单一的集中管理的服务器，保存所有文件的修订版本，而协同工作的人们都通过客户端连到这台服务器，取出最新的文件或者提交更新。多年以来，这已成为版本控制系统的标准做法，结构成图:&lt;/font&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="2012-01-11_154244" border="0" alt="2012-01-11_154244" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805554663.png" width="526" height="409" /&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;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;相较于老式的本地 VCS 来说。现在，每个人都可以一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限，并且管理一个 CVCS 要远比在各个客户端上维护本地数据库轻松容易得多&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;坏处以及遗留难以处理的问题是:&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;最显而易见的缺点是中央服务器的单点故障。若是宕机一小时，那么在这一小时内，谁都无法提交更新，也就无法协同工作。如果中央服务器的磁盘发生故障，并且没做过备份或者备份得不够及时的话，还会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录，被客户端提取出来的某些快照数据除外，但这样的话依然是个问题，你不能保证所有的数据都已经有人提取出来。本地版本控制系统也存在类似问题，只要整个项目的历史记录被保存在单一位置，就有丢失所有历史更新信息的风险.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;well.新的需求出现总是不断推动新的工具推出.紧接着.为了解决集中化版本控制中存在种种问题.同时继承原有的特点.&lt;strong&gt;分布式版本控制系统（ Distributed Version Control System，简称 DVCS&lt;/strong&gt; ）面世了。在这类系统中，诸如 Git，Mercurial，Bazaar 还有 Darcs 等，客户端并不只提取最新版本的文件快照，而是把原始的代码仓库完整地镜像下来。这么一来，任何一处协同工作用的服务器发生故障，事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的提取操作，实际上都是一次对代码仓库的完整备份,结构分析截图:&lt;/font&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="2012-01-11_155222" border="0" alt="2012-01-11_155222" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805556025.png" width="429" height="484" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;well 有了Git这种分布式工具.许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此，你就可以在同一个项目中，分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程，比方说层次模型式的工作流，这在以前的集中式系统中是无法实现的.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;从05开始其Linux开源社区为了不重蹈覆辙.决定基于Linux操作系统开发一个新版版本控制工具.就是我们今天见到的Git.当时开发团队对Git工具 设计目标作了如下的设想:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Git 设计目标:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;速度 &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;      &lt;li&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;简单的设计 &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;      &lt;li&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;对非线性开发模式的强力支持（允许上千个并行开发的分支） &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;      &lt;li&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;完全分布式 &lt;/strong&gt;&lt;/font&gt;&lt;/li&gt;      &lt;li&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;有能力高效管理类似 Linux 内核一样的超大规模项目（速度和数据量）]&lt;/strong&gt;&lt;/font&gt; &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;从05年至今.经过Linux开源社区推动.Git逐渐成熟.同时对演变对其他Windows MAC平台支持.&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;4&amp;gt;Git构建原理&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实很多人从CVS或是SVN过渡而来的用户,在使用指令操作方式依然能够粗类旁通.其实在原理层次2者之间并无可比性.反而从SVN过来而来用户在理解总是存在一个对比的概念.Git 和其他版本控制系统的主要差别在于，Git 只关心文件数据的整体是否发生变化，而大多数其他系统则只关心文件内容的具体差异。这类系统（CVS，Subversion，Perforce，Bazaar 等等）每次记录有哪些文件作了更新，以及都更新了哪些行的什么内容,构图吐下:&lt;/font&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="2012-01-11_171739" border="0" alt="2012-01-11_171739" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805567072.png" width="784" height="349" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;而Git在对基本文件操作完全不同.Git 并不保存这些前后变化的差异数据。实际上，Git 更像是把变化的文件作快照后，记录在一个微型的文件系统中。每次提交更新时，它会纵览一遍所有文件的指纹信息并对文件作一快照，然后保存一个指向这次快照的索引。为提高性能，若文件没有变化，Git 不会再次保存，而只对上次保存的快照作一连接。Git 的工作方式如下:&lt;/font&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="2012-01-11_171847" border="0" alt="2012-01-11_171847" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120111180557843.png" width="789" height="349" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;这是 Git 同其他系统的重要区别。它完全颠覆了传统版本控制的套路，并对各个环节的实现方式作了新的设计。Git 更像是个小型的文件系统，但它同时还提供了许多以此为基础的超强工具，而不只是一个简单的 VCS.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;因Git在底层的设计.本身具有的操作特点也不同于其他版本控制工具.具体表现如下几点.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;A：所有操作几乎在本地运行&lt;/strong&gt;.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git 中的绝大多数操作都只需要访问本地文件和资源，不用连网。但如果用 CVCS 的话，差不多所有操作都需要连接网络。因为 Git 在本地磁盘上就保存着所有有关当前项目的历史更新，所以这也就不难解释Git的处理起来速度飞快特点.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git这点能让开发人员.在大的项目结构下.随时随地在不用连接服务器的情况下查看版本之间差异.而不是采用SVN的方式通过请求服务器端运算获取差异.引文每次版本更新都能够拿到本地存在最新代码的快照.以后所有的操作都可以基于本地的Code进行.而无需请求服务器端.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;这样一来可以让开发人员随意修改本地的Code.在存在网络的情况时通过Push操作吧更改上传远程的镜像上.换作其他版本控制系统，这么做几乎不可能，抑或非常麻烦,例如：Subversion 或 CVS，虽然可以编辑文件，但无法提交更新，因为数据库在网络上.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;B：时刻保持数据完整性&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在保存到 Git 之前，所有数据都要进行内容的校验和（checksum）计算，并将此结果作为数据的唯一标识和索引。换句话说，不可能在你修改了文件或目录之后，Git 一无所知。这项特性作为 Git 的设计哲学，建在整体架构的最底层。所以如果文件在传输时变得不完整，或者磁盘损坏导致文件数据缺失，Git 都能立即察觉.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Git 使用 SHA-1 算法计算数据的校验和，通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值，作为指纹字符串。该字串由 40 个十六进制字符（0-9 及 a-f）组成，看起来就像是:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;24b9da6552252987aa493b52f8696cd6d3b00373&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Git 的工作完全依赖于这类指纹字串，所以你会经常看到这样的哈希值。实际上，所有保存在 Git 数据库中的东西都是用此哈希值来作索引的，而不是靠文件名&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;C：多数操作仅仅添加数据&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作，比如删除数据，要回退或重现都会非常困难。在别的 VCS 中，若还未提交更新，就有可能丢失或者混淆一些修改的内容，但在 Git 里，一旦提交快照之后就完全不用担心丢失数据，特别是在养成了定期推送至其他镜像仓库的习惯的话。&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这种高可靠性令我们的开发工作安心不少，尽管去做各种试验性的尝试好了，再怎样也不会弄丢数据.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;D：Git文件中三种状态&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来要讲的概念非常重要。对于任何一个文件，在 Git 内都只有三种状态：已提交（committed），已修改（modified）和已暂存（staged）。已提交表示该文件已经被安全地保存在本地数据库中了；已修改表示修改了某个文件，但还没有提交保存；已暂存表示把已修改的文件放在下次提交时要保存的清单中。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;由此我们看到 Git 管理项目时，文件流转的三个工作区域：Git 的工作目录,暂存区域,以及本地数据目录:&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-11_174211" border="0" alt="2012-01-11_174211" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201111805584714.png" width="531" height="484" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;每个项目都有一个 git 目录，它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要，每次克隆镜像仓库的时候，实际拷贝的就是这个目录里面的数据。&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;从项目中取出某个版本的所有文件和目录，用以开始后续工作的叫做工作目录。这些文件实际上都是从 git 目录中的压缩对象数据库中提取出来的，接下来就可以在工作目录中对这些文件进行编辑。&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;所谓的暂存区域只不过是个简单的文件，一般都放在 git 目录中。有时候人们会把这个文件叫做索引文件，不过标准说法还是叫暂存区域。&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;基本的 Git 工作流程如下所示：&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;ol&gt;&#xD;
  &lt;li&gt;&lt;font face="Consolas"&gt;在工作目录中修改某些文件。 &lt;/font&gt;&lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;font face="Consolas"&gt;对这些修改了的文件作快照，并保存到暂存区域。 &lt;/font&gt;&lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;font face="Consolas"&gt;提交更新，将保存在暂存区域的文件快照转储到 git 目录中。&lt;/font&gt; &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;所以，我们可以从文件所处的位置来判断状态：如果是 git 目录中保存着的特定版本文件，就属于已提交状态；如果作了修改并已放入暂存区域，就属于已暂存状态；如果自上次取出后，作了修改但还没有放到暂存区域，就是已修改状态.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;其实如上三种装当你在每次从创建文件到提交文件整个过程.一旦执行一条命令都可以通过Git Status来查看当前文件的状态.就能够很清晰扑捉到一个文件从创建到提交过程在Git版本状态的变化过程.我就不在此演示了.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;5&amp;gt;Git基础概念小结&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;着重写本篇主要目的是为了在使用Git解惑.清楚了解Git之前整个版本管理工具演化过程.以及相对其他版本工具Git自身具有的特点.和工作原理.重要性不言而喻. 就像很多开发人员强迫自己学习GOF 23种模式一样.大多的人只是关注如何快速熟练的使用GOF每种模式.力求使用能够精通.我们愿景是能够遇到问题时能够采用前人经验去解决.可惜是现实中使用效果总是与我们设想效果差很远.原因很简单.很多开发人员学习玩GoF 23模式后在碰到问题往往反而更迷茫了.因为他不知道采用哪种模式来解决问题最简单.或是换句话我们只是知道 了解 并熟练掌握GOF模式使用而忽略GOF模式本身的价值.具体解决什么样问题. 适用在什么问题场景最合适?这是否对学习对强迫自己学习GOF的同学是一种悲哀呢/.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;学习GIT也是如此.不要陷入细节的海洋无法自拔.在处理问题上.多一点全局的观念.往往能够带来更多思考.至少我们能确定做事方向和路线是对的.有些开发人员往往从事行业多年.却对很多专业技术都是略知.说白在建立自身知识系统完整性缺乏. 这也是产生所谓行业多了很多&amp;#8221;IT民工&amp;#8221;角色 而少了真正的创新原因之一.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这种现象是否值得我们去反思这种问题的现状呢?&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2319775.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/11/2319775.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/10/2318221.html</id><title type="text">Windows phone 应用开发[10]-自动化测试</title><summary type="text">本篇承接上篇Windows phone 应用开发[9]-单元测试,当在Unit TEst 确定了测试用例的方案.在单个模块单元测试通过开始走模块之间集成时.其实很多测试工作就可以开发人员手中开始向测试人员转移.类似针对单个模块，测试团队可以根据已经确定测试用例批量执行.得到实际结果与期望结果进行比较.而这个过程测试执行者无需了解代码如何执行.也就是俗称黑盒测试. 而对于单个模块的回归测试而言.为了提高效率引入自动化测试的概念.可惜的是目前并没有任何可用于Windows phone Application应用程序的自动化测试工具.曾在Silverlight中使用过自动化测试工具-Ranorex.</summary><published>2012-01-10T07:51:00Z</published><updated>2012-01-10T07:51:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/10/2318221.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/10/2318221.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;本篇承接上篇&lt;/font&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html"&gt;&lt;font face="Consolas"&gt;Windows phone 应用开发[9]-单元测试&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;,当在Unit TEst 确定了测试用例的方案.在单个模块单元测试通过开始走模块之间集成时.其实很多测试工作就可以开发人员手中开始向测试人员转移.类似针对单个模块，测试团队可以根据已经确定测试用例批量执行.得到实际结果与期望结果进行比较.而这个过程测试执行者无需了解代码如何执行.也就是俗称黑盒测试.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;而对于单个模块的回归测试而言.为了提高效率引入自动化测试的概念.可惜的是目前并没有任何可用于Windows phone Application应用程序的自动化测试工具.曾在Silverlight中使用过自动化测试工具-&lt;/font&gt;&lt;a href="http://www.ranorex.com/" target="_blank"&gt;&lt;font face="Consolas"&gt;Ranorex&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;,花费点时间尝试通过Ranorex在WP 上执行自动化测试.发现存在很多应用程序与测试工具之间很多不可控的问题. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;那么对于单个模块回归测试而言.需要哪些过程可以自动化?分析如下:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;自动化流程:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;[1]：模拟器控制-启动或关闭Windows phone 模拟器.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;[2]: 自动在模拟器上安装并执行测试用例应用程序.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;[3]: 收集测试结果&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;[4]: 卸载测试用应用程序前恢复模拟器&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;首先来看看应用程序安装执行过程.目前只能通过Application Development Tool部署真机上:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-10_112505" border="0" alt="2012-01-10_112505" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201101550573237.png" width="825" height="215" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;now，如果我们把这个过程自动化处理.问题就出现了如何在不使用Application Development Tool情况把XAP安装包安装到模拟器或真机上? 同样针对模拟器控制.如何能够在代码自动控制并运行XAP安装包?&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;针对这个问题.Windows phone 类库中提供一个Microsoft.SmartDevice.Connectivity.DLL用来实现与模拟器或设备进行交互.现在针对原有解决方案添加一个命名为DeveiceAutomationTest_Desktop的Console类型应用程序用来做回归测试自动化的控制台.解决方案结构如下:&lt;/font&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="2012-01-10_113843" border="0" alt="2012-01-10_113843" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201101550575156.png" width="342" height="301" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;要实现对模拟器交互控制 需要在控制台应用程序添加对Microsoft.SmartDevice.Connectivity.DLL引用,引用地址C:\Program Files (x86)\Common Files\microsoft shared\Phone Tools\CoreCon\10.0\Bin:&lt;/font&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="2012-01-09_143729" border="0" alt="2012-01-09_143729" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201101550584566.png" width="565" height="463" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;添加引用后，实现对应设备控制的操作.连接并安装初始化XAP到模拟器中,添加一个设备控制类DeviceManager类，首先要根绝设备类型模拟器或真机获取设备的控制设备的Device对象:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        &lt;span &gt;/// Get Current Support Platform Device Object&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;param name="localId"&amp;gt;Region Local Id&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;returns&amp;gt;Device Object&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; Device GetSupportPlatformDeviceObj(&lt;span &gt;int&lt;/span&gt; localId,&lt;span &gt;bool&lt;/span&gt; isDevice)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            &lt;span &gt;//Note By chenkai:&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;            &lt;span &gt;//1033 is the LCID for English, United States and 1031 is the LCID for German, Germany.&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;            &lt;span &gt;//Please Check List of Locale ID (LCID) Values as Assigned by Microsoft.&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            &lt;span &gt;//http://msdn.microsoft.com/zh-cn/goglobal/bb964664.aspx&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;            &lt;span &gt;//Now Use English is 1031&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (localId == 0)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;                localId = 1031;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;            Device currentDeviceObj = &lt;span &gt;null&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;            DatastoreManager datastoreManagerObj = &lt;span &gt;new&lt;/span&gt; DatastoreManager(localId);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;            Platform wp7Platform = datastoreManagerObj.GetPlatforms().Single(p =&amp;gt; p.Name == &lt;span &gt;"Windows Phone 7"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (wp7Platform != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;                &lt;span &gt;if&lt;/span&gt; (isDevice)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;                    currentDeviceObj = wp7Platform.GetDevices().Single(x =&amp;gt; x.Name == &lt;span &gt;"Windows Phone Device"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;                &lt;span &gt;else&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  24:  &lt;/span&gt;                    currentDeviceObj = wp7Platform.GetDevices().Single(x =&amp;gt; x.Name == &lt;span &gt;"Windows Phone Emulator"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  25:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  26:  &lt;/span&gt;            &lt;span &gt;return&lt;/span&gt; currentDeviceObj;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  27:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;localid是在初始化静态 &lt;a href="http://msdn.microsoft.com/zh-cn/library/microsoft.smartdevice.connectivity.datastoremanager(v=vs.90).aspx" target="_blank"&gt;DatastoreManager&lt;/a&gt; 对象时是一个区域设置标识符 (LCID)，这是一个标识语言、国家和/或地区的整数. 当然这里采用1031德国地区.针对这个区域Localid的设置请参考官方给出的&lt;a href="http://www.microsoft.com/globaldev/reference/lcid-all.mspx" target="_blank"&gt;List of Locale ID (LCID) Values as Assigned by Microsoft&lt;/a&gt; 列表.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;获取数据控制Device对象后.可以连接设备并把XAP包安装并初始化到设备中:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        &lt;span &gt;/// Connection Emulator Device&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;param name="deviceObj"&amp;gt;Device Object&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;param name="applicationGuid"&amp;gt;Application Guid&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;param name="iconFilePath"&amp;gt;IconFile Path&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;param name="xapFileName"&amp;gt;XapFile Name&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;        &lt;span &gt;/// &amp;lt;returns&amp;gt;return is Connection Device&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; ConnectionDeviceInstallApp(Device deviceObj,Guid applicationGuid,&lt;span &gt;string&lt;/span&gt; iconFilePath,&lt;span &gt;string&lt;/span&gt; xapFileName)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (!&lt;span &gt;string&lt;/span&gt;.IsNullOrEmpty(applicationGuid.ToString()))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;                &lt;span &gt;try&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;                {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;                    deviceObj.Connect();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;                    ApplicationManager.InstallApplicationAndLaunch(deviceObj, applicationGuid, iconFilePath, xapFileName);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;                }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;                &lt;span &gt;finally&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;                {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;                    deviceObj.Disconnect();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;                }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这个方法中需要提供Device设备操作对象.以及XAP安装包和对应应用程序图标的文件路径. 其实这里并不一定非得采用控制台的方式.也可以做一个Winform以可见UI的方式.至于Guid则是测试项目WP7AutomationTest_Demo.Test-WMAppmainfest.xml文件中的ProductId相对应:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;  &amp;lt;App xmlns=&lt;span &gt;""&lt;/span&gt; ProductID=&lt;span &gt;"{b81d87a6-3afd-4f21-9a60-3c5ae0921fd2}"&lt;/span&gt; Title=&lt;span &gt;"WP7AutomationTest_Demo.Test"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;该方法中执行了两个操作.链接设备.安装XAP包到设备中.安装XAP操作通过ApplicationManager类中InstallApplicationAndLaunch方法 .定义如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; InstallApplicationAndLaunch(Device deviceObj, Guid applicationGuid, &lt;span &gt;string&lt;/span&gt; iconFileName, &lt;span &gt;string&lt;/span&gt; xapFileName)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (!&lt;span &gt;string&lt;/span&gt;.IsNullOrEmpty(applicationGuid.ToString()))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;                &lt;span &gt;//Install and Luanch&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;                UnstallApplicationAndClear(deviceObj, applicationGuid);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;                deviceObj.InstallApplication(applicationGuid, applicationGuid, &lt;span &gt;"AutomationAPP"&lt;/span&gt;, iconFileName, xapFileName);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;                RemoteApplication currentApplication = deviceObj.GetApplication(applicationGuid);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;                &lt;span &gt;if&lt;/span&gt; (currentApplication != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;                    currentApplication.Launch();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;通过Device对象初始化XAP 并Lauch,.在执行安装XAP之前 如果正在运行则立即中断.如果已经安装该应用程序则需删除卸载:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; UnstallApplicationAndClear(Device deviceObj, Guid applicationGuid)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt;(!&lt;span &gt;string&lt;/span&gt;.IsNullOrEmpty(applicationGuid.ToString()))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;                &lt;span &gt;if&lt;/span&gt; (deviceObj.IsApplicationInstalled(applicationGuid))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;                {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;                    RemoteApplication remoteApplication = deviceObj.GetApplication(applicationGuid);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;                    &lt;span &gt;if&lt;/span&gt; (remoteApplication != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;                    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;                        &lt;span &gt;//Remove Application&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;                        remoteApplication.TerminateRunningInstances();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;                        remoteApplication.Uninstall();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;                    }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;                }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.如此封装号对设备的初始化的控制.开始执行ProgramMain 方法:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;        &lt;span &gt;static&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Main(&lt;span &gt;string&lt;/span&gt;[] args)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;            &lt;span &gt;//Base ApplicationInfo&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            &lt;span &gt;string&lt;/span&gt; xapfile = &lt;span &gt;@"..\..\..\WP7AutomationTest_Demo.Test\Bin\Debug\WP7AutomationTest_Demo.Test.xap"&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            &lt;span &gt;string&lt;/span&gt; iconfile = &lt;span &gt;@"..\..\..\WP7AutomationTest_Demo.Test\Bin\Debug\WApplicationIcon.png"&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;            ApplicationBaseInfo currentBaseInfo = &lt;span &gt;new&lt;/span&gt; ApplicationBaseInfo(xapfile, iconfile, &lt;span &gt;new&lt;/span&gt; Guid(&lt;span &gt;"b81d87a6-3afd-4f21-9a60-3c5ae0921fd2"&lt;/span&gt;));&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            &lt;span &gt;//DeviceManager Object&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;            Device deviceObj = DeviceManager.GetSupportPlatformDeviceObj(1031,&lt;span &gt;false&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;            &lt;span &gt;using&lt;/span&gt; (ServiceHost currentHost = &lt;span &gt;new&lt;/span&gt; ServiceHost(&lt;span &gt;typeof&lt;/span&gt;(TestResultReportService)))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;                currentHost.Open();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;                Console.WriteLine(&lt;span &gt;"Current Service is Open..."&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;                Console.WriteLine(&lt;span &gt;"Connecting to Windows phone Emluator Device..."&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;                &lt;span &gt;try&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;                {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;                    &lt;span &gt;//Device Connection&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;                    deviceObj.Connect();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;                    Console.WriteLine(&lt;span &gt;"Windows phone Emluator Device Connected..."&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;                    ApplicationManager.InstallApplicationAndLaunch(deviceObj, currentBaseInfo.ApplicationGuid, currentBaseInfo.IconFilePath, currentBaseInfo.XapFilePath);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;                    Console.WriteLine(&lt;span &gt;"Wait For Run TestCase Compated..."&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  24:  &lt;/span&gt;                    lastendTestRunEvent.WaitOne(12000);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  25:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  26:  &lt;/span&gt;                    Console.WriteLine(&lt;span &gt;"Test Case is Run Complate..."&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  27:  &lt;/span&gt;                    ApplicationManager.UnstallApplicationAndClear(deviceObj, currentBaseInfo.ApplicationGuid);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  28:  &lt;/span&gt;                    Console.WriteLine(&lt;span &gt;"Application is UnStall and Clear..."&lt;/span&gt;);                   &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  29:  &lt;/span&gt;                }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  30:  &lt;/span&gt;                &lt;span &gt;finally&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  31:  &lt;/span&gt;                {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  32:  &lt;/span&gt;                    deviceObj.Disconnect();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  33:  &lt;/span&gt;                }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  34:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  35:  &lt;/span&gt;                &lt;span &gt;//currentHost.Close();&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  36:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Main方法执行的流程.首先部署XAP停止正在应用程序.并从设备中移除.然后连接设备 部署XAP包. 执行TEstCase测试用例.获取测试用例反馈结果.卸载当前应用程序并清空数据状态.回复测试运行前.测试效果:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-09_183143" border="0" alt="2012-01-09_183143" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201101550582025.png" width="644" height="390" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;正常运行时如果模拟器没有运行会自动打开模拟器 安装XAP包运行测试用例.当控制台获取测试结果后.卸载当前当前测试用例.一个完整回归测试流程就建立成功了.而发现可以把整个执行流程全部自动化代码控制.当然可以把回归测试在执行多条数据时多次自动化执行.整个执行流程控制台操作如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-10_150414" border="0" alt="2012-01-10_150414" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201101550598404.png" width="681" height="478" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在main方法同时建立一个WCF服务.该服务的主要目的是在单元测试用例测试完成后通知控制台停止调用. 另外一个目的是把SUTF框架的测试结果传递给控制台.存在一个测试结果文件中保存在本地并输出到控制台中:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; TestResultReportService : ITestResultReportService&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; SaveTestResultFile(&lt;span &gt;string&lt;/span&gt; filename, &lt;span &gt;string&lt;/span&gt; filecontent)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            var outputfile = Path.Combine(@"..\..\..\DeveiceAutomationTest_Desktop\Bin\Debug\", filename);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (File.Exists(outputfile))&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;                File.Delete(outputfile);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;            File.WriteAllText(outputfile, filecontent);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            Console.WriteLine(filecontent);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;        &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; GetFinalTestResult(&lt;span &gt;bool&lt;/span&gt; failure, &lt;span &gt;int&lt;/span&gt; failures, &lt;span &gt;int&lt;/span&gt; totalScenarios, &lt;span &gt;string&lt;/span&gt; message)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;            Console.WriteLine(message);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;            Program.EndTestRun();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;而针对测试用例应用程序WP7AutomationTest_Demo.Test需要额外引用该服务.重新建立一个TestBaseReportService类用来重写TestReportingProvider实体类中方法实现.测试结果通过服务以消息的形式传递给控制台.保存在文件中: 首先添加引用:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; Microsoft.Silverlight.Testing;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; Microsoft.Silverlight.Testing.Harness;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; Microsoft.Silverlight.Testing.Service;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; Microsoft.VisualStudio.TestTools.UnitTesting;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;重写方法:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; TestBaseReportService:TestReportingProvider&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;//ServiceClient&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        UnitTestService.TestResultReportServiceClient reportClient = &lt;span &gt;new&lt;/span&gt; UnitTestService.TestResultReportServiceClient();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; TestBaseReportService(TestServiceProvider serviceProvider) : &lt;span &gt;base&lt;/span&gt;(serviceProvider) { }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; ReportFinalResult(Action&amp;lt;ServiceResult&amp;gt; callback, &lt;span &gt;bool&lt;/span&gt; failure, &lt;span &gt;int&lt;/span&gt; failures, &lt;span &gt;int&lt;/span&gt; totalScenarios, &lt;span &gt;string&lt;/span&gt; message)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.IncrementBusyServiceCounter();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;            reportClient.SaveTestResultFileCompleted += (se, x) =&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.DecrementBusyServiceCounter();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;            };&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;            reportClient.GetFinalTestResultAsync(failure, failures, totalScenarios, message);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;            &lt;span &gt;base&lt;/span&gt;.ReportFinalResult(callback, failure, failures, totalScenarios, message);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; WriteLog(Action&amp;lt;ServiceResult&amp;gt; callback, &lt;span &gt;string&lt;/span&gt; logName, &lt;span &gt;string&lt;/span&gt; content)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.IncrementBusyServiceCounter();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;            reportClient.SaveTestResultFileCompleted += (s, e) =&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.DecrementBusyServiceCounter();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  24:  &lt;/span&gt;            };&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  25:  &lt;/span&gt;            reportClient.SaveTestResultFileAsync(logName, content);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  26:  &lt;/span&gt;            &lt;span &gt;base&lt;/span&gt;.WriteLog(callback, logName, content);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  27:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  28:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;ok。定义重写服务之后还需要Silverlight Unit TESt FrameWork框架进行测试结果的关联.这很关键.SUTF框架将通过该服务来提交报告. 在mainpage定义输出的页面添加如下Code:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;           var reportSetting = UnitTestSystem.CreateDefaultSettings();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (reportSetting!=&lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;                reportSetting.TestService.RegisterService(TestServiceFeature.TestReporting, &lt;span &gt;new&lt;/span&gt; TestBaseReportService(reportSetting.TestService));&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;一整个回归测试自动化流程建立完毕"，编译通过执行:&lt;/p&gt;&#xD;
&#xD;
&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="2012-01-10_153241" border="0" alt="2012-01-10_153241" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201101550591959.png" width="644" height="351" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.可以看到把整个回归测试整个流程完全自动化用Code处理了. 而控制台应用就类似自动化时可以复用处理的脚本一样.可以复用.依然能够看到控制台中存在几个需要及时制定的变量类似.XAP 包路径等.也可以封装可见的UI指定.当我们修改审核玩测试用例后.就可以通过该控制台应用程序.定期执行自动化回归的测试.生成测试报告.很有效保证代码集成时质量.本篇只是提供自动化解决一种方案.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;源码如下:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/chenkai/WP7AutomationTest_Demo.rar"&gt;/Files/chenkai/WP7AutomationTest_Demo.rar&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2318221.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/10/2318221.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html</id><title type="text">Windows phone 应用开发[9]-单元测试</title><summary type="text">本篇来谈谈Windows phone Unit Test.原来在9月份一次线下技术沙龙现场交流.我在现场提到关于Windows phone Unit Test在实际编程所体现一些问题.可惜当时在现场回应人的太少.通过本篇将详细梳理关于在Windows phone 开发流程做UT可能遇到的问题,以及一些具体解决方案.关于UT.不会在这里拿太多篇幅解释它基本的用法.当然也更不会拿时间去强调UT它在实际编程中保证软件质量重要性.从自身角度来说.一个程序员良好的职业素养往往源自于对自身高要求,并能持之以恒的保持下去.在实际开发流程照成很多”不愉快“的体验,其实很多从自身角度来说完全可以避免的.其实很多</summary><published>2012-01-06T14:11:00Z</published><updated>2012-01-06T14:11:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;本篇来谈谈Windows phone Unit Test.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;原来在9月份一次线下技术沙龙现场交流.我在现场提到关于Windows phone Unit Test在实际编程所体现一些问题.可惜当时在现场回应人的太少.通过本篇将详细梳理关于在Windows phone 开发流程做UT可能遇到的问题,以及一些具体解决方案.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;关于UT.不会在这里拿太多篇幅解释它基本的用法.当然也更不会拿时间去强调UT它在实际编程中保证软件质量重要性.从自身角度来说.一个程序员良好的职业素养往往源自于对自身高要求,并能持之以恒的保持下去.在实际开发流程照成很多&amp;#8221;不愉快&amp;#8220;的体验,其实很多从自身角度来说完全可以避免的.&lt;/font&gt;&lt;/p&gt;&#xD;
&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="software_developer" border="0" alt="software_developer" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210153459.jpg" width="504" height="322" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;其实很多Team在实际开发中拒绝写UT.而且还不在少数.依然还是很多开发人员认为自己只是不断贡献产品的Code.而和UT无关.还是有那么多Program Manager太过于专注开发进度.在每次CodeReview后.忽略了为UT留下相应的时间.而在后期集成测试阶段让开发人员陷入Bug突显修修补补&amp;#8220;灾难&amp;#8221;之中难以自拔. 显然实际开发中突显种种问题.是对理想状态下软件工程必要流程断章取义.而IDE开发工具越来越强大编译能力似乎让开发人员产生依赖.编译通过只是说明语法正确.而无法真实确认实际Code语义是否也是愿景一致.而在具有一定规模存在多分枝项目结构中.如果没有一个完整保证软件质量的体系和具体措施方法.很难想象这样集成项目中对开发人员该是一种什么样的灾难.!?&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.谈到Windows phone应用或是客户端.往往实际开发规模相对于Pc Application较小. 特别是未来突出云平台发展方向.必然会照成客户端APP越来越瘦的趋势.但必要测试依然是构造可靠应用程序必经之路.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;1&amp;gt;构建测试环境&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;针对Windows phone应用程序Unit Test 官方并没有在IDE提供对应的测试框架.经过实际开发反复验证.依然可以通过如下几种方式建立.Windows phone 单元测试.:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;建立单元测试:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;[1]通过带有官方背景的Jeff Wilcox&amp;#8217;s 更新Silverlight Unit Test Framework的Windows phone版本建立单元测试.具体请参见&lt;a href="http://www.jeff.wilcox.name/2010/05/sl3-utf-bits/"&gt;Updated Silverlight Unit Test Framework bits for Windows Phone and Silverlight 3&lt;/a&gt; And &lt;a href="http://live.visitmix.com/MIX10/Sessions/CL59"&gt;Unit Testing Silverlight &amp;amp; Windows Phone Applications&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[2]通过第三方测试框架&lt;a href="http://wptestlib.codeplex.com/" target="_blank"&gt;Windows phone Test FrameWork&lt;/a&gt;或&lt;a href="http://nunitwindowsphone7.codeplex.com/" target="_blank"&gt;NUnit For Windows phone&lt;/a&gt; 等构建&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在目前Windows phone应用程序中建立单元测试框架中在开发者群体使用最广泛的是Jeff Wilcox&amp;#8217;s 维护更新的Silverlight Unit TEst FrameWork For Windows phone版本.其实熟悉Silverlight开发的同学应该知道.Jeff Wilcox是Silverlight 2版本时官方推出Unti Test FrameWork单元测试框架的主要开发人员之一.做过Silverlight单元测试的开发人员肯定知道他曾在博客写的&lt;a href="http://www.jeff.wilcox.name/2008/03/silverlight2-unit-testing/" target="_blank"&gt;Silverlight 2版本单元测试系列&lt;/a&gt;.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在Windows phone应用程序中引用单元测试需要添加如下引用DLL:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt;&lt;span &gt;//添加引用DLL&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt;Microsoft.Silverlight.Testing&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt;Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以通过两种方式获得该DLL引用.方式一在Jeff Wilcox&amp;#8217;s 博客下载 解压即可:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://media.jeff.wilcox.name/blog/TestFx20110609.zip"&gt;&lt;strong&gt;[ZIP, 518K]&lt;/strong&gt; Silverlight Unit Test Framework Assemblies compatible with Mango Beta Tools&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;下载完成后.解压能看到如上两个必须的DLL.这时解决方案添加一个普通的Windows phone Application项目.[UT测试结果需要在UI输出].手动添加如上两个DLL引用关系.这时会提示:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-04_180856" border="0" alt="2012-01-04_180856" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210164996.png" width="500" height="242" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;提示引用Silverlight类库.可以不理会提示直接点击是确定引用.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;方式二: 打开Visual Studio 2011 找到Tool-&amp;gt;Extension Manager .在Online Gallery选项中搜索:Windows phone Test Project 可以看到:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-05_192531" border="0" alt="2012-01-05_192531" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210173469.png" width="644" height="446" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以直接通过点击Download下载安装该项目模板.安装完成后新建Project就能看到 Test选项页下多了一个Windows phone Test Project模板:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-05_193307" border="0" alt="2012-01-05_193307" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210189225.png" width="644" height="446" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;新建一个测试项目命名Test project1[测试用].在执行编译前需要安装&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/04/2312024.html" target="_blank"&gt;Nuget&lt;/a&gt;然后通过Tool-&amp;gt;Library Package Manager-&amp;gt;Package Manager Console窗口输入如下命令添加引用:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-05_194039" border="0" alt="2012-01-05_194039" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210198603.png" width="779" height="211" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这时会在TestProject 1实际上会看到添加三个引用:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt;&lt;span &gt;//添加引用DLL &lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt;Microsoft.Silverlight.Testing &lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt;Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt;SilverlightSerializer.WP7&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;注意.当建立玩这个模板项目TestProject1会提示通过Nuget工具执行如下命令行: Install-Package Silverlight.UnitTest 和 Install-Package WindowsPhoneEssentials.Testing执行两个指令 .在执行命令前前者因WP7SDK 更新的原因,前者并不支持Mango版本所以就不推荐使用了.一律使用后者命令初始化引用库.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;构建好测试项目后.首先在Windows phone Unit TEst中.我们既可以采用极限编程XP提倡的[TDD]Test Driver Development测试驱动的方式从上而下进行.也可以仅仅只是回顾性的编写单元测试一遍验证代码的执行是否与预期的执行效果相同.本篇主要采用Silverlight Unit TEst FrameWork来构建执行WP7单元测试. &lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Well.在构建单元测试用例[Test Case]前.需要构建一个具有完成功能的Windows phone应用程序.这里为了演示的目的.当前应用程序以MVVM的方式实现UI上一个分类列表的显示.首先定义一个ViewModel-MainPage_ViewModel 内容:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; MainPage_ViewModel:BasicViewModel&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; ObservableCollection&amp;lt;CatalogInfo&amp;gt; catalogInfoCol = &lt;span &gt;new&lt;/span&gt; ObservableCollection&amp;lt;CatalogInfo&amp;gt;();&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; ObservableCollection&amp;lt;CatalogInfo&amp;gt; CatalogInfoCol&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; get { &lt;span &gt;return&lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogInfoCol; }&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; set&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogInfoCol = &lt;span &gt;value&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; &lt;span &gt;base&lt;/span&gt;.NotifyPropertyChangedEventHandler(&lt;span &gt;"CatalogInfoCol"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; LoadCatalogDefaultData()&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogInfoCol.Clear();&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 17: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogInfoCol.Add(&lt;span &gt;new&lt;/span&gt; CatalogInfo() { CatalogName=&lt;span &gt;"Music &amp;amp; Video"&lt;/span&gt;,CatalogComment=&lt;span &gt;"For Everyone Catalog"&lt;/span&gt; });&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 18: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogInfoCol.Add(&lt;span &gt;new&lt;/span&gt; CatalogInfo() { CatalogName = &lt;span &gt;"Book References"&lt;/span&gt;, CatalogComment = &lt;span &gt;"just For Child"&lt;/span&gt; });&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 19: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 20: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 21: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; catalogTitle;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 22: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; CatalogTitle&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 23: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 24: &lt;/span&gt; get { &lt;span &gt;return&lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogTitle; }&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 25: &lt;/span&gt; set&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 26: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 27: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.catalogTitle = &lt;span &gt;value&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 28: &lt;/span&gt; &lt;span &gt;base&lt;/span&gt;.NotifyPropertyChangedEventHandler(&lt;span &gt;"CatalogTitle"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 29: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 30: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 34: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 35: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 36: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; CatalogInfo&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 37: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 38: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; CatalogName{get;set;}&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 39: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; CatalogComment{get;set;}&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 40: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;这里定义一个ObserverCollection&amp;lt;T&amp;gt;来实现UI界面的绑定.数据源为了演示目的 采用静态添加集合方式.添加数据.建立号ViewModel 添加UI绑定:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;private&lt;/span&gt; MainPage_ViewModel mainPage_ViewModel = &lt;span &gt;null&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;void&lt;/span&gt; MainPage_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;this&lt;/span&gt;.mainPage_ViewModel == &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.mainPage_ViewModel = &lt;span &gt;new&lt;/span&gt; MainPage_ViewModel();&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.mainPage_ViewModel.LoadCatalogDefaultData();&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.DataContext = mainPage_ViewModel;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在UI中添加一个ListBox呈现数据直接运行效果如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-06_110013" border="0" alt="2012-01-06_110013" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210204600.png" width="268" height="484" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;至此一个简单以MVVM形式构建分类列表显示功能Windows phone 应用程序构建完成了.在构建单元测试之前.原结构化编程语言中，比如C，要进行测试的单元一般是函数或子过程.但在目前的OOP面向对象的概念中，单元测试对应基本单位就是类.但是实际操作发现.类作为测试单位，复杂度高，可操作性较差，因此仍然主张以函数作为单元测试的测试单位，但可以用一个测试类来组织某个类的所有测试函数. 相对于Windows phone 应用程序以MVVM模型以及UIBind引擎中.核心代码更加倾向于集中ViewMolde和UI的Code-Behind中.因Silverlight Unit test FrameWork[SUTF]框架对单元测试具有可视化的输出.所以必须基于Windows phone Application模板.要在单元测试的项目构建测试用例前.需要初始化SUTF测试结果用户显示界面.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在测试项目中UnitiyCommonEmptyDemo.Test的MainPage 的Loaded事件中需要做如下几件事:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;处理视图:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;[1]隐藏SystemTray系统托盘&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[2]处理应用程序的BackPress事件在SUTF中建立单元输出视图切换&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[3]把当SUTF的测试结果输出当前UI中&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;实现如下:&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;void&lt;/span&gt; MainPageOutPut_Form_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;//UnAvaliable SystemTray&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; SystemTray.IsVisible=&lt;span &gt;false&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; var currentMobileTestPage = UnitTestSystem.CreateTestPage() &lt;span &gt;as&lt;/span&gt; IMobileTestPage;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (currentMobileTestPage != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; BackKeyPress += (x, se) =&amp;gt; se.Cancel = currentMobileTestPage.NavigateBack();&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; (Application.Current.RootVisual &lt;span &gt;as&lt;/span&gt; PhoneApplicationFrame).Content = currentMobileTestPage;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;针对应用程序的功能.需要通过Unit TEst 验证CatalogInfoCol是否触发了PropertyChanged通知事件.绑定UI集合是否具有数据? 在修改CatalogTitle过程中是否正确传递属性的值?. &lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;有了如上两个测试用例.针对对应MainpageUI建立MainPageTestHelper并表示类[TestClass]特性. 首先验证CatalogInfoCol是否触发通知事件.并在值发生变化集合中是否具有数据.建立第一个TEstCase:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; [TestMethod]&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; DataColIsChanged_Test()&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;bool&lt;/span&gt; isPropertyChanged = &lt;span &gt;false&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; MainPage_ViewModel currentViewModel = &lt;span &gt;new&lt;/span&gt; MainPage_ViewModel();&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; currentViewModel.PropertyChanged += (x, se) =&amp;gt; &lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt;(currentViewModel.CatalogInfoCol.Count&amp;gt;0)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; isPropertyChanged = &lt;span &gt;true&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; };&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; currentViewModel.CatalogInfoCol = &lt;span &gt;new&lt;/span&gt; System.Collections.ObjectModel.ObservableCollection&amp;lt;CatalogInfo&amp;gt;() &lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; &lt;span &gt;new&lt;/span&gt; CatalogInfo(){CatalogName=&lt;span &gt;"ComplateTestChanged"&lt;/span&gt;,CatalogComment=&lt;span &gt;"TestData"&lt;/span&gt;}&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; };&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; Assert.IsTrue(isPropertyChanged);&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当对ViewModel属性赋值触发PropertyChanged事件.并判断当前集合是否存在数据.同样.修改CatalogTitle看额外的修改是否正确传递属性对应的值，建立对应的Test Case 如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; [TestMethod]&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; DataCatalogTitle_CatalogTitle_Test()&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;bool&lt;/span&gt; isEventChanged = &lt;span &gt;false&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; MainPage_ViewModel currentViewModel = &lt;span &gt;new&lt;/span&gt; MainPage_ViewModel(); &lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; currentViewModel.PropertyChanged += (x, se) =&amp;gt; &lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt;(currentViewModel.catalogTitle.Equals(&lt;span &gt;"newTitle"&lt;/span&gt;))&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; isEventChanged=&lt;span &gt;true&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; };&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; currentViewModel.CatalogTitle = &lt;span &gt;"newTitle"&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; Assert.IsTrue(isEventChanged);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font face="Consolas"&gt;ok.编译通过。运行结果：&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-06_120209" border="0" alt="2012-01-06_120209" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210217532.png" width="268" height="484" /&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="2012-01-06_120224" border="0" alt="2012-01-06_120224" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210228305.png" width="268" height="484" /&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="2012-01-06_120233" border="0" alt="2012-01-06_120233" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210237891.png" width="268" height="484" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在SUTF中对应类和函数 测试结果之间具有一定层级关系.点击进入每个TestMethod具体的测试详情:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="2012-01-06_135056" border="0" alt="2012-01-06_135056" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210246156.png" width="268" height="484" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.也可以写一个测试出错的函数来看看在出错是SUTF表现.添加TestCase 模拟出错的情况 添加如下Code:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; [TestMethod]&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; [Description(&lt;span &gt;"This test always fails intentionally"&lt;/span&gt;)]&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; AllwaysWrong()&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; Assert.IsTrue(&lt;span &gt;false&lt;/span&gt;,&lt;span &gt;"Test Method For Wrong Case!"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;编译通过 运行:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-06_135517" border="0" alt="2012-01-06_135517" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210258565.png" width="268" height="484" /&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="2012-01-06_135525" border="0" alt="2012-01-06_135525" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210252610.png" width="268" height="484" /&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="2012-01-06_140737" border="0" alt="2012-01-06_140737" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210264463.png" width="268" height="484" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;带有红点是没有通过测试的类.单击类名可以找到类中带有TestMethod特性的方法列表.能在测试结果详情页看到对应TestMethod对应Description描述，测试的结果 运行时间和对应的异常信息.而能在异常信息中也能看到我们Code预先设置出错时会显示ExceptionMessage字符串提示.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如上在Windows phone application 构建一个最简单单元测试整个流程.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;2&amp;gt;异步操作&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在Windows phone 应用开发中常常需要通过网络协议获取数据.或是通过异步操作实现常用UI更新等.这也是最为常见极为频繁的异步操作.其实做过Silverlight Application集成测试的同学应该知道这往往大量异步操作照成测试过程很多难易规避的问题.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;和大多数单元测试框架不同.Silverlight Unit Test FrameWork整个单元测试框架是运行相同的线程上的.如果应用程序引用任何外部服务类似一个WCF Service都需要一个返回的UI线程的异步调用. 导致在UT同一线程执行时无法阻止当前线程等待WCF调用返回结果.UT无法做.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;针对Windows phone Application应用程序. 如果想做集成测试基本不太可能.Silverlight Unit Test Framework 常常因为进程之间互操作出现任何未处理的异常都会中断整个集成测试的运行.而集成测试常常也需要长时间.跨越多线程操作的. 常常在运行时会出现异常后会自动跑到App.cs中Debugger.Break()方法中断整个程序执行立即退出.没有任何提示.而不是完全预期想UT测试返回Fail结果.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.其实在Silverlight Unit Test Framework 框架对异步操作做UT完全可行的.只是存在一些测试用例中常常容易出错问题.出错频率较高.如上应用扩展一下.把ViewModel中集合通过异步方式获取数据源.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在独立封装UnitiyCommon 类库中定义CommentAPI类用来获取网络上数据.定义Code如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;delegate&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; CommentData(List&amp;lt;CommentInfo&amp;gt; commentList, Exception se);&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;event&lt;/span&gt; CommentData LoadCommentDataComplated;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; &lt;span &gt;/// This Method Simulate asynchronous request &lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;/// &amp;lt;param name="uri"&amp;gt;Request Download Image Uri&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; GetAllNewsCommentOperator(&lt;span &gt;object&lt;/span&gt; uri)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (!&lt;span &gt;string&lt;/span&gt;.IsNullOrEmpty(uri.ToString()))&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; &lt;span &gt;//Single Subscribe&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; LoadCommentDataComplated = &lt;span &gt;null&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; BasicAPI.TransportWebRequestOperator(&lt;span &gt;"POST"&lt;/span&gt;, uri.ToString(), RequestComent_CallBack);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如上程序的目的通过一个指定的URI获取网络上图片数据.这个过程是异步的.封装类库中.要UI进行交互则使用最原始简单的委托+事件的组合方式.当图片数据下载完成通过LoadCommentDataComplated事件通知执行操作. 下载图片数据成功后.回调函数如下：&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; RequestComent_CallBack(IAsyncResult result)&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; &lt;span &gt;try&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; HttpWebRequest currentRequest = result.AsyncState &lt;span &gt;as&lt;/span&gt; HttpWebRequest;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; WebResponse currentResponse = currentRequest.EndGetResponse(result);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (currentResponse != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; &lt;span &gt;//Update State&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; IsComplated = &lt;span &gt;true&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; CommentInfo downloadComment = &lt;span &gt;new&lt;/span&gt; CommentInfo()&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; CommentName = &lt;span &gt;"Comment Image"&lt;/span&gt;,&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; CommentImageUri=currentRequest.RequestUri.AbsoluteUri,&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; CommentImageData = currentResponse.GetResponseStream()&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt; };&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 18: &lt;/span&gt; List&amp;lt;CommentInfo&amp;gt; commentList = &lt;span &gt;new&lt;/span&gt; List&amp;lt;CommentInfo&amp;gt;(){downloadComment};&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 19: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (LoadCommentDataComplated != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 20: &lt;/span&gt; LoadCommentDataComplated(commentList, &lt;span &gt;null&lt;/span&gt;);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 21: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 23: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 24: &lt;/span&gt; &lt;span &gt;catch&lt;/span&gt; (Exception se)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 25: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 26: &lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (LoadCommentDataComplated != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 27: &lt;/span&gt; LoadCommentDataComplated(&lt;span &gt;null&lt;/span&gt;, se);&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 28: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 29: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;回调函数手动处理数据.为了处理Unit Test单元测试.针对单元测试采用EnqueueCallback对象.需要额外添加如下Code:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt;&lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;bool&lt;/span&gt; IsComplated { get; &lt;span &gt;private&lt;/span&gt; set; }&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt;&lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; UpdateAsync()&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt;{&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; System.Threading.ThreadPool.QueueUserWorkItem(GetAllNewsCommentOperator);&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt;}&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font face="Consolas"&gt;UpdateAsync方法的目的是通过Threadpool进程池的方式.在执行单元时调用.把所有的异步操作封装队列方式并稍后执行,.封装号CommentAPI后.通过ViewModel与UI进行关联.这里Code略去.详见源码.篇幅限制 不在赘述. 绑定UI后运行执行的结果如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-06_215219" border="0" alt="2012-01-06_215219" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210278824.png" width="268" height="484" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;如上其实我哪了一个最简单而最常见WebRequest异步请求方式获取网络数据.如何在Silverlight Unit Test FrameWork中对这种异步操作做单元测试?&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;其实原来Silverlight Unit Test FrameWork在第一个版本时并不支持对异步操作.后来确实太多开发人员发现很多核心的业务在异步中无法实现UT.Jeff Wilcox在后续版本增加对异步操作支持 .关于实现的过程Jeff Wilcox在其博客中有一篇Blog说的非常清楚:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&lt;font style="font-weight: bold"&gt;Asynchronous Support For SUTF:&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.jeff.wilcox.name/2009/03/asynchronous-testing/"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-weight: bold"&gt;Asynchronous test support &amp;#8211; Silverlight unit test framework and the UI thread&lt;/font&gt;&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在Silverlight Unit Test Framework执行过程随着时间迁移执行如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&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="ComparingExecution" border="0" alt="ComparingExecution" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210284265.png" width="525" height="484" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;从图中轻易发现SUTF框架要面临的问题，相对桌面Silverlight应用成不同的.SUTF要把可能在不同线程中异步调用操作.在时间轴能够以类似同步方式按照队列加以排序执行.关于这个执行规则组成.可以通过一系列UT中操作步骤完成. 那我们UT要完整测试一个异步调用 需要执行如下步骤:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;异步测试需要执行的步骤:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[1]：首先通过线程池TheadPool把所有异步操作封装.在队列中随着时间轴线稍后执行.在UT中通过调用该方法开发异步调用&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[2]：EnqueueCallback()方法添加一个任务到执行队列中.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[3]：EnqueueConditional()方法添加一个条件判断队列，如果为true才继续执行&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&lt;font size="2"&gt;[4]: &lt;/font&gt;EnqueueDelay() &amp;#8211;添加指定的队列等待时间&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;[5]: EnqueueTestComplete() 添加一个TestComplete()到队列中，这个方法告知framework测试结束了&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;具体的执行流程如下:&lt;/p&gt;&#xD;
&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="WorkItemExample2" border="0" alt="WorkItemExample2" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210334359.png" width="644" height="477" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;[如下章节.是在7份醉意下写的. 有些细节可能写的有些粗糙.]&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;梳理好了在测试框架中整个测试异步Begin-End模型流程.按照该流程执行.新建一个测试类MainPageAsyncTestHelper.首先针对异步测试需要引用常用的EnqueueCallback、EnqueueDelay等对象.该类需要继承Microsoft.Silverlight.Testing;空间下SilverlightTes类.以便引用，实现核心Code:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&lt;span &gt; 1: &lt;/span&gt; [TestClass]&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 2: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; MainPageAsyncTestHelper:SilverlightTest&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 3: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 4: &lt;/span&gt; [TestMethod]&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 5: &lt;/span&gt; [Asynchronous]&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 6: &lt;/span&gt; [Description(&lt;span &gt;"Test Async Operator ."&lt;/span&gt;)]&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 7: &lt;/span&gt; [Timeout(6000)]&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 8: &lt;/span&gt; &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; AsyncOperator_ViewModel_Test()&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 9: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 10: &lt;/span&gt; CommentAPI currentCommentAPI = &lt;span &gt;new&lt;/span&gt; CommentAPI();&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 11: &lt;/span&gt; &lt;span &gt;bool&lt;/span&gt; isAsnycComplated = &lt;span &gt;false&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 12: &lt;/span&gt; CommentAPI.LoadCommentDataComplated += (x, se) =&amp;gt; &lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 13: &lt;/span&gt; {&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 14: &lt;/span&gt; isAsnycComplated = &lt;span &gt;true&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 15: &lt;/span&gt; }; &lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 16: &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 17: &lt;/span&gt; &lt;span &gt;//Test Async &lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 18: &lt;/span&gt; EnqueueCallback(() =&amp;gt; { currentCommentAPI.UpdateAsync(); });&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 19: &lt;/span&gt; EnqueueConditional(() =&amp;gt; isAsnycComplated);&lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 20: &lt;/span&gt; EnqueueCallback(() =&amp;gt; Assert.IsFalse(CommentAPI.IsComplated));&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span &gt; 21: &lt;/span&gt; EnqueueTestComplete(); &lt;/pre&gt;&#xD;
&lt;pre&gt;&lt;span &gt; 22: &lt;/span&gt; }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
font-size: small;&#xD;
color: black;&#xD;
font-family: consolas, "Courier New", courier, monospace;&#xD;
background-color: #ffffff;&#xD;
/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt&#xD;
{&#xD;
background-color: #f4f4f4;&#xD;
width: 100%;&#xD;
margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在异步测试方法中.可选的特性项.针对异步操作测试方法必须添加[Asynchronous]标识.Description特性用来描述当前测试方法测试的功能简介描述.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;而对于Timeout用意.大家都应该知道Begin-End异步模型中.如果建立网络请求可能导致请求超时情况发生.而且是服务器被动限制的.而在单元测试过程中.我们也不得不考虑当前单元测试可能会失败.可能在执行异步过程中会卡在一个无线循环或是类似请求的状态中.此类状态会使测试的执行耗费太长的时间.特别在执行集成测试中这种现象最为明显和常见.当然作为单元测试.尽量保证功能完整正确.特别在使用ASynchronous特性标识.如果在执行EnqueueConditional时从未使其条件语句为真.导致测试用例可能会被无限期锁住.当然为了是测试流程中避免出现中断测试或测试用例无法全部执行下去情况发生.Timeout特性为执行测试方法的时间提供一个上限值. 如果测试方法超过该时间则认定为失败.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Well.通过测试用例中.首先建立一个标识属性isAsnycComplated 用来标识当前异步操作是否完成.这是作为EnqueueCallBAck对象执行队列中必备的执行条件.首先通过UpdateAsync()方法启动异步方法. 再通过IsAsnyncComplated指定执行条件. Assert对齐进行排列.最后通过EnqueueComplete（）方法来指示当前测试方法结束.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;编译通过.测试结果:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&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="2012-01-06_215020" border="0" alt="2012-01-06_215020" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210333180.png" width="268" height="484" /&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="2012-01-06_215032" border="0" alt="2012-01-06_215032" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210351553.png" width="268" height="484" /&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="2012-01-06_215037" border="0" alt="2012-01-06_215037" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201062210361454.png" width="268" height="484" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;异步测试通过.&lt;/p&gt;&#xD;
&lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;4&amp;gt;小结&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;本篇其实原不想写这么多篇幅.在Windows phone 中开始做Unit Test和集成测试也因传统的异步Begin-End模型会在实际操作出现很多异常.本篇目的是演示Windows phone 中做UT主要方式.以及处理这个过程自己碰到一些具体问题寻求的实际解决方案.抛砖引玉.但目前集成测试中一个解决方案是始终通过EnqueueCallback确保异常恰当地报告给单元测试框架。只要一个错误就能中断接下来的所有测试.而引起这个问题根源主要源于Windows phone很多操作异步模型导致.当然关于集成测试出错比较频繁的情况.国外一个作者&lt;a href="http://blog.richardszalay.com/2011/08/08/writing-asynchronous-unit-tests-with-rx-and-the-silverlight-unit-testing-framework/"&gt;Richard Szalay&lt;/a&gt;在其通过RX[Reactive Extensions]结合单元测试 给出一个处理解决方案. 这篇文章链接如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&lt;font style="font-weight: bold"&gt;Richard Szalay 集成解决方案:&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&lt;font style="font-weight: bold"&gt;&lt;a href="http://blog.richardszalay.com/2011/08/08/writing-asynchronous-unit-tests-with-rx-and-the-silverlight-unit-testing-framework/" target="_blank"&gt;Writing asynchronous unit tests with Rx and the Silverlight Unit Testing Framework&lt;/a&gt;&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在实际开发中其实我们项目中采用三种测试框架.Silverlight Unit Test Framework采用的最为广泛. 但SUTf依然存在很多限制和需要改善的地方。下篇将介绍通过其他第三方框架更简洁实现UT.并总结相对SUTF具有优势和特点.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;关于本盘如果任何问题 请在评论中指出.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;本篇所有演示的源码下载地址:&lt;a href="http://files.cnblogs.com/chenkai/UnitiyCommonDirDemo.rar"&gt;/Files/chenkai/UnitiyCommonDirDemo.rar&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;参考资料:&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="3" face="Consolas"&gt;&lt;a href="http://blog.richardszalay.com/2011/08/08/writing-asynchronous-unit-tests-with-rx-and-the-silverlight-unit-testing-framework/" target="_blank"&gt;&lt;span style="font-size: 10pt; "&gt;Writing asynchronous unit tests with Rx and the Silverlight Unit Testing Framework&lt;/span&gt;&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&lt;a href="http://smartypantscoding.com/a-cheat-sheet-for-unit-testing-silverlight-apps-on-windows-phone-7" target="_blank"&gt;A Cheat Sheet for Unit Testing Silverlight Apps on Windows Phone 7&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font size="3" face="Consolas"&gt;&lt;a href="http://www.jeff.wilcox.name/2009/03/asynchronous-testing/"&gt;&lt;span style="font-size: 10pt; "&gt;Asynchronous test support &amp;#8211; Silverlight unit test framework and the UI thread&lt;/span&gt;&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://blogs.msdn.com/b/francischeung/archive/2012/01/03/running-windows-phone-unit-tests-via-msbuild.aspx"&gt;&lt;font size="3" face="Consolas"&gt;&lt;span style="font-size: 10pt; "&gt;Running Windows Phone Unit Tests via MSBuild&lt;/span&gt;&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2315214.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/06/2315214.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2012/01/04/2312024.html</id><title type="text">Nuget Tool</title><summary type="text">Nuget 这个工具最先是在MIX11上开始让我注意.不知道当时看MIX同学是否注意到一个小细节.-就是所有MIX11 Code演示环节中MS开发人员都使用Nuget.本篇介绍一些Nuget安装和一些在实际项目中基本用法. 首先 解释一下Nuget Tool是什么? NuGet 是一种 Visual Studio 扩展工具，它能够简化在 Visual Studio 项目中添加、更新和删除库（部署为程序包）的操作。 NuGet 程序包是打包成一个文件的文件集，扩展名是 . nupkg，使用开放打包约定 (OPC) 格式. 在没有使用Nuget工具之前.如果我们要在一个普通.NET项目中...</summary><published>2012-01-04T06:51:00Z</published><updated>2012-01-04T06:51:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2012/01/04/2312024.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2012/01/04/2312024.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;Nuget 这个工具最先是在MIX11上开始让我注意.不知道当时看MIX同学是否注意到一个小细节.-就是所有MIX11 Code演示环节中MS开发人员都使用Nuget.本篇介绍一些Nuget安装和一些在实际项目中基本用法.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;首先 解释一下Nuget Tool是什么?&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.nuget.org/" target="_blank"&gt;&lt;font face="Consolas"&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-12-20_183915" border="0" alt="2011-12-20_183915" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120104145106326.png" width="233" height="68" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;NuGet 是一种 Visual Studio 扩展工具，它能够简化在 Visual Studio 项目中添加、更新和删除库（部署为程序包）的操作。 NuGet 程序包是打包成一个文件的文件集，扩展名是 . nupkg，使用开放打包约定 (OPC) 格式.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在没有使用Nuget工具之前.如果我们要在一个普通.NET项目中添加一个库的引用.最简单的方式就是添加DLL引用的方式实现第三方代码库引用.通过下载解压.添加引用操作.如果在发布时还需要为项目依赖项进行大量手工整理.是否发现.在DLL引入到发布整个过程存在一个管理&amp;#8221;真空&amp;#8220;状态.如果要向其他开发者或组织共享我们代码.是否意味更复杂的操作.着恰恰也是Nuget所做的.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;安装Nuget有两种方式.方式一打开Visual Studio 2010,打开Tool-&amp;gt;Extension Manager窗体.选择Online Gallery，在搜索框中输入NuGet看到:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="extension-manager-with-nuget" border="0" alt="extension-manager-with-nuget" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451063640.png" width="728" height="417" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;点击Download下载会自动安装，另外一种方式打开&lt;/font&gt;&lt;a href="http://www.nuget.org/"&gt;&lt;font face="Consolas"&gt;http://www.nuget.org/&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;直接下载安装文件&lt;/font&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c" target="_blank"&gt;&lt;font face="Consolas"&gt;NuGet Manager&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; . 点击运行开始安装:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_105511" border="0" alt="2012-01-04_105511" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451069147.png" width="464" height="363" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;选择安装工具 下一步:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_105518" border="0" alt="2012-01-04_105518" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451074654.png" width="464" height="363" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;安装完成.如果在安装过程出现错误货没有正确安装会在安装界面提示:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_115357" border="0" alt="2012-01-04_115357" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451074621.png" width="464" height="348" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;关于安装出错后通过查看Install Log 确定出错的原因:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_115744" border="0" alt="2012-01-04_115744" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451085112.png" width="644" height="463" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;如果觉得麻烦.也可以不看.直接找到上图的目录删除掉NuGet Package Manager文件夹，重新安装Nuget Tool即可.安装完成后可以创建一个Windows phone Application 打开Tool-&amp;gt;Library Package Manager-&amp;gt;Package Manager Console:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_135817" border="0" alt="2012-01-04_135817" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451085394.png" width="640" height="441" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;可以通过在控制台Package Manager Console 输出目录管理库 首先在在线的&lt;/font&gt;&lt;a href="http://www.nuget.org/packages"&gt;&lt;font face="Consolas"&gt;http://www.nuget.org/packages&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt;目录下找到对应库初始化路径 类似找到Json.NET &lt;/font&gt;&lt;a href="http://www.nuget.org/packages/Newtonsoft.Json"&gt;&lt;font face="Consolas"&gt;http://www.nuget.org/packages/Newtonsoft.Json&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; 初始化路径为:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_140447" border="0" alt="2012-01-04_140447" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451085918.png" width="748" height="78" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;输入：Install-Package Newtonsoft.Json&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_140616" border="0" alt="2012-01-04_140616" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451088393.png" width="401" height="322" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;如果对应库文件较大.则会在Visual Studio 右下角提示有下载进度.安装完成后:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_140921" border="0" alt="2012-01-04_140921" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451092820.png" width="612" height="213" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;可以在当前项目目录中看到已经成功添加到引用中:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_141025" border="0" alt="2012-01-04_141025" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451092471.png" width="377" height="357" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;可以引用管理手动添加库文件.在解决方案的References引用可以看到:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_141245" border="0" alt="2012-01-04_141245" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451096898.png" width="375" height="352" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;多了一个Manage Nuget Packages打开管理窗体能够实现已经安装库文件管理:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_141459" border="0" alt="2012-01-04_141459" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451104357.png" width="644" height="431" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Nuget提供基于 Windows PowerShell 的控制台窗口（称作程序包管理器控制台）以及一组 Windows PowerShell 命令与 NuGet 进行交互。 Windows PowerShell 是基于 .NET 的脚本语言和命令行 shell，非常适合组成命令集，并能够处理对象.当然PowerShell提供强大支持可以Package Manager Console通过指令直接管理卸载库 例如卸载已经引用Json.NET库输入:Unstall-Package Newtonsoft.Json卸载.如果想看到当前项目已经引用的Package在Console 直接通过指令的方式获取 Get-Package:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_142207" border="0" alt="2012-01-04_142207" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451108784.png" width="637" height="230" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;看到当前项目中已经使用库文件 以及版本其他信息.如果已经引用的组件存在新的版本 依然可以通过Update-Package批量更新已经引用的库:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_143018" border="0" alt="2012-01-04_143018" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451101259.png" width="651" height="218" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;命令尝试将每个程序包都更新到最新版本,如果任何程序包包含重大改变，这会是一项非常重大的操作。 在多数情况下，您仅希望将各程序包更新至最新的修补程序版本。 这叫&amp;#8220;安全&amp;#8221;更新，前提是具有较大内部版本号或修订号（但具有相同的主版本号和次版本号）的程序包能够向后兼容。 仅添加 Safe 标记以执行安全更新:例：&lt;strong&gt;Update-Package &amp;#8211;Safe&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;当然我们能够现在操作都是基于在线Nuget官方数据源Package操作.当然我们可以PAckage数据源设置成本地 找到绿色按钮Package Manager Settings:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_143814" border="0" alt="2012-01-04_143814" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451103178.png" width="659" height="222" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;打开并在一个指定本地目录下添加一个本地Package数据源:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_143950" border="0" alt="2012-01-04_143950" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/201201041451114225.png" width="644" height="421" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;能在Console看到指定的数据源设置分类LocalPackages:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&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="2012-01-04_144057" border="0" alt="2012-01-04_144057" src="http://images.cnblogs.com/cnblogs_com/chenkai/201201/20120104145111604.png" width="651" height="218" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;当然对于组织结构更大的公司和开发团队.如果简单的使用SVN和Git管理方式依然不容易控制不同库版本和对外共享的控制.Nuget针对企业用户提供可以在企业内部搭建一个Nuget Server的形式来统一管理内部开发团队库共享. 大大提高开发效率.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;参考资源:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://www.nuget.org/" target="_blank"&gt;Nuget Org HomePage&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://docs.nuget.org/docs/start-here/installing-nuget" target="_blank"&gt;How to InStall Nuget Component?&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2312024.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2012/01/04/2312024.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2011/12/31/2309035.html</id><title type="text">Windows phone 应用开发[8]-体验PhoneGap</title><summary type="text">早在7月份就听说PhoneGap.移动应用产品往往常常考虑多个平台的支持.单一平台很难保证应用的覆盖面或者换句话说就是用户群体的量和持续的活跃性上从长期的角度而言往往存在短板.另外从开发的角度而言.多平台的支持往往需要建立不同的技术团队.而平台之间开发技术也是完全迥异的. 开发一个具有相同业务的应用Natural-Application需要使用到不同平台的框架和开发语言.使用 C/C++ 的 Symbian、使用 Object C 的 iOS 和使用 Java 的 Android 应用开发技术，几乎是完全无法融合的. PhoneGap跨平台移动应用开发框架正是应运而生. Well .在介绍P.</summary><published>2011-12-31T10:13:00Z</published><updated>2011-12-31T10:13:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2011/12/31/2309035.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2011/12/31/2309035.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;早在7月份就听说PhoneGap.移动应用产品往往常常考虑多个平台的支持.单一平台很难保证应用的覆盖面或者换句话说就是用户群体的量和持续的活跃性上从长期的角度而言往往存在短板.另外从开发的角度而言.多平台的支持往往需要建立不同的技术团队.而平台之间开发技术也是完全迥异的. 开发一个具有相同业务的应用Natural-Application需要使用到不同平台的框架和开发语言.使用 C/C++ 的 Symbian、使用 Object C 的 iOS 和使用 Java 的 Android 应用开发技术，几乎是完全无法融合的. PhoneGap跨平台移动应用开发框架正是应运而生.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Well .在介绍PhoneGap前关于移动平台Application 需要搞清楚几个概念:Web App，Native App,Hybird App：&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;移动平台Application几个概念:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Web App:这个主要是采用统一的标准的HTML,JavaScript.CSS等web技术开发.通过不同平台的浏览器访问来实现跨平台.同时可以通过浏览器支持充分使用HTML5特性，缺点是这些基于浏览器的应用无法调用系统API来实现一些高级功能，也不适合高性能要求的场合.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Native APP:就是所谓的原生应用.指的是用平台特定的开发语言所开发的应用.使用它们的优点是可以完全利用系统的API和平台特性，在性能上也是最好的。缺点是由于开发技术不同，如果你要覆盖多个平台，则要针对每个平台独立开发,无跨平台特性.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;Hybird App：则是为了弥补如上两者开发模式的缺陷的产物.分别继承双方的优势.首先它让为数众多的web开发人员可以几乎零成本的转型成移动应用开发者；其次，相同的代码只需针对不同平台进行编译就能实现在多平台的分发，大大提高了多平台开发的效率；而相较于web App，开发者可以通过包装好的接口，调用大部分常用的系统API.&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;而PhoneGap正是Hybird APP目前框架中集大成者. 一方面以标准HTML JavaScript技术开发应用通过浏览器的方式实现跨平台的概念.另外它也满足在能够应用直接调用核心功能的API.用PhoneGap官方的一句话概况其特点是:&amp;#8221;written once, run everywhere&amp;#8221;-一次编译到处运行.&lt;/font&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="e0f269be-9caf-363e-bac9-90995b823586" border="0" alt="e0f269be-9caf-363e-bac9-90995b823586" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813019682.jpg" width="240" height="270" /&gt;&lt;font face="Consolas"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;1&amp;gt;PhoneGap发展历程&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;本篇我并不打算介绍一些PhoneGap基础概念.而是想说说最近几天在体验PhoneGap中碰到一些困惑.以及找到一些关于这些问题的答案.如果你不了解PhoneGap是什么可以通过如下链接:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;PhoneGap Platform:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;&lt;a href="http://phonegap.com/" target="_blank"&gt;PhoneGap Home Page&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&lt;a href="http://en.wikipedia.org/wiki/PhoneGap" target="_blank"&gt;PhoneGap On WikiPedia&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Consolas"&gt;&lt;a href="http://baike.baidu.com/view/4157600.htm" target="_blank"&gt;PhoneGap on Baidu Baike&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;关于PhoneGap整理其发展历程如下:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实PhoneGap原来是由一家加拿大的小公司开发支持. 它真正开始成名是在2008年的在San Francisco举办的iPhoneDevCamp上.很快就在2009年由O&amp;#8217;Reilly Media举办的2009 Web 2.0 大会赢得了&amp;#8220;开发者选择&amp;#8221;奖的殊荣.而正在此时项来以封闭的著称的苹果帝国-苹果公司正式认同这个开发框架.甚至为此特意修改了4.0版开发者协议。其实这也是苹果支持为数不多的开放标准之一HTML5一次选择.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;2009年2月25日，PhoneGap0.60正式发布，这是第一个稳定版，同时支持iOS、Android、BlackBerry三个平台.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;2009年8月到2010年7月，PhoneGap实现了对Windows Mobile、Nokia WRT(S60)、Palm、Symbian^3平台的支持，支持平台达到6个.Worklight和appMobi等移动应用开发平台也采用了PhoneGap框架作为对其移动客户端开发引擎的支撑.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;2011年10月，Adobe收购了创立PhoneGap项目的Nitobi公司，随后把PhoneGap项目捐给了Apache基金会，但Adobe保留了PhoneGap的商标所有权（该项目在Apache旗下的名称是Apache Callback）。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;2011年7月29日，PhoneGap发布了1.0版产品。PhoneGap 1.0的推出，该版本重点是访问本地设备的API.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;2011年11月7日，PhoneGap1.2.0发布，随着微软的介入这个版本正式支持Windows Phone 7，至此支持的平台数达到7个.&lt;/font&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="2011-12-31_143930" border="0" alt="2011-12-31_143930" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813012681.png" width="607" height="484" /&gt;&lt;font face="Consolas"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;&amp;gt;PhoneGap原理&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实在看到PhoneGAp实现Windows phone 和其他平台IOs Android平台应用互动Demo后.我当时就很疑惑PhoneGap如何实现的?其实谈到这点.很多人往往关注到PhoneGap解决了了什么.却忽略了作为跨平台移动应用框架所在交互上所面临的问题.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&amp;#8220;written once, run everywhere&amp;#8221; 这句话要解决跨平台移动应用框架两个无法规避的问题:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;存在问题:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;A：首先要解决平台之间兼容问题.实现其跨平台的特性.必须要在开发技术上要跨越各个平台开发编程语言和框架的界限.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;B:&amp;nbsp;&amp;nbsp; 其次要能够实现和各平台的SDK API实现无差别的交互.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;这两点其实也正是PhoneGap所最开始的设计初衷.那么PhoneGap如何解决这两个问题?&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;首先在解决平台兼容性问题上.来看看PhoneGap使用的开发技术-[HTML+CSS+JavaScript等].不难看出这些具有成熟统一标准的web前段技术[HTML+CSS+JavaSCript],在各个主流平台支持HTML 5背景下.这些技术都是支持和认可的.PhoneGap的做法是采用成熟的脚本和 Web 技术作为实现平台兼容的切入点. 而未来HTML 5标准之一就是跨平台特性. 无疑为这种成熟解决方案创造了可能.具体来说这些开发技术[HTML+CSS+JavaScript]在PhoneGap主要实现应用程序UI呈现和组织业务逻辑功能.对于移动应用框架的跨平台性 有一张很好解释图:&lt;/font&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="build3" border="0" alt="build3" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813027108.png" width="658" height="294" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实在说到和各个平台SDK API实现无差别的交互上.PhoneGap通过调用JavaSCript 调用API库实现和各个平台的SDK进行无差别的交互. 以达到调用不同平台手机上摄像头，文件系统,重力感应.GPS定位等功能.从第二张图中可以看出.虽然能够实现这种方式实现SDK API调用.但是各个平台之间依然存在差异.但Windows phone 支持所有PhoneGap对SDK操作.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;虽然能够实现JavaScript调用Windows phone SDK功能.当我按照官方给出的API文档简单实现几个功能后. 我不禁有些疑惑这种在JavaScript中直接实现调用SDK API在框架中是如何实现的.? &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;其实这个问题也不难找到.PhoneGap在运行时.会吧编写的HTML、CSS,Javascript文件处理成一种类似&amp;#8221;文件镜像&amp;#8221;方式.然后通过浏览器解析执行.在解析执行的过程中会调用SDK 中API.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;而调用SDK中API方式其实你只要打开fildder工具监听请求.就能看到每次调用时会发送Ajax请求，也就是通过脚本向设备发送消息方式.当设备接到消息后解析处理后通过调用XAML固定的WebView浏览器控制的Load方法执行脚本从而实现脚本回调.这就是PhoneGap通过JavaScript调用SDK 中API的&amp;#8221;秘密&amp;#8220;所在.&lt;/font&gt;&lt;font face="Consolas"&gt; 图解如下:&lt;/font&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="1555551" border="0" alt="1555551" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813022059.png" width="644" height="481" /&gt;&lt;/p&gt;  &lt;h3 style="padding-bottom: 3px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;3&amp;gt;PhoneGap在Windows phone 体验&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;如下在Windows&amp;nbsp; phone开发环境构建几个简单PhoneGap应用来体验一下其执行过程.So 如果你不了解如何在Windows phone 中搭建PhoneGap开发环境请参考如下链接:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;How to Build development environment ：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://phonegap.com/start#wp" target="_blank"&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;Build PhoneGap Development Environment HomePage&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;API Docs:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://docs.phonegap.com/en/1.3.0/index.html"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;http://docs.phonegap.com/en/1.3.0/index.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;构建一个PhoneGap Application 命名:PhoneGapBuildAppDemo&lt;/font&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="2011-12-31_162613" border="0" alt="2011-12-31_162613" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813025614.png" width="344" height="378" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;从初始的解决方案的结构来看.Gaplib目录下包含一个WP7GapClassLib.dll. WWW目录下则是要编写发布 运行时展示的内容.如果要迁移支持多平台.这是核心内容.关于一次编译到处运行.很多开发人员可能产生一些误解. 即使我们在Windows phone 平台成功编译运行.还是需要Copy WWW目录下文件迁移到其他平台.做一些必要调整和修改.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;至于Plugins目录稍后解释. 打开MainPage.xml文件发现只有一个定制的WEbBrowser控件:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;          &lt;span &gt;&amp;lt;!--xmlns:my="clr-namespace:WP7GapClassLib;assembly=WP7GapClassLib"--&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;          &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;my:PGView&lt;/span&gt; &lt;span &gt;HorizontalAlignment&lt;/span&gt;&lt;span &gt;="Stretch"&lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;                   &lt;span &gt;Margin&lt;/span&gt;&lt;span &gt;="0,0,0,0"&lt;/span&gt;  &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;                   &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;="PGView"&lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;                   &lt;span &gt;VerticalAlignment&lt;/span&gt;&lt;span &gt;="Stretch"&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&#xD;
&lt;p&gt;&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font face="Consolas"&gt;运行时加载解析的是www目录下Inde.html网页内容.Well.这里我们现实当前平台一些基本信息.可以在API Doc文档找到Deveice现实信息的API,修改JavaSCript如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;      &amp;lt;script type=&lt;span &gt;"text/javascript"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;          document.addEventListener(&lt;span &gt;"deviceready"&lt;/span&gt;, onDeviceReady, &lt;span &gt;false&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        &lt;span &gt;// once the device ready event fires, you can safely do your thing! -jm&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;        &lt;span &gt;function&lt;/span&gt; onDeviceReady() {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;            document.getElementById(&lt;span &gt;"welcomeMsg"&lt;/span&gt;).innerHTML += &lt;span &gt;'Device Name: '&lt;/span&gt; + device.name + &lt;span &gt;'&amp;lt;br /&amp;gt;'&lt;/span&gt; +&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;                            &lt;span &gt;'Device PhoneGap: '&lt;/span&gt; + device.phonegap + &lt;span &gt;'&amp;lt;br /&amp;gt;'&lt;/span&gt; +&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;                            &lt;span &gt;'Device Platform: '&lt;/span&gt; + device.platform + &lt;span &gt;'&amp;lt;br /&amp;gt;'&lt;/span&gt; +&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;                            &lt;span &gt;'Device UUID: '&lt;/span&gt; + device.uuid + &lt;span &gt;'&amp;lt;br /&amp;gt;'&lt;/span&gt; +&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;                            &lt;span &gt;'Device Version: '&lt;/span&gt; + device.version + &lt;span &gt;'&amp;lt;br /&amp;gt;'&lt;/span&gt;;         &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;      &amp;lt;/script&amp;gt;  &lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;运行应用程序:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&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-12-31_171109" border="0" alt="2011-12-31_171109" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813037532.png" width="268" height="484" /&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可以看到通过JAvaScript中调用直接访问Windows phone SDK 中API拿到当前设备的基本信息.如果你觉得PhoneGap还不足够媲美Windows phone 自身SDK API能力.那么JAvaScript中直接调用设备的摄像头.并能够实现摄像头图片截屏. 并保存到图片库中. 保存成功后.JAvaScript依然能够能够访问指定图片相册去读取截图文件. 只需需该一段JAvaScript 轻松实现截屏功能:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;&amp;lt;script type=&lt;span &gt;"text/javascript"&lt;/span&gt; charset=&lt;span &gt;"utf-8"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;navigator.camera.getPicture(onSuccess, onFail, { quality: 50 }); &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;function onSuccess(imageData) {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;    var image = document.getElementById(&lt;span &gt;'myImage'&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;    image.src = &lt;span &gt;"data:image/jpeg;base64,"&lt;/span&gt; + imageData;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;}&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;function onFail(message) {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;    alert(&lt;span &gt;'Failed because: '&lt;/span&gt; + message);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;}&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;运行时截图:&lt;/p&gt;&#xD;
&#xD;
&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="2011-12-31_172841" border="0" alt="2011-12-31_172841" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112311813039451.png" width="268" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;具体调用摄像头的实例请参考官方API文档：&lt;/font&gt;&lt;a href="http://docs.phonegap.com/en/1.3.0/phonegap_camera_camera.md.html#Camera"&gt;&lt;font face="Consolas"&gt;http://docs.phonegap.com/en/1.3.0/phonegap_camera_camera.md.html#Camera&lt;/font&gt;&lt;/a&gt; .&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;well.出了官方提供的通用的SDK API.我们依然能够从第二章图能看出有些SDK API调用也是因平台不同而 各异. 不禁有开发人员提出一些具体而实际的需求.如果说要在PhoneGap直接调用PhoneCallTask任务实现打电话功能. 这里就必须提到如上解决方案中Plugins目录. &lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Plugins目录当然顾名思义.就是扩展的插件.PhoneGap有一个另外很重要的特点就是对对应平台可以供开发人员插件的方式集成SDK API中功能.实现即插即用的框架组织结构.这对开发人员无意给出最大的扩展自由. 如果我们PhoneGap集成一个打电话功能.首先要在Plugins目录创建一个PhoneTaskService类 添加引用:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; Microsoft.Phone.Tasks;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; WP7GapClassLib.PhoneGap;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&#xD;
&lt;p&gt;&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font face="Consolas"&gt;定义类:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; PhoneTaskService : BaseCommand&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; ExcutePhoneCallTask()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            PhoneCallTask mefPhoneCallTask = &lt;span &gt;new&lt;/span&gt; PhoneCallTask();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;            mefPhoneCallTask.DisplayName = &lt;span &gt;"China Mobile Customer Service"&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;            mefPhoneCallTask.PhoneNumber = &lt;span &gt;"10086"&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            mefPhoneCallTask.Show();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先修改类命名空间.将该类做为 PhoneGap 运行库命名空间，因此将该类的命名空间修改为&lt;strong&gt;WP7GapClassLib.PhoneGap.Commands&lt;/strong&gt;. 另外我们还必须继承 PhoneGap 运行库的 BaseCommand 类，以便我们可以在 JavaScript 中调用到该类. 定义JAvaScript调用:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;function CallComposer(){     &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    &lt;span &gt;this&lt;/span&gt;.resultCallback = &lt;span &gt;null&lt;/span&gt;; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;} &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;CallComposer.prototype.showCallComposer = function(toRecipients, body) &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;{ &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;    var args = {};     &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;    &lt;span &gt;if&lt;/span&gt;(toRecipients)         &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;        args.toRecipients = toRecipients;     &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;    &lt;span &gt;if&lt;/span&gt;(body) &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;        args.body = body; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;    PhoneGap.exec(&lt;span &gt;null&lt;/span&gt;, &lt;span &gt;null&lt;/span&gt;, &lt;span &gt;"PhoneCall"&lt;/span&gt;, &lt;span &gt;"call"&lt;/span&gt;, args); &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;} &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;PhoneGap.addConstructor(function () { &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;    &lt;span &gt;if&lt;/span&gt; (!window.plugins) { &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;        window.plugins = {}; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;    } &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;    window.plugins.CallComposer = &lt;span &gt;new&lt;/span&gt; CallComposer(); &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  24:  &lt;/span&gt;  } &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  25:  &lt;/span&gt;); &lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在解决方案另存为.JS文件. 通过&amp;lt;Script&amp;gt;引用Index.HTML页面.通过如下方式JavaScript代码调用:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;window.plugins.CallComposer.showCallComposer(recipients, message) &lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;h3 style="padding-bottom: 4px; background-color: #80ac92; font-family: verdana, geneva, arial, helvetica, sans-serif; height: 44px; color: white; font-size: 15pt; font-weight: bolder; padding-top: 10px"&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;&amp;lt;4&amp;gt;PhoneGap小结&lt;/font&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;PhoneGap针对不同平台的WebView做了扩展和封装，使WebView这个组件变成可访问设备本地API的强大浏览器，所以开发人员在PhoneGap框架下可通过JavaScript访问设备本地API.实现WebView与SDK API双向通信.但PhoneGAp所体现的混合类型的应用还不能完全取代原生应用，在一些复杂的API调用或者涉及高性能计算的应用开发上，原生应用还是唯一的选择。除此以外的大多数场合，混合类型的应用以很小的性能牺牲为代价，带来了极大的灵活性和开发效率.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;当然PhoneGap依然存在很多问题:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;存在的问题:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;运行速度慢：PhoneGap集成多了个平台.程序的载入和UI界面的反应都比原生的程序慢，UI反应延时&amp;#8212;&amp;#8212;这是个致命伤 .它实际上还是在展示Web页面，所以载入、页面刷新等肯定是需要一定时间的。 这在用户体验上来说PhoneGAp依然无法替代原生应用程序.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
  &lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;strong&gt;不适合部分程序：如果你的程序需要3D功能，或者对界面刷新有较高的要求，这样的程序现在来说还只是用原生的语言会比较好.PhoneGap支持API还有待在各个平台逐步完善&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;开发者可以选择jQueryMobile和SenchaTouch等JavaScript库加速开发进度，使用AppMobi和Tiggr等集成开发环境进行开发和调试（通过拖拽进行排版、在线编码以及运行各种移动设备的模拟器），也可以选择PhoneGap Build这个专业的在线编译工具提供编码效率.&lt;/font&gt;&lt;font face="Consolas"&gt;当然与其类似还有Titanium.Rhodes 等跨平台移动开发框架.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;PhoneGap提供一种多平台解决方案.无疑为开发提供一种方式可参考思路.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;参考资料:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://baike.baidu.com/view/4157600.htm" target="_blank"&gt;PhoneGap On Baidu Baike&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://docs.phonegap.com/en/1.3.0/index.html" target="_blank"&gt;PhoneGap Online Doc API&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="https://build.phonegap.com/" target="_blank"&gt;PhoneGAp Build Tool&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://phonegap.com/" target="_blank"&gt;PhoneGap HomePage&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="https://github.com/phonegap" target="_blank"&gt;PhoneGap on GitHub&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2309035.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2011/12/31/2309035.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chenkai/archive/2011/12/28/2305324.html</id><title type="text">Windows phone 应用开发[7]-MEF For Windows phone</title><summary type="text">本篇是接着上篇Windows phone 应用开发[6]-Managed Extensibility Framework应用程序扩展 基础之上而来. 关于Managed Extensibility FrameWork[MEf]基础概念这里不再赘述.MEF 作为.NET 4一部分.同时也支持Silverlight4 版本.但因目前官方并没有推出Managed Extensibility Framework For Windows phone 版本. 对Codeplexhttp://mef.codeplex.com/上类库并不支持Windows phone. 这里介绍另外一种方式在Windows </summary><published>2011-12-28T11:41:00Z</published><updated>2011-12-28T11:41:00Z</updated><author><name>chenkai</name><uri>http://www.cnblogs.com/chenkai/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chenkai/archive/2011/12/28/2305324.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chenkai/archive/2011/12/28/2305324.html"/><content type="html">&lt;p&gt;&lt;font face="Consolas"&gt;本篇是接着上篇&lt;a href="http://www.cnblogs.com/chenkai/archive/2011/12/27/2303880.html" target="_blank"&gt;Windows phone 应用开发[6]-Managed Extensibility Framework应用程序扩展&lt;/a&gt; 基础之上而来. 关于Managed Extensibility FrameWork[MEf]基础概念这里不再赘述.MEF 作为.NET 4一部分.同时也支持Silverlight4 版本.但因目前官方并没有推出Managed Extensibility Framework For Windows phone 版本. 对Codeplex&lt;a href="http://mef.codeplex.com/"&gt;http://mef.codeplex.com/&lt;/a&gt;上类库并不支持Windows phone. 这里介绍另外一种方式在Windows phone 中使用MEF.并以一个简单实例 抛砖引玉.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;在开始介绍之前如果你对MEf For Windows phone 中使用存在问题和相关的技术瓶颈 想了解一番可以阅读如下文章:&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;MEf For Windows phone By damonpayne:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.damonpayne.com/post/2010/06/25/MEF-for-Windows-Phone-7.aspx"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;http://www.damonpayne.com/post/2010/06/25/MEF-for-Windows-Phone-7.aspx&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;这篇文章中作者Damonpayne很详细阐述了MEF 发展的过程以及相对Windows phone 开发不支持的一些相关特性类似:System.Reflection.Emit剔除. 针对MEF操作同样也不支持IQueryable接口的类Linq操作等.并提出自己的一套在Windows phone 中使用MEF的解决方案.可惜的是作者直接给一个封装不完整DLL.并删除下载页面.经过实际代码尝试Damonpayne给出的一条DeadWay. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;而欣慰的总是有人在无意间给你额外的惊喜. 在我看&lt;a href="http://msaf.codeplex.com/" target="_blank"&gt;Microsoft Silverlight Analytics Framework&lt;/a&gt;[MSAF]源码时意外的发现.这个开源框架中尽然移植一个Windows phone 版本的MEF:&lt;/font&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="2011-12-28_180341" border="0" alt="2011-12-28_180341" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112281940483046.png" width="371" height="454" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;MSAF分别针对原ComponentModel和Composition.Initialization空间做了Windows phone 类库的移植. 而如上类库正是MEF的核心.MSAF框架主要作用是提供了一种标准方法在Windows phone应用程序中添加对使用情况加以跟踪并支持第三方数据分析的功能.这个我会下篇中Windows phone采集用户数据和行为分析上讲解.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;Well 似乎MEF支持问题就如此意外的迎刃而解了.如下来做一个简单实例来验证.&lt;/font&gt;&lt;font face="Consolas"&gt;现在提出一个简单需求我们宿主程序中要通过MEF方式集成一个管理分类的组件.组件和Windows phone宿主程序关系如下:&lt;/font&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="2011-12-28_185257" border="0" alt="2011-12-28_185257" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112281940491226.png" width="594" height="374" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;以创建一个Windows phone的类库形式来实现这个组件 创建类库并命名-MEFCommon.Data.首先添加MEF 类库的引用:&lt;/font&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="2011-12-28_182410" border="0" alt="2011-12-28_182410" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112281940505229.png" width="422" height="430" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;分别引用了元MSAF源码中System.ComponentModel和Composition.Initialization两个DLL.创建一个封装组件分类操作的接口IAppCatalog 添加引用如下:&lt;/font&gt;&lt;/p&gt;  &lt;div &gt;   &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; System.ComponentModel;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; System.ComponentModel.Composition;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;&lt;span &gt;using&lt;/span&gt; System.ComponentModel.Composition.Hosting;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;接口中分别定义两个操作方法.一个用来添加分类方法 另外一个获取所有分类的数据方法:&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;   &lt;span &gt;public&lt;/span&gt; &lt;span &gt;interface&lt;/span&gt; IAppCatalog&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;       &lt;span &gt;bool&lt;/span&gt; AddCatalog(AppCatalog newAppCatalog);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;       List&amp;lt;AppCatalog&amp;gt; GetAllAppCatalogList();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;创建AppCatalogOperator类实现该接口:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    [Export(&lt;span &gt;typeof&lt;/span&gt;(IAppCatalog))]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; AppCatalogOperator:IAppCatalog&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; List&amp;lt;AppCatalog&amp;gt; OperatorCatalogList = &lt;span &gt;new&lt;/span&gt; List&amp;lt;AppCatalog&amp;gt;();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;bool&lt;/span&gt; AddCatalog(AppCatalog newAppCatalog)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            &lt;span &gt;//No Check Reply&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt;(newAppCatalog!=&lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;               &lt;span &gt;this&lt;/span&gt;.OperatorCatalogList.Add(newAppCatalog);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            &lt;span &gt;return&lt;/span&gt; &lt;span &gt;true&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; List&amp;lt;AppCatalog&amp;gt; GetAllAppCatalogList()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.OperatorCatalogList.Clear();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.OperatorCatalogList.Add(&lt;span &gt;new&lt;/span&gt; AppCatalog() { CatalogName = &lt;span &gt;"Music+Video"&lt;/span&gt;, CatalogNote = &lt;span &gt;"Important for Common User"&lt;/span&gt; });&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.OperatorCatalogList.Add(&lt;span &gt;new&lt;/span&gt; AppCatalog() { CatalogName = &lt;span &gt;"Game"&lt;/span&gt;, CatalogNote = &lt;span &gt;"Different Kind of Game platform"&lt;/span&gt; });&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.OperatorCatalogList.Add(&lt;span &gt;new&lt;/span&gt; AppCatalog() { CatalogName = &lt;span &gt;"Book"&lt;/span&gt;, CatalogNote = &lt;span &gt;"Reader"&lt;/span&gt; });&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;            &lt;span &gt;return&lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.OperatorCatalogList;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  24:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;同时在该类以IAppCatalog接口作为契约名向MEF开放.该类一方面提供分类的全部数据同时能够执行添加分类的操作.如下我们要在一个Windows phone宿主程序中用到分类组件提供分类数据.绑定UI上显示，定义一个UI上可操作的ViewModel:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; AppCatalog_ViewModel:BasicViewModel&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; AppCatalog_ViewModel()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            CompositionInitializer.SatisfyImports(&lt;span &gt;this&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; ObservableCollection&amp;lt;AppCatalog&amp;gt; appCatalogCollection = &lt;span &gt;new&lt;/span&gt; ObservableCollection&amp;lt;AppCatalog&amp;gt;();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; ObservableCollection&amp;lt;AppCatalog&amp;gt; AppCatalogCollection&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;            get { &lt;span &gt;return&lt;/span&gt; &lt;span &gt;this&lt;/span&gt;.appCatalogCollection; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;            set&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  14:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.appCatalogCollection = &lt;span &gt;value&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  15:  &lt;/span&gt;                &lt;span &gt;base&lt;/span&gt;.NotifyPropertyChangedEventHandler(&lt;span &gt;"AppCatalogCollection"&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  16:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  17:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  18:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  19:  &lt;/span&gt;        [Import(&lt;span &gt;typeof&lt;/span&gt;(IAppCatalog))]&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  20:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; IAppCatalog CurrentCatalogData { get; set; }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  21:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  22:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; LoadAppCatalogData()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  23:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  24:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;this&lt;/span&gt;.CurrentCatalogData != &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  25:  &lt;/span&gt;            {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  26:  &lt;/span&gt;                &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;this&lt;/span&gt;.CurrentCatalogData.GetAllAppCatalogList().Count &amp;gt; 0)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  27:  &lt;/span&gt;                {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  28:  &lt;/span&gt;                    var catalogList = &lt;span &gt;this&lt;/span&gt;.CurrentCatalogData.GetAllAppCatalogList();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  29:  &lt;/span&gt;                    &lt;span &gt;this&lt;/span&gt;.appCatalogCollection.Clear();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  30:  &lt;/span&gt;                    catalogList.ForEach(x =&amp;gt; { &lt;span &gt;this&lt;/span&gt;.appCatalogCollection.Add(x); });&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  31:  &lt;/span&gt;                }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  32:  &lt;/span&gt;            }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  33:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  34:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;首先在ViewModel定义一个以Import标识IAppcatalog类型属性用来接收组件中通过MEF需要传递的数据.其实这就是宿主程序一个扩展点.同样这个Windows phone宿主程序需要添加对组件类库和MEF 引用.现在有了组件的数据 和宿主程序的扩展点接入.Well,要实现组件与宿主程序之间通信则需要通过MEF建立组合的关联关系. 而这个组合关系引用需要在应用程序启动是调用.上篇中我们采用是一个Console应用程序直接写在Main方法.作为Windows phone当然也可以直接写在Launching和Activated事件中.当然最好的方式是创建一个实现IApplicationService接口的应用程序服务.可以获得更好的代码封装和关注分离的效果 创建Service如下:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;public&lt;/span&gt; &lt;span &gt;class&lt;/span&gt; MEFAppCatalogService:IApplicationService&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; MEFAppCatalogService()&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            CompositionHost.Initialize&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;                (&lt;span &gt;new&lt;/span&gt; AssemblyCatalog(Application.Current.GetType().Assembly),&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;                 &lt;span &gt;new&lt;/span&gt; AssemblyCatalog(&lt;span &gt;typeof&lt;/span&gt;(MEFCommon.Data.IAppCatalog).Assembly));&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  10:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; StartService(ApplicationServiceContext context) {   }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  11:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;  12:  &lt;/span&gt;        &lt;span &gt;public&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; StopService() {  }&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;  13:  &lt;/span&gt;    }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;在构造方法中.调用CompositionHost对象Initialize()方法.相对于上篇我们直接通过定义CompositionContainer容器的方式.而目前CompositionHost对象提供用于控制 &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.componentmodel.composition.compositioninitializer(v=vs.95).aspx"&gt;&lt;font face="Consolas"&gt;CompositionInitializer&lt;/font&gt;&lt;/a&gt;&lt;font face="Consolas"&gt; 所使用的容器的静态方法.二者效果是一致的. Initialize()方法在构造是可以接受任意数量的目录. 这和AggregateCatalog对象指定MEF解析范围是一致的.目录适用于定义MEF在解析类型是需要检索的位置范围.而引用的对象AssemblyCatalog则分别提供对分类组件类库和宿主应用程序的静态引用.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;接着指定运行的位置.向App.xaml内Application.ApplicationLifetimeObjects集合添加一个MEFAppCatalogService实例.则宿主程序会在任何应用程序代码运行之前调用服务的Initialize方法来初始化MEF的管理容器.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Application.ApplicationLifetimeObjects&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        &lt;span &gt;&amp;lt;!--Required object that handles lifetime events for the application--&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;shell:PhoneApplicationService&lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            &lt;span &gt;Launching&lt;/span&gt;&lt;span &gt;="Application_Launching"&lt;/span&gt; &lt;span &gt;Closing&lt;/span&gt;&lt;span &gt;="Application_Closing"&lt;/span&gt; &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            &lt;span &gt;Activated&lt;/span&gt;&lt;span &gt;="Application_Activated"&lt;/span&gt; &lt;span &gt;Deactivated&lt;/span&gt;&lt;span &gt;="Application_Deactivated"&lt;/span&gt;&lt;span &gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;        &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;        &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;mef:MEFAppCatalogService&lt;/span&gt;&lt;span &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;mef:MEFAppCatalogService&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;    &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Application.ApplicationLifetimeObjects&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;最后就是通过在ViewModel够着方法中调用CompositionInitializer对象的SatisfyImports()方法实现填充指定组件的导入.[observerCollection集合已经绑定UIlistBox控件]:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;&lt;span &gt;//组件导入&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt; CompositionInitializer.SatisfyImports(&lt;span &gt;this&lt;/span&gt;);&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;现在运行Windows phone应用程序看分类组件提供分类数据能拿到:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&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="2011-12-28_191411" border="0" alt="2011-12-28_191411" src="http://images.cnblogs.com/cnblogs_com/chenkai/201112/201112281940522853.png" width="268" height="484" /&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;ok.成功通过MEF框架宿主程序自动感知的灵活方式添加组件并获得组件提供分类数据.证明MASF提供MEF类库是可行的.到这了不禁有人会问相对上篇难道没有其他方式建立宿主和组件之间组合关系?答案是肯定的.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;只不过如果我们不以Service形式.我们建立组件关系.这段建立组合关系代码放在那? 应该采用什么方式来组合? 来看看Mainpage绑定ViewModel时:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;       &lt;span &gt;//Bind ViewModel&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;        &lt;span &gt;private&lt;/span&gt; AppCatalog_ViewModel appcatalog_ViewModel = &lt;span &gt;null&lt;/span&gt;;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;        &lt;span &gt;void&lt;/span&gt; MainPage_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;this&lt;/span&gt;.appcatalog_ViewModel == &lt;span &gt;null&lt;/span&gt;)&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;                &lt;span &gt;this&lt;/span&gt;.appcatalog_ViewModel = &lt;span &gt;new&lt;/span&gt; AppCatalog_ViewModel();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.appcatalog_ViewModel.LoadAppCatalogData();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            &lt;span &gt;this&lt;/span&gt;.DataContext = appcatalog_ViewModel;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   9:  &lt;/span&gt;        }&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;可见每次都会Load时重新构造并调用ViewModel构造方法.考虑可以把组合关系代码放在这.CompositionInitializer对象提供了对MEF容器的静态方法控制.当然我们也可以像上篇一样显示的定义一个CompositionContainer 容器的方式直接管理. 可以把原ViewModel中代码替换成:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;div &gt;&#xD;
  &lt;pre &gt;&lt;span &gt;   1:  &lt;/span&gt;          &lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   2:  &lt;/span&gt;            &lt;span &gt;//显示建立关联关系&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   3:  &lt;/span&gt;            AggregateCatalog mefCatalog = &lt;span &gt;new&lt;/span&gt; AggregateCatalog();&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   4:  &lt;/span&gt;            mefCatalog.Catalogs.Add(&lt;span &gt;new&lt;/span&gt; AssemblyCatalog(Application.Current.GetType().Assembly));&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   5:  &lt;/span&gt;            mefCatalog.Catalogs.Add(&lt;span &gt;new&lt;/span&gt; AssemblyCatalog(&lt;span &gt;typeof&lt;/span&gt;(MEFCommon.Data.IAppCatalog).Assembly));&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre &gt;&lt;span &gt;   7:  &lt;/span&gt;            CompositionContainer mefContainer = &lt;span &gt;new&lt;/span&gt; CompositionContainer(mefCatalog);&lt;/pre&gt;&#xD;
&#xD;
  &lt;pre&gt;&lt;span &gt;   8:  &lt;/span&gt;            mefContainer.ComposeParts(&lt;span &gt;this&lt;/span&gt;);&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;通过AggregateCAtalog显示指定MEF解析类型需要检索的位置范围。编译运行发现效果是一致的.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;关于这两种方式.最简洁使用就是CompositionInitializer对象提供静态控制.把更多的工作交给MEF自身去做. 另外一个好处就是可以随时随地在程序中添加MEF组合关系和检索位置的范围.这是显示定义CompositionContainer 容器方式所无法直接做到的.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;Well关于MEF终于历经多次验证终于能够成功运行在Windows phone应用程序中.本篇只是介绍简单使用方法.目的是抛砖引玉.体现MEF也能够在Windows phone扩展组件能力和灵活的方式都值得我们在实际项目加以实践. 算是提出MEF 在Windows phone中使用一种解决方案.如果任何问题请在评论中提出.如下会给出本篇实例源码和MASF MEF For windows phone版本的DLL.&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;本篇实例代码:&lt;a href="http://files.cnblogs.com/chenkai/MEFSampleDemo.rar"&gt;/Files/chenkai/MEFSampleDemo.rar&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;MEF For windows Phone DLL文件:&lt;a href="http://files.cnblogs.com/chenkai/ComponentModelDLL.rar"&gt;/Files/chenkai/ComponentModelDLL.rar&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;参考资料:&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://www.damonpayne.com/post/2010/06/25/MEF-for-Windows-Phone-7.aspx" target="_blank"&gt;MEF For Windows phone 7 By DAmon Payne&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="https://github.com/mefcontrib" target="_blank"&gt;MEF Contrib [Github]&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;font face="Consolas"&gt;&lt;a href="http://msaf.codeplex.com/" target="_blank"&gt;Microsoft Silverlight Analyics FrameWork Codeplex&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chenkai/aggbug/2305324.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chenkai/archive/2011/12/28/2305324.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
