<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>编程 on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/%E7%BC%96%E7%A8%8B/</link>
    <description>Recent content in 编程 on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sun, 06 Nov 2016 14:40:03 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/%E7%BC%96%E7%A8%8B/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>graylog中的mongodb配置</title>
      <link>http://blog.leaver.me/2016/11/06/graylog%E4%B8%AD%E7%9A%84mongodb%E9%85%8D%E7%BD%AE/</link>
      <pubDate>Sun, 06 Nov 2016 14:40:03 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/11/06/graylog%E4%B8%AD%E7%9A%84mongodb%E9%85%8D%E7%BD%AE/</guid>
      <description>&lt;p&gt;接手的一个工具平台,发现 graylog 集群使用了单个的 mongodb 作为数据库,于是需要配置一下集群,来防止数据丢失,毕竟很多配置都在里面.&lt;/p&gt;
&lt;p&gt;为了以防万一,先备份一下 graylog 的配置.
&lt;code&gt;mongodump -h dbhost -d dbname -o dbdirectory&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;防止分布式部署的使用搞坏了.之后的恢复可以使用&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mongorestore -h dbhost -d dbname --directoryperdb dbdirectory&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;来恢复.相关说明可以参考&lt;a href=&#34;http://www.runoob.com/mongodb/mongodb-mongodump-mongorestore.html&#34;&gt;这里&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;之后就可以正式开始了&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;修改集群名字&lt;/p&gt;
&lt;p&gt;在/etc/mongod.conf 中,修改这个值.设置集群使用的集群名称是 graylog,几个机器都配置一下.都先不要启动&lt;/p&gt;
&lt;p&gt;replication:
replSetName: graylog&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;然后添加集群配置&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;启动其中一台,然后通过mongo 命令连接上数据库,依次执行下面的命令.注意,这里有个坑.添加本机的时候,一定要写对外的域名或者 ip.否则会导致无法选主.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; rs.initiate()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; rs.add(&amp;#34;&amp;lt;hostname&amp;gt;:27017&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; rs.add(&amp;#34;&amp;lt;hostname&amp;gt;:27017&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; rs.add(&amp;#34;&amp;lt;hostname&amp;gt;:27017&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; rs.conf()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;开始启动&lt;/p&gt;
&lt;p&gt;这里启动就不用说了. &lt;code&gt;service mongod start&lt;/code&gt; 启动就好了.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置 graylog 集群连接地址&lt;/p&gt;
&lt;p&gt;在/etc/graylog/server/server.conf 中配置.mongodb_uri = mongodb://host1,host2,host3/graylog&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;后面这个 graylog 就是给 graylog 使用的库名,你可以先创建.&lt;/p&gt;
&lt;p&gt;之后mongodb 就开始自行同步了.&lt;/p&gt;
&lt;p&gt;[参考]&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.jianshu.com/p/2825a66d6aed&#34;&gt;高可用的MongoDB集群&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;</description>
    </item>
    <item>
      <title>AngularJS 学习资源</title>
      <link>http://blog.leaver.me/2015/08/08/angularjs-%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%BA%90/</link>
      <pubDate>Sat, 08 Aug 2015 21:48:31 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/08/08/angularjs-%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%BA%90/</guid>
      <description>&lt;p&gt;一直对AngularJS很好奇,之前看过国内某在线网站的一套AngularJS教程,可惜没看懂.也没理解为了解决什么问题,只是知道是个前端JS框架.这周看到个Udemy - Learn and Understand AngularJS 这个教程.去看了一下,是收费的.强烈推荐看.无字幕,但是不难,已经看完了.讲的非常非常好.网上有别人分享的.我给个&lt;a href=&#34;magnet:?xt=urn:btih:900a5d5f6535bcf956cba5248ffce416d150a7fc&#34;&gt;磁力链接&lt;/a&gt;吧.&lt;/p&gt;
&lt;p&gt;01 Getting Started&lt;/p&gt;
&lt;p&gt;02 Model, View, Whatever___&lt;/p&gt;
&lt;p&gt;03 Services and Dependency Injection&lt;/p&gt;
&lt;p&gt;04 Data Binding and Directives&lt;/p&gt;
&lt;p&gt;05 Single Page Applications&lt;/p&gt;
&lt;p&gt;06 Custom Services&lt;/p&gt;
&lt;p&gt;07 Custom Directives&lt;/p&gt;
&lt;p&gt;08 Lets Build an App in record time&lt;/p&gt;
&lt;p&gt;09 BONUS Lectures&lt;/p&gt;
&lt;p&gt;10 Getting Ready for AngularJS 2.0 in 2016&lt;/p&gt;
&lt;p&gt;11 Conclusion&lt;/p&gt;
&lt;p&gt;非常的介绍.看完之后,你会理解AngularJS解决了什么问题,他的数据绑定怎么使用,模块怎么弄,怎么写服务,怎么定义指令等等.强烈推荐.&lt;/p&gt;
&lt;p&gt;最好有一点js和css的基础会比较好理解.如果懂后端开发的就更好了.依赖注入这些有点基础会比较好理解.&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用CSS3的自定义字体美化文字</title>
      <link>http://blog.leaver.me/2013/07/17/%E4%BD%BF%E7%94%A8css3%E7%9A%84%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AD%97%E4%BD%93%E7%BE%8E%E5%8C%96%E6%96%87%E5%AD%97/</link>
      <pubDate>Wed, 17 Jul 2013 14:45:45 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/07/17/%E4%BD%BF%E7%94%A8css3%E7%9A%84%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AD%97%E4%BD%93%E7%BE%8E%E5%8C%96%E6%96%87%E5%AD%97/</guid>
      <description>&lt;p&gt;之前看到一些设计师的主题的字体很美，下载下来发现使用了css3的自定义字体，可以用来显示服务器上的字体，非常方便，学习了一下&lt;/p&gt;
&lt;p&gt;1.首先得到字体&lt;/p&gt;
&lt;p&gt;这个方法很多，本机的字体，一些国外的免费网站，比如这个：&lt;a href=&#34;http://www.dafont.com/&#34;&gt;http://www.dafont.com&lt;/a&gt;，下载后的字体一般为ttf格式，ttf字体被很多浏览器支持，但是，IE不支持，为了兼容性，需要为IE单独设置字体文件，格式必须为eot，所以我们需要转换字体，使用在线工具，比如&lt;a href=&#34;http://www.kirsle.net/wizards/ttf2eot.cgi&#34;&gt;http://www.kirsle.net/wizards/ttf2eot.cgi&lt;/a&gt;，当然类似的网站有很多，根据个人爱好，随意。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;2.添加内容&lt;/p&gt;
&lt;p&gt;这里，我写一个简单的html文件，内容为&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;body&amp;gt;
&amp;lt;p class=&#34;test&#34;&amp;gt;bystander&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;&lt;/pre&gt;
&lt;p&gt;在没有设置customFont这个类的css之前，字体就是默认的字体了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;3.设置css样式&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;@font-face
{
font-family:myFont;/*主流浏览器可用*/
src:url(&#34;PONCTUATION.ttf&#34;);
}
@font-face
{
font-family:myFont;/*兼容IE*/
src:url(&#34;PONCTUATION.eot&#34;);
}
.test
{
font-family:myFont;
font-size:40px;
}&lt;/pre&gt;
&lt;p&gt;显示效果就是这样的了&amp;hellip;只是用来演示的一个字体。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/38421_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/0aa0db5ed4bc986d61cfbb9e1e421a2226c94f9b.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;因为浏览器是要自动下载这个字体文件的，所以对于英文字体没啥问题，英文字体一般这个字体文件在100k左右，和一张图片比起来，基本算不是问题，但是对于中文字体，包一般在10M-20M左右，这样是不现实的，我的想法是，可以自己制作字体包，这样只需要满足常用的一些汉字就行了，大大减少包的大小，然后去找了一下，发现了&lt;a href=&#34;http://www.high-logic.com/font-editor/fontcreator.html&#34;&gt;http://www.high-logic.com/font-editor/fontcreator.html&lt;/a&gt;这个软件，是可以直接编辑字体包的，也可以创建字体包，有空了用来试试.&lt;/p&gt;</description>
    </item>
    <item>
      <title>引用和指针(C&#43;&#43;)</title>
      <link>http://blog.leaver.me/2013/05/22/%E5%BC%95%E7%94%A8%E5%92%8C%E6%8C%87%E9%92%88c/</link>
      <pubDate>Wed, 22 May 2013 16:16:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/22/%E5%BC%95%E7%94%A8%E5%92%8C%E6%8C%87%E9%92%88c/</guid>
      <description>&lt;p&gt;今天在整理收藏夹的时候，又看到了这两篇非常不错的文章，关于指针和引用的，我就不翻译了，文章很简单，不过把其中我觉得很有意思的两部分结合我的理解希望说的更清楚,假定你读这篇文章之前已经知道指针，但是不是很清楚其中的部分。&lt;/p&gt;
&lt;p&gt;首先是关于指针的一个直观的一个认识.&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &amp;lt;iostream&amp;gt;

int main()
{
  using namespace std;

// 声明并初始化指针.
  unsigned short int * pPointer = 0;
// 定义一个unsigned short int 变量 值为35698
  unsigned short int twoInt = 35698;
// 定义一个unsigned short int 变量 值为 77
  unsigned short int oneInt = 77;
// 使用&amp;amp;操作符将twoInt的地址赋给指针
  pPointer = &amp;amp;twoInt;
// pPointer 现在的值就是twoInt的地址了

// 打印
  cout &amp;lt;&amp;lt; &#34;pPointer的内存地址:\t\t&#34; &amp;lt;&amp;lt; &amp;amp;pPointer &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &#34;oneInt的内存地址:\t&#34; &amp;lt;&amp;lt; &amp;amp;oneInt &amp;lt;&amp;lt; &#34;\t整数值:\t&#34; &amp;lt;&amp;lt; oneInt &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &#34;twoInt的内存地址:\t&#34; &amp;lt;&amp;lt; &amp;amp;twoInt &amp;lt;&amp;lt; &#34;\t整数值:\t&#34; &amp;lt;&amp;lt; twoInt &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &#34;pPointer所指向的地址(也就是pPoint的值):\t&#34; &amp;lt;&amp;lt; pPointer &amp;lt;&amp;lt; &#34;\t整数值:\t&#34; &amp;lt;&amp;lt; *pPointer &amp;lt;&amp;lt; endl;

return 0;
}&lt;/pre&gt;
&lt;p&gt;上面这段代码，声明了一个指针，和两个整数，指针指向第一个整数，然后输出结果（每个人的输出结果不一样）是：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;pPointer的内存地址:                   0xbff43314
oneInt的内存地址:                     0xbff43318       整数值:  77
twoInt的内存地址:                     0xbff4331a       整数值:  35698
pPointer所指向的地址(也就是pPoint的值): 0xbff4331a       整数值:  35698&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/36294_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ef97273d51f6843eb062463a3091a8edb177b30e.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这张图是这几个变量的内存分布图，上面一排是内存地址编号，正对我们的是该处的值&lt;/p&gt;
&lt;p&gt;指针pPointer这个变量从最左边0xbff43314这个内存位置开始，占用了四个字节，这个一个指针占四个字节，大家都知道的，这个变量的值是一个地址，也就是他的指向地址。&lt;/p&gt;
&lt;p&gt;pPointer 所指向的地址呢，是一个short int 类型的值所在的位置，在这里就是我们的twoint，twoint在内存中呢，是从0xbff4331a开始的，也就是说，我们的pPointer指向了twoint所在的地址，&lt;/p&gt;
&lt;p&gt;注意，看一下左边四个方块前面的二进制数，转换成16进制就是0xbff4331a了&lt;/p&gt;
&lt;p&gt;因此，取指针所指向的值就是35698了。指针本身的值则是0xbff4331a，指针所在的位置是0xbff43314。&lt;/p&gt;
&lt;p&gt;参考文章：&lt;a href=&#34;http://linuxconfig.org/c-understanding-pointers&#34;&gt;C++ : Understanding pointers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;另一个呢是关于引用的实现原理&lt;/p&gt;
&lt;p&gt;大家都知道，引用就是别名，比如下面这段代码&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int main() {
   int number = 88;          // 定义一个int变量
   int &amp;amp; refNumber = number; // 声明并初始化一个引用
                             // 现在他们都表示了同一个值

   cout &amp;lt;&amp;lt; number &amp;lt;&amp;lt; endl;    // 打印number的值 (88)
   cout &amp;lt;&amp;lt; refNumber &amp;lt;&amp;lt; endl; // 打印引用的值 (88)

   refNumber = 99;            // 给refNumber重新赋一个值
   cout &amp;lt;&amp;lt; refNumber &amp;lt;&amp;lt; endl;
   cout &amp;lt;&amp;lt; number &amp;lt;&amp;lt; endl;    // number的值也就变成了 (99)

   number = 55;               // 重新给number赋一个值
   cout &amp;lt;&amp;lt; number &amp;lt;&amp;lt; endl;
   cout &amp;lt;&amp;lt; refNumber &amp;lt;&amp;lt; endl; // refNumber也就变成了(55)
}&lt;/pre&gt;
&lt;p&gt;输出结果肯定一目了然，其中的原理想过没&lt;/p&gt;</description>
    </item>
    <item>
      <title>倒水问题求解(C&#43;&#43;)</title>
      <link>http://blog.leaver.me/2013/05/15/%E5%80%92%E6%B0%B4%E9%97%AE%E9%A2%98%E6%B1%82%E8%A7%A3c/</link>
      <pubDate>Wed, 15 May 2013 18:37:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/15/%E5%80%92%E6%B0%B4%E9%97%AE%E9%A2%98%E6%B1%82%E8%A7%A3c/</guid>
      <description>&lt;p&gt;明天要去参加微软面试，不求顺利，但求体验。&lt;/p&gt;
&lt;p&gt;这个题目答题的意思是:&lt;/p&gt;
&lt;p&gt;给你一个容量为A升的桶和一个容量为B升的桶，水不限使用，要求精确得到Q升水.请说明步骤&lt;/p&gt;
&lt;p&gt;当数字比较小的时候,我们可以通过大脑穷举来得到结果,但这里有两个问题,当数字很大的时候怎么解?题目给定的数据是否有解?&lt;/p&gt;
&lt;p&gt;首先判断是否有解?&lt;/p&gt;
&lt;p&gt;题目可以理解为,x为用A的次数,y为用B的次数,Q为目标值&lt;/p&gt;
&lt;p&gt;Q = A * x + B * y
Q =目标值.&lt;/p&gt;
&lt;p&gt;Q必须是 Gcd(A,B)(也就是A,B的最大公约数)的倍数,否则无解,如果 Gcd(A,B) == 1, 任何Q都是可解的&lt;/p&gt;
&lt;p&gt;最简单的方法就是把A的水不断的向B中倒(B向A中倒也行),知道得到最终结果,如果桶满了,就清空该桶.举个例子&lt;/p&gt;
&lt;p&gt;A = 3, B = 4 并且 Q = 2
重复得从 A-&amp;gt;B&lt;/p&gt;
&lt;p&gt;A B&lt;/p&gt;
&lt;h6&gt;&lt;/h6&gt;
&lt;p&gt;0 0
4 0
1 3
1 0
0 1
4 1
2 3 &amp;lt;-A桶中得到2了&lt;/p&gt;
&lt;p&gt;试试从  B-&amp;gt;A&lt;/p&gt;
&lt;p&gt;A B&lt;/p&gt;
&lt;h5&gt;&lt;/h5&gt;
&lt;p&gt;0 0
0 3
3 0
3 3
4 2 &amp;lt;- B中也得到了2
但是注意,从 B-&amp;gt;A 比从 A-&amp;gt;B快哦&lt;/p&gt;
&lt;p&gt;然后我贴出代码&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &#34;stdafx.h&#34;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include&amp;lt;string&amp;gt;

using namespace std;

//热门智力题 - 打水问题
//基本思想：用A桶容量的倍数对B桶的容量进行取余。
//指导方针：不断用A桶装水倒入B桶，B桶满了立即清空
//每次判断下二个桶中水的容量是否等于指定容量。
const string OPERATOR_NAME[7] = {
	&#34;装满A桶&#34;,
	&#34;装满B桶&#34;,
	&#34;将A桶清空&#34;,
	&#34;将B桶清空&#34;,
	&#34;A桶中水倒入B桶&#34;,
	&#34;B桶中水倒入A桶&#34;,
	&#34;成功得到结果&#34;
};
int max(int a,int b)
{
	return a&amp;gt;b?a:b;
}
int gcd(int m,int n)
{
	int temp,p,r;
	//n存放最小数，m存放最大数
	if(n&amp;gt;m){
		temp = n;
		n = m;
		m = temp;
	}
	p=n*m;//先取得两个数的积
	while(n!=0){
		r=m%n;
		m=n;
		n=r;
	}
return m;
}
int _tmain(int argc, _TCHAR* argv[])
{
	int    a_capacity, b_capacity, goal_capacity;
	vector&amp;lt;string&amp;gt; record;       //记录操作过程
	int a_water, b_water;

	cout&amp;lt;&amp;lt;&#34;请输入A桶容量，B桶容量，目标容量Q：&#34;;
	cin&amp;gt;&amp;gt;a_capacity&amp;gt;&amp;gt;b_capacity&amp;gt;&amp;gt;goal_capacity;
	a_water = b_water = 0; //A桶，B桶中有多少升水

	//判断是否一定可解
	if (a_capacity&amp;lt;=0 || b_capacity&amp;lt;=0 || goal_capacity&amp;lt;=0)
	{
		cout&amp;lt;&amp;lt;&#34;请保证所以容量大于0&#34;&amp;lt;&amp;lt;endl;
		return -1;
	}
	if (goal_capacity&amp;gt;max(a_capacity,b_capacity))
	{
		cout&amp;lt;&amp;lt;&#34;要量出的容量应该小于其中桶容量&#34;&amp;lt;&amp;lt;endl;
		return -2;
	}
	//如果可解则解之
	if(goal_capacity%gcd(a_capacity,b_capacity)==0)
	{
		//存放临时的字符串构造
		char szTemp[30];
		while (true)
		{
			if (a_water == 0)//A桶没水,就装满水
			{
				a_water = a_capacity;
				sprintf(szTemp, &#34;         A:%d  B:%d&#34;, a_water, b_water);
				record.push_back(OPERATOR_NAME[0] + szTemp);//先填满 A桶
			}
			else
			{
				//如果A桶的水比(B桶容量-B桶的水)要多，也就是多于没装满的B桶空出来的部分，A桶会剩下
				if (a_water &amp;gt; b_capacity - b_water)
				{
					//A桶向B桶倒水直到B桶满，此时A桶的水==A桶的水+B桶的水-B桶容量
					a_water = a_water + b_water- b_capacity;
					b_water = b_capacity;		 //B桶的水装满了
					sprintf(szTemp, &#34;  A:%d  B:%d&#34;, a_water, b_water); 
					record.push_back(OPERATOR_NAME[4] + szTemp);//A-&amp;gt;B	
					if (a_water == goal_capacity)
						break;
					b_water = 0;			//将B桶清空
					sprintf(szTemp, &#34;       A:%d  B:%d&#34;, a_water, b_water); 
					record.push_back(OPERATOR_NAME[3] + szTemp);
				}
				else
				{
					//A桶小于装满B桶需要的水，此时B桶的水==A桶的水+B桶的水
					b_water += a_water;	
					a_water = 0;
					sprintf(szTemp, &#34;  A:%d  B:%d&#34;, a_water, b_water);
					record.push_back(OPERATOR_NAME[4] + szTemp);//A-&amp;gt;B
					if (b_water == goal_capacity) 
						break;
				}
			}
		}
		record.push_back(OPERATOR_NAME[6]);	//break出来说明成功了
		cout&amp;lt;&amp;lt;&#34;\n---------------------------------------------------&#34;&amp;lt;&amp;lt;endl;
		cout&amp;lt;&amp;lt;&#34;以下下是一种方案&#34;&amp;lt;&amp;lt;endl;
		vector&amp;lt;string&amp;gt;::iterator pos;
		for (pos = record.begin(); pos != record.end(); pos++)
			cout&amp;lt;&amp;lt;*pos&amp;lt;&amp;lt;endl;
		cout&amp;lt;&amp;lt;&#34;---------------------------------------------------&#34;&amp;lt;&amp;lt;endl;
	}
	else
	{
		cout&amp;lt;&amp;lt;&#34;此情况下无解&#34;&amp;lt;&amp;lt;endl;
	}

	return 0;
}&lt;/pre&gt;
&lt;p&gt;运行结果如下：&lt;/p&gt;</description>
    </item>
    <item>
      <title>模板优先级队列及堆排序(C&#43;&#43;实现)</title>
      <link>http://blog.leaver.me/2013/04/16/%E6%A8%A1%E6%9D%BF%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97%E5%8F%8A%E5%A0%86%E6%8E%92%E5%BA%8Fc-%E5%AE%9E%E7%8E%B0/</link>
      <pubDate>Tue, 16 Apr 2013 08:42:58 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/04/16/%E6%A8%A1%E6%9D%BF%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97%E5%8F%8A%E5%A0%86%E6%8E%92%E5%BA%8Fc-%E5%AE%9E%E7%8E%B0/</guid>
      <description>&lt;p&gt;模板优先级队列，数组实现，再熟悉一下常用算法，同时简单的堆排序应用&lt;/p&gt;
&lt;p&gt;写了一个是队列自增长，另一个为了演示我还添加了一个叫做FillPq的方法，这个方法可以使用一个数组直接填充到优先级队列里，此时，优先级队列并不优先，然后进行下滤调整，之后建堆完成，输出即可&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &#34;stdafx.h&#34;

template&amp;lt; class T&amp;gt;
class PriorityQueue
{
private:
	 T *pq;
	 int N;
	 int capacity;
public:
	PriorityQueue(void);
	~PriorityQueue(void);
	void Insert(T x);
	T DelTop();
	void Swim(int k);
	void Sink(int k);
	bool Less(int i,int j);
	void Swap(int i,int j);
	bool Resize();
	void FillPq(T arr[],int size);
};

template&amp;lt; class T&amp;gt;
void PriorityQueue&amp;lt;T&amp;gt;::FillPq( T arr[],int size )
{
	N=size;
	capacity=2*size;
	for (int i=0;i&amp;lt;size;i++)
	{
		pq[i+1]=arr[i];
	}
}

template&amp;lt; class T&amp;gt;
PriorityQueue&amp;lt;T&amp;gt;::PriorityQueue(void)
{
	pq=new T[10];
	N=0;
	capacity=10;
}

template&amp;lt; class T&amp;gt;
void PriorityQueue&amp;lt;T&amp;gt;::Insert( T x )
{
	if (N==capacity)
	{
		Resize();
	}
	pq[++N]=x;
	Swim(N);
}

template&amp;lt; class T&amp;gt;
T PriorityQueue&amp;lt;T&amp;gt;::DelTop()
{
	T max=pq[1];
	Swap(1,N--);
	Sink(1);
	pq[N+1]=NULL;
	return max;
}
//下滤
template&amp;lt; class T&amp;gt;
void PriorityQueue&amp;lt;T&amp;gt;::Sink( int k )
{
	while (2*k&amp;lt;=N)
	{
		int j=2*k;
		if (j&amp;lt;N &amp;amp;&amp;amp; Less(j,j+1))
		{
			j++;
		}
		if (!Less(k,j))
		{
			break;
		}
		Swap(k,j);
		k=j;
	}
}
//上浮
template&amp;lt; class T&amp;gt;
void PriorityQueue&amp;lt;T&amp;gt;::Swim( int k )
{
	while (k&amp;gt;1 &amp;amp;&amp;amp; Less(k/2,k))
	{
		Swap(k,k/2);
	}
}

template&amp;lt; class T&amp;gt;
void PriorityQueue&amp;lt;T&amp;gt;::Swap( int i,int j )
{
	T temp=pq[i];
	pq[i]=pq[j];
	pq[j]=temp;
}

template&amp;lt; class T&amp;gt;
bool PriorityQueue&amp;lt;T&amp;gt;::Less( int i,int j )
{
	return pq[i]&amp;lt;pq[j];
}

template&amp;lt; class T&amp;gt;
bool PriorityQueue&amp;lt;T&amp;gt;::Resize()
{
	T *newPq=new T[capacity*2];
	capacity=capacity*2;
	for (int i=1;i&amp;lt;=N;i++)
	{
		newPq[i]=pq[i];
	}
	pq=newPq;
	return true;
}

template&amp;lt; class T&amp;gt;
PriorityQueue&amp;lt;T&amp;gt;::~PriorityQueue(void)
{
}&lt;/pre&gt;
&lt;p&gt;然后是堆排序&lt;/p&gt;</description>
    </item>
    <item>
      <title>模板栈以及中缀表达式求值(C&#43;&#43;实现)</title>
      <link>http://blog.leaver.me/2013/04/11/%E6%A8%A1%E6%9D%BF%E6%A0%88%E4%BB%A5%E5%8F%8A%E4%B8%AD%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BCc-%E5%AE%9E%E7%8E%B0/</link>
      <pubDate>Thu, 11 Apr 2013 18:50:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/04/11/%E6%A8%A1%E6%9D%BF%E6%A0%88%E4%BB%A5%E5%8F%8A%E4%B8%AD%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BCc-%E5%AE%9E%E7%8E%B0/</guid>
      <description>&lt;p&gt;栈直接用链表实现，这个比较简单，不多说，不过C++写程序，IDE的错误检测不是很给力。&lt;/p&gt;
&lt;p&gt;至于给定一个中缀表达式，如何不转换成后缀表达式，直接求值，方法就是使用两个栈，一个操作符栈，一个操作数栈，然后从左到右扫描表达式，我这里中缀表达式计算实现的很简单，不完整，大家可以扩展。栈的实现是我想写的，思路如下：&lt;/p&gt;
&lt;p&gt;1.如何是操作数，压入操作数栈&lt;/p&gt;
&lt;p&gt;2.如果是操作符，压入操作符栈&lt;/p&gt;
&lt;p&gt;3.如果是左括号，直接忽略&lt;/p&gt;
&lt;p&gt;4.如果是有括号，弹出操作符栈栈顶元素，然后弹出操作数栈两个元素，进行操作以后结果压入操作数栈&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;看个图就好了&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/34863_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d0b2eed86d2ba2b987d3e5db380b9a452e8f5f87.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;最后给出栈顶实现代码&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &#34;stdafx.h&#34;
#pragma region Node定义

template &amp;lt;class T&amp;gt;
class Node
{
	template&amp;lt;class T&amp;gt; 
	friend class Stack;
private:
	T m_data;
	Node *pNextNode;
public:
	Node();
	Node(T d);
};

template &amp;lt;class T&amp;gt;
Node&amp;lt;T&amp;gt;::Node()
{
	m_data=default(T);
	pNextNode=NULL;
}
template &amp;lt;class T&amp;gt;
Node&amp;lt;T&amp;gt;::Node(T d)
{
	m_data=d;
	pNextNode=NULL;
}
#pragma endregion 

#pragma region Stack定义

template &amp;lt;class T&amp;gt;
class Stack
{

private:
	Node&amp;lt;T&amp;gt; *m_pTopNode;
	int m_nNodeCount;
public:
	Stack();
	~Stack();
	bool IsEmpty();
	bool Push(T e);
	T Pop();
	int Size();
};

template &amp;lt;class T&amp;gt;
Stack&amp;lt;T&amp;gt;::Stack() : m_pTopNode(NULL),m_nNodeCount(0)
{
}

template &amp;lt;class T&amp;gt;
Stack&amp;lt;T&amp;gt;::~Stack()
{
	while (!IsEmpty())
	{
		Node&amp;lt;T&amp;gt; *pTempNode = m_pTopNode;
		m_pTopNode = m_pTopNode-&amp;gt;pNextNode;
		delete (pTempNode);
		pTempNode = NULL;
	}
	m_nNodeCount = 0;
	m_pTopNode = NULL;
}

template &amp;lt;class T&amp;gt;
bool Stack&amp;lt;T&amp;gt;::IsEmpty()
{
	return (m_pTopNode == NULL);
}

template &amp;lt;class T&amp;gt;
bool Stack&amp;lt;T&amp;gt;::Push(T e )
{
	Node&amp;lt;T&amp;gt; *pNewNode = new Node&amp;lt;T&amp;gt;(e);
	if (NULL == pNewNode)     {
		return false;
	}

	if(! IsEmpty()) {
		pNewNode-&amp;gt;pNextNode = m_pTopNode;
	}
	m_pTopNode = pNewNode;
	m_nNodeCount ++;

	return true;
}

template &amp;lt;class T&amp;gt;
T Stack&amp;lt;T&amp;gt;::Pop()
{
	if(IsEmpty()) {
		return T(-1);
	}
	T e;
	e = m_pTopNode-&amp;gt;m_data;
	Node&amp;lt;T&amp;gt; *pNode = m_pTopNode;
	m_pTopNode = m_pTopNode-&amp;gt;pNextNode;
	delete (pNode);
	m_nNodeCount--;

	return e;
}

template &amp;lt;class T&amp;gt;
int Stack&amp;lt;T&amp;gt;::Size()
{
	return m_nNodeCount;
}
#pragma endregion&lt;/pre&gt;
&lt;p&gt;然后是main函数代码&lt;/p&gt;</description>
    </item>
    <item>
      <title>并查集(C&#43;&#43;实现)</title>
      <link>http://blog.leaver.me/2013/04/11/%E5%B9%B6%E6%9F%A5%E9%9B%86c-%E5%AE%9E%E7%8E%B0/</link>
      <pubDate>Thu, 11 Apr 2013 08:45:38 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/04/11/%E5%B9%B6%E6%9F%A5%E9%9B%86c-%E5%AE%9E%E7%8E%B0/</guid>
      <description>&lt;p&gt;并查集这个很有意思，并查集是一种树型的数据结构，用于处理一些不相交集合（Disjoint Sets）的合并及查询问题。昨天看书看到了，然后用C++简单实现了下。在Dijkstra算法中，用来判断两个顶点是否在同一个集合里。&lt;/p&gt;
&lt;p&gt;里面定义了两个类，都是并查集，一个是QuickFind，查找很快，一个是QuickUnion，合并较快。写了一些注释，有一些优化的提示.看代码吧，有什么问题指出来吧。&lt;/p&gt;
&lt;p&gt;QuickFind的实现&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &#34;QuickFind.h&#34;

QuickFind::QuickFind(int N)
{
	size=N;
	id=new int[N];
	for(int i=0;i&amp;lt;N;i++)
	{
		id[i]=i;
	}
}

bool QuickFind::Find(int p,int q)
{
	return id[p]==id[q];
}

void QuickFind::Unite(int p,int q)
{
	int pid=id[p];
	for(int i=0;i&amp;lt;size;i++)
		if(id[i]==pid)
			id[i]=id[q];

}
QuickFind::~QuickFind(void)
{
	delete []id;
}&lt;/pre&gt;
&lt;p&gt;QuickUnion的实现&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &#34;QuickUnion.h&#34;

QuickUnion::QuickUnion(int N)
{
	size=N;
	id=new int[N];
	for(int i=0;i&amp;lt;N;i++)
	{
		id[i]=i;
	}
}
int QuickUnion::root(int i)
{
	while (i!=id[i])
	{
		//id[i]=id[id[i]]; 若添加这句话则为压缩路径
		i=id[i];
	}
	return i;
}
bool QuickUnion::Find(int p,int q)
{
	return root(p)==root(q);
}

void QuickUnion::Unite(int p,int q)
{
	//将p的根挂在q的根上，
	//这样会导此数变高，若需要优化，需要设置另一个
	//数组sz[]，sz[i]表示所以根为i的节点的数目，然后将
	//小树靠在大树上

	/*
	int i=root(p);
	int j=root(q);
	if(sz[i]&amp;lt;sz[j])
	{
		id[i]=j;sz[j]+=sz[i];
	}
	else
	{
		id[j]=i;sz[i]+=sz[j];
	}*/
	int rootp=root(p);
	int rootq=root(q);
	id[rootp]=rootq;
}
QuickUnion::~QuickUnion(void)
{
	delete []id;
}&lt;/pre&gt;
&lt;p&gt;参考文档(英文)：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=436984&amp;amp;uk=1493685990&#34;&gt;UnionFind.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;工程代码下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=436978&amp;amp;uk=1493685990&#34;&gt;并查集Demo&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#反射实现简单的插件系统</title>
      <link>http://blog.leaver.me/2013/02/21/c%23%E5%8F%8D%E5%B0%84%E5%AE%9E%E7%8E%B0%E7%AE%80%E5%8D%95%E7%9A%84%E6%8F%92%E4%BB%B6%E7%B3%BB%E7%BB%9F/</link>
      <pubDate>Thu, 21 Feb 2013 08:28:27 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/21/c%23%E5%8F%8D%E5%B0%84%E5%AE%9E%E7%8E%B0%E7%AE%80%E5%8D%95%E7%9A%84%E6%8F%92%E4%BB%B6%E7%B3%BB%E7%BB%9F/</guid>
      <description>&lt;p&gt;如果用过一些优秀的开源或是非开源的应用软件，就会发现这些软件的一个很大的优势就是其开放性，任何有能力的人都可以为其开发不同的插件来增强其的功能。比如著名的foobar2000，Vim和TotalCommander等等。&lt;/p&gt;
&lt;p&gt;C#的反射可以用来实现一个简单的插件系统。思路很简单，我们创建一个解决方案，包含三个工程，一个为我们的软件MyApplication，一个为插件接口IPlugin，一个为具体的插件MyPlugin。插件系统的基本思路是我们用一个接口类库,来定义我们软件可以使用的插件必须实现的方法签名。然后我们的软件MyApplication通过引用该IPlugin dll来动态调用，而具体的实现插件MyPlugin则引用该接口来实现具体的方法。这样我们的应用程序就能在不知道具体插件的情况下调用插件了。。&lt;/p&gt;
&lt;p&gt;结构图如下：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32896_o.jpg&#34;&gt;&lt;img alt=&#34;Myapplication&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bf202a9b50d5ce497f88718743c344d8579fadf1.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;关键代码也就是通过对程序集载入。搜索到对应接口的实现类。然后调用即可。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Assembly a = Assembly.LoadFrom(AssemblyName);
                foreach (Type t in a.GetTypes())
                {
                    if (t.GetInterface(&#34;IMyFunction&#34;) != null)
                    {
                        try
                        {
                            IMyFunction pluginclass = Activator.CreateInstance(t) as IMyFunction;
                            pluginclass.doSomething();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }
                    }
                }&lt;/pre&gt;
&lt;p&gt;运行结果：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32897_o.jpg&#34;&gt;&lt;img alt=&#34;QQ截图20130220200408&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/6c33ac761faef8c7d4beae4a478b4240cdeb7ee3.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;源码下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=302323&amp;amp;uk=1493685990&#34;&gt;PluginSystem.zip&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统中的文件系统</title>
      <link>http://blog.leaver.me/2013/01/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/</link>
      <pubDate>Thu, 31 Jan 2013 15:00:44 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;文件系统&lt;/strong&gt;
进程，地址空间，文件这些抽象概念均是操作系统中的重要概念，如果理解了这三个概念，就迈上了成为一个操作系统专家的道路。
文件系统存放在磁盘上，多数磁盘划分为一个/多个分区，每个分区有一个独立的文件系统，磁盘的0号扇区称为主引导记录，也就是MBR，用来引导计算机，MBR的结尾就是分区表了。该表给出了每个分区的起始和结束地址。表中的一个分区被标记为活动分区。在计算机被引导时，BIOS读入并执行MBR，MBR做的第一件事就是确定活动分区，读入他的第一个块，称为引导块，并执行之，引导块中的程度将装载该分区中的操作系统，为统一起见，每个分区都从一个启动块开始，即使它不含有一个可以启动的操作系统。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32257_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2e6edaf72b3ff2b35c5e98e4a1538ae14d74d858.png&#34;&gt;&lt;/a&gt;
&lt;strong&gt;文件的实现：&lt;/strong&gt;
1.连续分配，每个文件作为一连串连续数据存储在磁盘上。实现简单，读操作性能好，一次就可以了。但不足是删除之后不能移动，因为成本太高，使得空块增多。碎片化严重。更诡异的是对于文件编辑软件，实现无法准确预测大小，如果预测错了。。就跪了。
//研究那些具有清晰和简洁概念的老式系统和思想是很重要的，因为他们可能以一种令人吃惊的方式在未来系统中获得应用。&lt;/p&gt;
&lt;p&gt;2.链表分配
为每个文件构造磁盘块链表，一个文件分为N个文件块，N个文件块构成一个链表，存储在物理上的多个地方。顺序读取很方便，但随机读取则相当缓慢，由于指针的存在，每个磁盘块存储数据的字节不再是2的整数次幂，导致系统运行效率降低，因为很多程序都是以2的整数次幂来读写磁盘的。&lt;/p&gt;
&lt;p&gt;3.在内存中采用表的链表分配
去除每个文件块在磁盘上的指针字，放入内存的一个表上，就可以解决上一个分配的不足。直观的例子如图。
文件A使用了磁盘块4，7，2，10，12&lt;/p&gt;
&lt;p&gt;内存中这样的表格称为文件分配表，也就是FAT了。主要缺点是对于大磁盘的小块，这种表需要的内存占用太大。。不太适用。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32256_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b3afb8b5bedaaa50b38292cd6eb90a388d5081d1.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4.i节点
记录各个文件包含哪些磁盘块的方法是给每个文件赋予一个称为i节点的数据结构,其中类除了文件属性和文件块的磁盘地址.相对于在内存中采用表的方式,这种机制的优势在于只有对应文件打开时,其i节点才进入内存.&lt;/p&gt;
&lt;p&gt;文件系统的一致性检查分为两种:块的一致性检查和文件的一致性检查.构造两张表,一张跟踪块在文件中的出现次数,另一张跟踪该块在空闲表中的出现次数,如果一致,则某一块必然在两个表中1/2中为1,如果某一块没有出现在任何一张表中,则称为块丢失,浪费了磁盘空间.解决方法是让文件系统检验程序把他们加入到空闲表中
如果在空闲表中出现了两次.则重新建议建议空闲表即可.
如果在文件表中出现了两次.则比较麻烦.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文件系统性能&lt;/strong&gt;
1.高速缓存,最常用,指的是一系列的块,逻辑上属于磁盘.但实际上被保存在内存上.基本算法是检查全部的读请求,查看在高速缓存中是否有所需要的块,如果存在,就读,否则读入高速缓存在复制到其他地方.
2.块提前读,在需要用到块之前,试图提前将其写入高速缓存,从而提高命中率.比如某个文件有n个块,则请求k块的时候,则同时预读k+1块.只适用于顺序读取的文件,对随机读取文件,则没有效果/反效果.
3.减少磁盘臂运动
把所有可能顺序读取的块放在一起,当然最好是放在同一个柱面上,从而减少磁盘臂的移动次数.&lt;/p&gt;</description>
    </item>
    <item>
      <title>远程管理Demo(C#)</title>
      <link>http://blog.leaver.me/2013/01/04/%E8%BF%9C%E7%A8%8B%E7%AE%A1%E7%90%86democ/</link>
      <pubDate>Fri, 04 Jan 2013 15:18:06 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/04/%E8%BF%9C%E7%A8%8B%E7%AE%A1%E7%90%86democ/</guid>
      <description>&lt;p&gt;一个C#的通信的例子&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31142_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8a608877e1ae0aef14d26fea8260f247bbb7ee33.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;1.服务端，服务端通过ip和端口生成客户端之后，点击开始监听后，便开启监听线程持续监听，同时注册断开连接和收到信息的事件。收到来自TcpClient 流中的信息后，解析之，如果是连接信息，就添加到连接列表，这样服务端就可以显示多个客户端了。如果是断开信息，就删掉。如果服务端想要给客户端发消息，就选中该客户，然后填写信息，就会调用连接类的发送方法。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;2.客户端，也就是被控端，被控端通过tcp连接到远端ip，然后发送连接成功状态，随后异步读取。读取到信息后调用解析方式。然后处理。。&lt;/p&gt;
&lt;p&gt;3.服务端如何生成客户端。其实也比较简单。就是写好客户端以后，保存为文本。然后通过CodeDomProvider的相关方法来编译即可。代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt; public static bool Compile(string EXE_Name, string Source)
        {
            CodeDomProvider Compiler = CodeDomProvider.CreateProvider(&#34;CSharp&#34;);
            CompilerParameters Parameters = new CompilerParameters();
            CompilerResults cResults = default(CompilerResults);

            Parameters.GenerateExecutable = true;
            Parameters.OutputAssembly = EXE_Name;
            Parameters.ReferencedAssemblies.Add(&#34;System.dll&#34;);
            Parameters.CompilerOptions = &#34; /target:winexe&#34;;
            Parameters.TreatWarningsAsErrors = false;

            cResults = Compiler.CompileAssemblyFromSource(Parameters, Source);

            if (cResults.Errors.Count &amp;gt; 0)
            {
                foreach (CompilerError CompilerError_loopVariable in cResults.Errors)
                {
                    CompilerError error = CompilerError_loopVariable;
                    MessageBox.Show(&#34;Error: &#34; + error.ErrorText, &#34;&#34;, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return false;
            }
            else if (cResults.Errors.Count == 0)
            {
                return true;
            }
            return true;
        }&lt;/pre&gt;
&lt;p&gt;源码下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=223714&amp;amp;uk=1493685990&#34;&gt;CSharp RAT Example.zip&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>如何创建WPF用户控件&amp;在WPF项目中使用</title>
      <link>http://blog.leaver.me/2012/10/14/%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BAwpf%E7%94%A8%E6%88%B7%E6%8E%A7%E4%BB%B6%E5%9C%A8wpf%E9%A1%B9%E7%9B%AE%E4%B8%AD%E4%BD%BF%E7%94%A8/</link>
      <pubDate>Sun, 14 Oct 2012 15:19:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/14/%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BAwpf%E7%94%A8%E6%88%B7%E6%8E%A7%E4%BB%B6%E5%9C%A8wpf%E9%A1%B9%E7%9B%AE%E4%B8%AD%E4%BD%BF%E7%94%A8/</guid>
      <description>&lt;p&gt;作者给的Demo我合并了下。VS2010直接打开解决方案。二者都有。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28121_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/82f9a2b2665cf35702e252f3518a2f420361da11.png&#34; title=&#34;00&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;
本文展示在WPF中如何创建用户控件并且如果在WPF项目中使用。我将使用VS2008和C#来展示如何创建一个自定义的ToolTip&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这篇由&lt;a href=&#34;http://www.codeproject.com/KB/WPF/WPF_CustomerControl.aspx&#34;&gt;Sacha Barber&lt;/a&gt;.写的和我的有点像。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;开始。首先，我们创建一个用户控件。因此，我们选择新建WPF用户控件类库（WPF User Control Library）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28122_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/920a78558c2e8a260f9fd448739f68cd80e37108.png&#34; title=&#34;01&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;现在。我们可以创建或者编辑XAML代码来创建自定义的用户控件了。我使用XAML来创建自定义的ToolTip。你想做什么随你。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;UserControl 
    Name=&#34;UserControlToolTip&#34;
    x:Class=&#34;CustomToolTip.UserControl1&#34;
    xmlns=&#34;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#34;
    xmlns:x=&#34;http://schemas.microsoft.com/winfx/2006/xaml&#34;
    xmlns:d=&#34;http://schemas.microsoft.com/expression/blend/2008&#34; 
    xmlns:mc=&#34;http://schemas.openxmlformats.org/markup-compatibility/2006&#34; 
    mc:Ignorable=&#34;d&#34; RenderTransformOrigin=&#34;0,0&#34; HorizontalAlignment=&#34;Left&#34; 
	VerticalAlignment=&#34;Top&#34; &amp;gt;

    &amp;lt;UserControl.RenderTransform&amp;gt;
        &amp;lt;TransformGroup&amp;gt;
            &amp;lt;ScaleTransform ScaleX=&#34;1&#34; ScaleY=&#34;1&#34;/&amp;gt;
            &amp;lt;SkewTransform AngleX=&#34;0&#34; AngleY=&#34;0&#34;/&amp;gt;
            &amp;lt;RotateTransform Angle=&#34;0&#34;/&amp;gt;
            &amp;lt;TranslateTransform x:Name=&#34;UserControlToolTipXY&#34; X=&#34;0&#34; Y=&#34;0&#34;/&amp;gt;
        &amp;lt;/TransformGroup&amp;gt;
    &amp;lt;/UserControl.RenderTransform&amp;gt;

    &amp;lt;Grid HorizontalAlignment=&#34;Center&#34; VerticalAlignment=&#34;Center&#34; 
	MinWidth=&#34;200&#34; MinHeight=&#34;120&#34;&amp;gt;
    	&amp;lt;Grid.RowDefinitions&amp;gt;
    		&amp;lt;RowDefinition Height=&#34;0.333*&#34;/&amp;gt;
    		&amp;lt;RowDefinition Height=&#34;0.667*&#34;/&amp;gt;
    	&amp;lt;/Grid.RowDefinitions&amp;gt;
        &amp;lt;Rectangle Fill=&#34;#FFFBFBFB&#34; Stroke=&#34;#FF000000&#34; RadiusX=&#34;10&#34; RadiusY=&#34;10&#34;
        	 RenderTransformOrigin=&#34;0.139,0.012&#34; StrokeThickness=&#34;1&#34; Grid.RowSpan=&#34;2&#34;&amp;gt;
            &amp;lt;Rectangle.BitmapEffect&amp;gt;
                &amp;lt;DropShadowBitmapEffect Opacity=&#34;0.8&#34;/&amp;gt;
            &amp;lt;/Rectangle.BitmapEffect&amp;gt;
        &amp;lt;/Rectangle&amp;gt;
        &amp;lt;Rectangle RadiusX=&#34;10&#34; RadiusY=&#34;10&#34; RenderTransformOrigin=&#34;0.139,0.012&#34; 
        	StrokeThickness=&#34;10&#34; Stroke=&#34;{x:Null}&#34; 
	Margin=&#34;1,1,1,1&#34; Grid.Row=&#34;0&#34; Grid.RowSpan=&#34;2&#34;&amp;gt;
        	&amp;lt;Rectangle.Fill&amp;gt;
        		&amp;lt;LinearGradientBrush EndPoint=&#34;0.5,1&#34; StartPoint=&#34;0.5,0.725&#34;&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#00E6D9AA&#34; Offset=&#34;0.487&#34;/&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#FFE6D9AA&#34; Offset=&#34;0.996&#34;/&amp;gt;
        		&amp;lt;/LinearGradientBrush&amp;gt;
        	&amp;lt;/Rectangle.Fill&amp;gt;
        &amp;lt;/Rectangle&amp;gt;
        &amp;lt;Rectangle RadiusX=&#34;10&#34; RadiusY=&#34;10&#34; RenderTransformOrigin=&#34;0.493,0.485&#34; 
        	StrokeThickness=&#34;10&#34; Stroke=&#34;{x:Null}&#34; Grid.RowSpan=&#34;2&#34; Margin=&#34;1,1,1,1&#34;&amp;gt;
        	&amp;lt;Rectangle.Fill&amp;gt;
        		&amp;lt;LinearGradientBrush EndPoint=&#34;0.014,0.5&#34; StartPoint=&#34;0.211,0.5&#34;&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#00E6D9AA&#34; Offset=&#34;0.513&#34;/&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#FFE6D9AA&#34; Offset=&#34;0.996&#34;/&amp;gt;
        		&amp;lt;/LinearGradientBrush&amp;gt;
        	&amp;lt;/Rectangle.Fill&amp;gt;
        &amp;lt;/Rectangle&amp;gt;
        &amp;lt;Rectangle RadiusX=&#34;10&#34; RadiusY=&#34;10&#34; RenderTransformOrigin=&#34;0.493,0.485&#34; 
        	StrokeThickness=&#34;10&#34; Stroke=&#34;{x:Null}&#34; Grid.RowSpan=&#34;2&#34; Margin=&#34;1,1,1,1&#34;&amp;gt;
        	&amp;lt;Rectangle.Fill&amp;gt;
        		&amp;lt;LinearGradientBrush EndPoint=&#34;0.493,0.002&#34; StartPoint=&#34;0.493,0.33&#34;&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#00E6D9AA&#34; Offset=&#34;0.513&#34;/&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#FFE6D9AA&#34; Offset=&#34;0.996&#34;/&amp;gt;
        		&amp;lt;/LinearGradientBrush&amp;gt;
        	&amp;lt;/Rectangle.Fill&amp;gt;
        &amp;lt;/Rectangle&amp;gt;
        &amp;lt;Rectangle RadiusX=&#34;10&#34; RadiusY=&#34;10&#34; RenderTransformOrigin=&#34;0.493,0.485&#34; 
        	StrokeThickness=&#34;10&#34; Stroke=&#34;{x:Null}&#34; Grid.RowSpan=&#34;2&#34; Margin=&#34;1,1,1,1&#34;&amp;gt;
        	&amp;lt;Rectangle.Fill&amp;gt;
        		&amp;lt;LinearGradientBrush EndPoint=&#34;0.99,0.441&#34; StartPoint=&#34;0.794,0.441&#34;&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#00E6D9AA&#34; Offset=&#34;0.513&#34;/&amp;gt;
        			&amp;lt;GradientStop Color=&#34;#FFE6D9AA&#34; Offset=&#34;0.996&#34;/&amp;gt;
        		&amp;lt;/LinearGradientBrush&amp;gt;
        	&amp;lt;/Rectangle.Fill&amp;gt;
        &amp;lt;/Rectangle&amp;gt;
        &amp;lt;TextBlock Text=&#34;TextBlock&#34; TextWrapping=&#34;Wrap&#34; x:Name=&#34;TextBlockToolTip&#34; 
        	RenderTransformOrigin=&#34;0.5,0.5&#34; Grid.Row=&#34;1&#34; HorizontalAlignment=&#34;Left&#34; 
            	VerticalAlignment=&#34;Center&#34; Margin=&#34;20,0,0,20&#34; /&amp;gt;
        &amp;lt;TextBlock Name=&#34;ToolTipTitle&#34; HorizontalAlignment=&#34;Stretch&#34; Margin=&#34;15,16,15,6.1&#34; 
        	FontSize=&#34;14&#34; Text=&#34;title&#34; d:LayoutOverrides=&#34;Height&#34; /&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;同时。我们需要添加一些方法和属性来控制这些元素。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;namespace CustomToolTip
{
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        public double UserControlToolTipX
        {
            get { return this.UserControlToolTipXY.X; }
            set { this.UserControlToolTipXY.X = value; }
        }

        public double UserControlToolTipY
        {
            get { return this.UserControlToolTipXY.Y; }
            set { this.UserControlToolTipXY.Y = value; }
        }

        public string UserControlTextBlockToolTip
        {
            get { return TextBlockToolTip.Text; }
            set { TextBlockToolTip.Text = value; }
        }

        public string UserControlToolTipTitle
        {
            get { return ToolTipTitle.Text; }
            set { ToolTipTitle.Text = value; }
        }
    }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>WPF绘制圆角多边形</title>
      <link>http://blog.leaver.me/2012/10/13/wpf%E7%BB%98%E5%88%B6%E5%9C%86%E8%A7%92%E5%A4%9A%E8%BE%B9%E5%BD%A2/</link>
      <pubDate>Sat, 13 Oct 2012 09:45:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/13/wpf%E7%BB%98%E5%88%B6%E5%9C%86%E8%A7%92%E5%A4%9A%E8%BE%B9%E5%BD%A2/</guid>
      <description>&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;最近，我发现我需要个圆角多边形。而且是需要在运行时从用户界面来绘制。WPF有多边形。但是不支持圆角。我搜索了一下。也没找到可行的现成例子。于是就自己做吧。本文描述了圆角多边形的实现，也包括如何用在你的项目里。在Demo里面的RoundedCornersPolygon 类是完整的实现。&lt;/p&gt;
&lt;p&gt;下载的Demo包括两部分&lt;/p&gt;
&lt;p&gt;1. 通过XAML绘制圆角多边形&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28036_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/83dd3b37c81d0d4e1a82e80ba69d00411930ce52.png&#34; title=&#34;1&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2. 运行时创建圆角多边形&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28037_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/864fccf9677ea6ce52dad56c85cf7389108c6874.png&#34; title=&#34;2&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;
多边形可以被认为是沿着一个给定半径的圆的边缘和一些指定点/边。所构成的点的集合。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28038_o.gif&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/82969618833250386b07a5177dc8c454da0530e1.gif&#34; title=&#34;3&#34;&gt;&lt;/a&gt;
在WPF中。你可以给Polygon对象的Points属性添加一系列的点来制作多边形。&lt;/p&gt;
&lt;p&gt;XAML方式&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Canvas&amp;gt;
    &amp;lt;Polygon Points=&#34;10,50 180,50 180,150 10,150&#34; 
       StrokeThickness=&#34;1&#34; Stroke=&#34;Black&#34; /&amp;gt;
&amp;lt;/Canvas&amp;gt;&lt;/pre&gt;
&lt;p&gt;C#方式&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;var cnv = new Canvas(); 
var polygon = new Polygon {StrokeThickness = 1, Fill = Brushes.Black};
polygon.Points.Add(new Point(10, 50)); 
polygon.Points.Add(new Point(180, 50));
polygon.Points.Add(new Point(180, 150));
polygon.Points.Add(new Point(10, 150));
cnv.Children.Add(polygon);
this.Content = cnv;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;上面两个例子会输出下面的矩形&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28039_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/787268128d45598cff769b9209e41652a66775ae.png&#34; title=&#34;4&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用代码&lt;/strong&gt;
我写的RoundedCornersPolygon 类和普通的多边形类很相似。但是有更多的属性来控制圆角。首先。看一个例子。展示一下圆角矩形类的使用&lt;/p&gt;
&lt;p&gt;XAML方式&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Canvas&amp;gt;
    &amp;lt;CustomRoundedCornersPolygon:RoundedCornersPolygon Points=&#34;10,50 180,50 180,150 10,150&#34; 
               StrokeThickness=&#34;1&#34; Stroke=&#34;Black&#34; ArcRoundness=&#34;25&#34; 
               UseAnglePercentage=&#34;False&#34; IsClosed=&#34;True&#34;/&amp;gt;
&amp;lt;Canvas&amp;gt;&lt;/pre&gt;
&lt;p&gt;C#方式&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;var cnv = new Canvas();  
var roundedPolygon = new RoundedCornersPolygon
{
    Stroke = Brushes.Black, StrokeThickness = 1, 
    ArcRoundness = 25, UseAnglePercentage = false, IsClosed = true
};
roundedPolygon.Points.Add(new Point(10, 50));
roundedPolygon.Points.Add(new Point(180, 50));
roundedPolygon.Points.Add(new Point(180, 150));
roundedPolygon.Points.Add(new Point(10, 150));
cnv.Children.Add(roundedPolygon);
this.Content = cnv;&lt;/pre&gt;
&lt;p&gt;输出如下：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28040_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/fb11bced67d29f74ff4e539a8008871934d74c04.png&#34; title=&#34;5&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;多边形有四个主要属性
ArcRoundness 属性指定了从距离LineSegment终点多远的距离开始弯曲，通常和UseRoundnessPercentage 一起使用。UseRoundnessPercentage属性指定了ArcRoundness 值是百分比还是一个固定的值。&lt;/p&gt;
&lt;p&gt;举个例子。ArcRoundness 被设置成10，而且UseRoundnessPercentage 被设置成false，那么弯曲将会在距离线段终点10的地方开始。而如果UseRoundnessPercentage 被设置成ture。则会是从线段终点10%的地方开始弯曲。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;/// &amp;lt;summary&amp;gt; 
/// Gets or sets a value that specifies the arc roundness.
/// &amp;lt;/summary&amp;gt;
public double ArcRoundness { get; set; }

/// &amp;lt;summary&amp;gt;  
/// Gets or sets a value that specifies if the ArcRoundness property
/// value will be used as a percentage of the connecting segment or not.
/// &amp;lt;/summary&amp;gt;
public bool UseRoundnessPercentage { get; set; }&lt;/pre&gt;
&lt;p&gt;IsClosed 指定多边形的最后一个点是否和第一个点闭合。为了成为一个多边形。一般应该被设置为true&lt;/p&gt;</description>
    </item>
    <item>
      <title>自定义WPF LinkLabel 控件</title>
      <link>http://blog.leaver.me/2012/10/11/%E8%87%AA%E5%AE%9A%E4%B9%89wpf-linklabel-%E6%8E%A7%E4%BB%B6/</link>
      <pubDate>Thu, 11 Oct 2012 13:24:02 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/11/%E8%87%AA%E5%AE%9A%E4%B9%89wpf-linklabel-%E6%8E%A7%E4%BB%B6/</guid>
      <description>&lt;p&gt;WPF里是没有LinkLabel控件的。因此我自己写一个。首先。我们看一下WPF中什么类似的组件可以实现这个链接功能&lt;/p&gt;
&lt;p&gt;如果你想要模拟一个LinkLabel控件。你可以在TextBlock里使用内联的Hyperlink。像下面这样&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;TextBlock&amp;gt;
    &amp;lt;Hyperlink&amp;gt;
        &amp;lt;Run Text=&#34;Test link&#34;/&amp;gt;
    &amp;lt;/Hyperlink&amp;gt;
&amp;lt;/TextBlock&amp;gt;&lt;/pre&gt;
&lt;p&gt;你可以使用Label控件。加一个内联的HyperLink，但是我认为TextBlock更好。因为你可以在Expression Blend 中通过&lt;a href=&#34;http://msdn2.microsoft.com/en-us/library/system.windows.documents.inlinecollection.aspx&#34; title=&#34;InlineCollection&#34;&gt;InlineCollection&lt;/a&gt;  编辑所有子元素的属性&lt;/p&gt;
&lt;p&gt;图1&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27987_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2fbf37d3f59121424e1f68d6ac6e2a461f8e1ab9.png&#34; title=&#34;1&#34;&gt;&lt;/a&gt;
虽然这种方法也行，但是我还是不太喜欢。因为我觉得我还是写一个类似windows窗体程序中的LinkLabel控件。然后我就做了。首先看一下控件的样子&lt;/p&gt;
&lt;p&gt;图2&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27988_o.gif&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b4438242681c5adebadef5aff0f7f2145be09a43.gif&#34; title=&#34;2&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;第一个是默认的LinkLabel控件。第二个是LinkLabelBehavior 属性被设置为HoverUnderline ，第三个的Foreground和 HoverForeground 属性都使用了自定的颜色。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;LinkLabel控件支持的属性&lt;/p&gt;
&lt;p&gt;1.Foreground和 HoverForeground属性&lt;/p&gt;
&lt;p&gt;允许自定义这两个属性的值&lt;/p&gt;
&lt;p&gt;2.LinkLabelBehavior 属性&lt;/p&gt;
&lt;p&gt;允许设置下划线的显示与否&lt;/p&gt;
&lt;p&gt;3.自定义HyperlinkStyle 属性&lt;/p&gt;
&lt;p&gt;你可以使用这个属性给超链接设置自定义的样式。如果你已经自定了Foreground和 HoverForeground。则会被覆盖。&lt;/p&gt;
&lt;p&gt;Url 超链接的目标&lt;/p&gt;
&lt;p&gt;所有这些属性都继承自标准的System.Windows.Controls.Label 控件&lt;/p&gt;
&lt;p&gt;通过Blend/Xaml设置这些属性很简单&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;ThemedControlLibrary:LinkLabel Content=&#34;Link Label&#34; FontSize=&#34;22&#34;/&amp;gt;
&amp;lt;ThemedControlLibrary:LinkLabel Content=&#34;Link Label&#34; LinkLabelBehavour=&#34;HoverUnderline&#34; /&amp;gt;
&amp;lt;ThemedControlLibrary:LinkLabel Foreground=&#34;#FF847901&#34; HoverForeground=&#34;#FF06C8F2&#34; Content=&#34;Link Label&#34; LinkLabelBehavour=&#34;NeverUnderline&#34;/&amp;gt;&lt;/pre&gt;
&lt;p&gt;图三&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27989_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a3a5126a4aba4698c3916d5a9e92f4daa7d77b97.png&#34; title=&#34;3&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;然后是控件的使用方法。仅仅添加命名空间到xaml中。然后使用就行了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Window
    xmlns=&#34;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#34;
    xmlns:x=&#34;http://schemas.microsoft.com/winfx/2006/xaml&#34;
    x:Class=&#34;DemoApplication.Window1&#34;
    Title=&#34;DemoApplication&#34; Height=&#34;300&#34; Width=&#34;300&#34;
    xmlns:ThemedControlsLibrary=&#34;clr-namespace:ThemedControlsLibrary;assembly=ThemedControlsLibrary&#34;
    &amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;ThemedControlsLibrary:LinkLabel HorizontalAlignment=&#34;Left&#34; VerticalAlignment=&#34;Top&#34; Content=&#34;LinkLabel&#34;/&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;控件的完整代码很简单。就定义一下需要的属性，和控制这些属性应该显示在Blend中的（category）目录位置就行了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class LinkLabel : Label
{
    private const string _linkLabel = &#34;LinkLabel&#34;;

    public static readonly DependencyProperty UrlProperty = DependencyProperty.Register(&#34;Url&#34;, typeof(Uri), typeof(LinkLabel));

    [Category(&#34;Common Properties&#34;), Bindable(true)]
    public Uri Url
    {
        get { return GetValue(UrlProperty) as Uri; }
        set { SetValue(UrlProperty, value); }
    }

    public static readonly DependencyProperty HyperlinkStyleProperty = DependencyProperty.Register(&#34;HyperlinkStyle&#34;, typeof(Style),
            typeof(LinkLabel));

    public Style HyperlinkStyle
    {
        get { return GetValue(HyperlinkStyleProperty) as Style; }
        set { SetValue(HyperlinkStyleProperty, value); }
    }

    public static readonly DependencyProperty HoverForegroundProperty = DependencyProperty.Register(&#34;HoverForeground&#34;, typeof(Brush),
            typeof(LinkLabel));

    [Category(&#34;Brushes&#34;), Bindable(true)]
    public Brush HoverForeground
    {
        get { return GetValue(HoverForegroundProperty) as Brush; }
        set { SetValue(HoverForegroundProperty, value); }
    }

    public static readonly DependencyProperty LinkLabelBehavourProperty = DependencyProperty.Register(&#34;LinkLabelBehavour&#34;,            typeof(LinkLabelBehaviour),     typeof(LinkLabel));

    [Category(&#34;Common Properties&#34;), Bindable(true)]
    public LinkLabelBehaviour LinkLabelBehavour
    {
        get { return (LinkLabelBehaviour)GetValue(LinkLabelBehavourProperty); }
        set { SetValue(LinkLabelBehavourProperty, value); }
    }

    static LinkLabel()
    {
        FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(
            typeof(LinkLabel),
            new FrameworkPropertyMetadata(typeof(LinkLabel)));
    }

}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>C#制作进度窗体</title>
      <link>http://blog.leaver.me/2012/10/10/c%23%E5%88%B6%E4%BD%9C%E8%BF%9B%E5%BA%A6%E7%AA%97%E4%BD%93/</link>
      <pubDate>Wed, 10 Oct 2012 09:07:41 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/10/c%23%E5%88%B6%E4%BD%9C%E8%BF%9B%E5%BA%A6%E7%AA%97%E4%BD%93/</guid>
      <description>&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是我在CodeProject上的第一篇文章。我希望对你有用&lt;/p&gt;
&lt;p&gt;当我开发软件的时候。我通常因为一个很耗时是任务需要完成。而请求让用户等待，并且通过也允许用户取消。不论我做何种操作（比如下载文件。保存大文件等等）。我都需要做下面几件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过一个模态对话框来让用户等待操作完成&lt;/li&gt;
&lt;li&gt;能让用户看到进度。&lt;/li&gt;
&lt;li&gt;能让用户随时取消。
我搜了好久也没找到拿来就能用的窗体控件，也许是我没找到。于是我自己写。。
图1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/9f46aad8d865255936532f68d592d8ffd45b8b3d.jpg&#34; title=&#34;progress&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;BackgroundWorker 类包含了我需要完成任务的所有东西。我只需要给他提供一个对话框。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ProgressForm 包含了一个BackgroundWorker ，你要做的仅仅就是提供了一个完成工作的方法。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;ProgressForm form = new ProgressForm();
form.DoWork += new ProgressForm.DoWorkEventHandler(form_DoWork);
//如果想为后台任务提供参数的话
form.Argument = something;&lt;/pre&gt;
&lt;p&gt;为了开始BackgroundWorker，只需要调用ShowDialog 方法。返回值则取决于任务是怎么完成的。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;DialogResult result = form.ShowDialog();
if (result == DialogResult.Cancel)
{
//用户点击了取消
}
else if (result == DialogResult.Abort)
{
/未处理的异常抛出
//你可以得到异常信息
MessageBox.Show(form.Result.Error.Message);
}
else if (result == DialogResult.OK)
{
//正常完成
//结果存储在 form.Result里
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;最后。任务方法看起来是这样的。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;void form_DoWork(ProgressForm sender, DoWorkEventArgs e)
{
//得到参数
object myArgument = e.Argument;

//做一些耗时的任务...
for (int i = 0; i &amp;lt; 100; i++)
{
//通知进度
sender.SetProgress(i, &#34;Step &#34; + i.ToString() + &#34; / 100...&#34;);

//...

//检查是否点击了取消
if (sender.CancellationPending)
{
e.Cancel = true;
return;
}
}
}&lt;/pre&gt;
&lt;p&gt;如果你想要改改进度条，或者进度条显示的文本。SetProgress 有一些重载的方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public void SetProgress(string status);
public void SetProgress(int percent);
public void SetProgress(int percent, string status);&lt;/pre&gt;
&lt;p&gt;最后一个可自定义的字符串是：有两个预定义的字符串CancellingText 和DefaultStatusText. CancellingText ，这两个字符串，当用户点击取消的时候显示&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如何实现&lt;/strong&gt;
ProgressForm 紧紧嵌入了一个BackgroundWorker ，并包装进了主函数。&lt;/p&gt;
&lt;p&gt;首先。我设计了如图所示的一个窗体，然后。添加了BackgroundWorker。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public partial class ProgressForm : Form
{
public ProgressForm()
{
InitializeComponent();

worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new System.ComponentModel.DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(
worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
worker_RunWorkerCompleted);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
BackgroundWorker worker;
}&lt;/pre&gt;
&lt;p&gt;我们必须把DoWork事件暴露给用户。我添加了一个委托。这样。我可以很容易的访问窗体成员&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#编写FTP客户端软件</title>
      <link>http://blog.leaver.me/2012/10/09/c%23%E7%BC%96%E5%86%99ftp%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BD%AF%E4%BB%B6/</link>
      <pubDate>Tue, 09 Oct 2012 09:06:16 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/09/c%23%E7%BC%96%E5%86%99ftp%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BD%AF%E4%BB%B6/</guid>
      <description>&lt;h1&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27933_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/df5f8fbfeaeabe639c893a078ddeda6cac4361db.png&#34; title=&#34;1&#34;&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h1 id=&#34;1-介绍&#34;&gt;1 介绍&lt;/h1&gt;
&lt;p&gt;我知道。网上有很多现成的FTP软件。但是。我们也想要了解FTP的一些底层机构，因此。 这个开源的项目在你学习FTP知识的时候也许对你有些帮组。程序的界面看起来像FileZilla，FileZilla虽然流行但是有些bug，当我打开我博客的时候总是有问题。我需要通过FTP连接我的服务器。发送文件，下载文件等等。因为。我决定写我自己的软件来处理所有的情况。FileZilla足够好。但它不是我的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1 id=&#34;2-背景&#34;&gt;2 背景&lt;/h1&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;看看我们已经知道的。我们知道FTP是一个标准的基于TCP网络协议。用于从一个主机向另一个主机传输文件。它是一个C/S架构。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;图2&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27934_o.gif&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ceb7abd419bd3e983fa8f9cbf1962546cc0880a4.gif&#34; title=&#34;2&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;FTP程序曾经是基于命令行的。我们仍沿可以通过cmd.exe连接FTP服务器。因为FTP的确可以通过命令来操作。举个例子。我们可以在命令行使用“stor”命令来发送文件。为了完成这些请求。FTP服务器需要一直运行等待即将到来的客户端请求。我们可以从来自维基百科的解释更好的理解FTP：&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;客户端计算机可以通过服务器的21端口和服务器通信。叫做控制连接。它在一次会话期间保持开放。第一次连接的时候。叫做数据连接,服务器可以对客户端打开20端口（主动模式），建立一条数据通路，连接上客户端传输数据。或者客户端打开一个随机的端口（被动模式），去连接服务器，来传输数据。控制连接使用一个类似Telnet的协议，被用作客户端和服务器会话管理（命令，标识，密码）。。比如。&amp;ldquo;RETR &lt;em&gt;filename&lt;/em&gt;&amp;rdquo;  会从服务器端下载文件。&lt;/p&gt;
&lt;p&gt;图三&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/9c06cc0d8d904390202ef269a18467324df590c9.gif&#34; title=&#34;3&#34;&gt;&lt;/p&gt;
&lt;p&gt;一个完整的FTP文件传输需要建立两种类型的连接，一种为文件传输下命令，称为控制连接，另一种实现真正的文件传输，称为数据连接。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;服务器 通过三位ASCII的数字状态码，可能包含可选的描述信息，在控制连接上做出回应。比如。“200”或者是“200 OK”,表示上一条命令成功了。数字代表编号，描述信息给出了一些说明（比如“OK”）,或者可能是一些需要的参数(比如需要帐号来存储文件)，那么我们需要怎么做呢。很明显。发送命令，接收“OK”回应，发送数据。接收数据。完了。但是首先需要服务器已经准备好了。FTP服务器可以在主动和被动两种模式下运行。主动模式是基于服务器的连接而被动模式是基友客户端的连接。继续看。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;在主动连接中，客户端把自己的ip和端口发送给服务器。然后服务器尝试连接到客户端，但是可能会因为防火墙的原因而被拒绝。我们在windows上都会使用反病毒/自带防火墙。是吧。那么我们来看看被动模式&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;在被动连接中。服务器通过一个“PASV”命令把自己的ip和端口发送给客户端。然后客户端通过该IP尝试连接服务器。对于发送文件非常有用。当我们发送文件的时候。优先使用“PASV”模式，如你们所说。大多数协议。像FTP/HTTP 使用ASCII编码，因为全球可用。因此我们会使用这种编码。你可以从下面得到FTP的命令列表&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;主动和被动都是对于服务器端来说的&lt;/p&gt;
&lt;h1 id=&#34;3-使用代码&#34;&gt;3 使用代码&lt;/h1&gt;
&lt;p&gt;现在我们已经为编写软件做好准备了。我们写些有用的代码吧。：）首先。我们“打开文件对话框”，集成到我们的窗体里。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;31-资源管理器组件&#34;&gt;3.1 资源管理器组件&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;我们需要一个资源管理器组件在软件界面可以看到我们所有的文件。这样我们才可以选择哪些文件来发送到FTP服务器，新建一个Windows窗体控件库（下载包中提供了）&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;图四&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27937_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b2ae5f59d51b1a183a0ceea50a2c9497971422e7.png&#34; title=&#34;4&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;最后看起来样子是上面这样。先添加一个TreeView，一些按钮，和一个搜索功能&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;TreeView.Nodes.Clear();
&lt;p&gt;TreeNode nodeD = new TreeNode();&lt;/p&gt;
&lt;p&gt;nodeD.Tag = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);&lt;/p&gt;
&lt;p&gt;nodeD.Text = &amp;ldquo;Desktop&amp;rdquo;;&lt;/p&gt;
&lt;p&gt;nodeD.ImageIndex = 10;&lt;/p&gt;
&lt;p&gt;nodeD.SelectedImageIndex = 10;&lt;/p&gt;
&lt;p&gt;TreeView.Nodes.Add(nodeD);&lt;/pre&gt;
 &lt;/p&gt;
&lt;/div&gt;
就像上面代码展示的那样。我们需要添加地一个主节点。我的文档。我的电脑等等。然后获得子目录。
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;string[] dirList;
dirList = Directory.GetDirectories(parentNode.Tag.ToString());
Array.Sort(dirList);
if (dirList.Length == parentNode.Nodes.Count)
    return;
for (int i = 0; i &amp;lt; dirList.Length; i++)
{
    node = new TreeNode();
    node.Tag = dirList[i]; 
    node.Text = dirList[i].Substring(dirList[i].LastIndexOf(@&#34;\&#34;) + 1);
    node.ImageIndex = 1;
    parentNode.Nodes.Add(node);
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;可以从下载包里看到完整的代码。我们还应该处理鼠标单击事件。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;现在我们有了一个资源管理器。还有FTP和VS所需要的所有信息。&lt;/p&gt;
&lt;p&gt;首先，我们连接服务器。我们应该怎么做呢？&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;FTPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
AppendText(rchLog,&#34;Status : Resolving IP Address\n&#34;,Color.Red);
remoteAddress = Dns.GetHostEntry(Server).AddressList[0];
AppendText(rchLog, &#34;Status : IP Address Found -&amp;gt;&#34; + remoteAddress.ToString() + &#34;\n&#34;, Color.Red);
addrEndPoint = new IPEndPoint(remoteAddress, Port);
AppendText(rchLog,&#34;Status : EndPoint Found -&amp;gt;&#34; + addrEndPoint.ToString() + &#34;\n&#34;, Color.Red);
FTPSocket.Connect(addrEndPoint);
是的。我们需要一个socket连接到服务器 ，然后发送命令

AppendText(rchLog, &#34;Command : &#34; + msg + &#34;\n&#34;, Color.Blue);
Byte[] CommandBytes = Encoding.ASCII.GetBytes((msg + &#34;\r\n&#34;).ToCharArray());
FTPSocket.Send(CommandBytes, CommandBytes.Length, 0);
//read Response
ReadResponse();&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>理解并实现生成器模式</title>
      <link>http://blog.leaver.me/2012/10/08/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E7%94%9F%E6%88%90%E5%99%A8%E6%A8%A1%E5%BC%8F/</link>
      <pubDate>Mon, 08 Oct 2012 13:11:16 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/08/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E7%94%9F%E6%88%90%E5%99%A8%E6%A8%A1%E5%BC%8F/</guid>
      <description>&lt;h1 id=&#34;介绍&#34;&gt;介绍&lt;/h1&gt;
&lt;p&gt;本文讨论生成器设计模式，讨论该模式什么情况下使用，怎么实现。并且。最后会有一个简单的生成器模式的实现。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1 id=&#34;背景&#34;&gt;背景&lt;/h1&gt;
&lt;p&gt;当我们的程序需要创建一个对象。而这个对象必须由很多不同的对象来构造的时候。为了构造最后的对象。我们不得不组合那些部分对象。最后我们会发现我们的代码被各种各样的部分对象的细节所弄的难以理解&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;为了说明上面的情况。我们做一个手机生产制造系统的例子。假定我们我们有一个已经安装在手机供应商那块的一个系统。现在供应商系那个要根据一些参数来创造一个新手机。比如触屏，操作系统，电池等。如果我们已经有了这些部分的对象，那么上述部分的任意组合将会导致客户端代码复杂难以管理。比如决定生产哪种手机的模块。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;生成器模式目的就是解决上述问题的。GoF定义生成器模式如下：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Separate the construction of a complex object from its representation so that the same construction process can create different representations&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;这个定义意味着我们不得不设计这个系统。通过一种客户端仅仅定义参数，而生成器则接管创建复杂对象 的方式。我们看一下生成器模式的类图。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27924_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/489ad862ea61f21ae79e749c31fb0aef3c0eea45.jpg&#34; title=&#34;gof&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;然后看看上图中的每一个类都表示什么&lt;/p&gt;
&lt;p&gt;ConcreteBuilder: 创建复杂产品的具体类.将会知道他已经创建的Product（产品），也就是他已经装配了的Product， 客户端通过该类得到Product对象.&lt;/p&gt;
&lt;p&gt;Builder: 创建Product的接口&lt;/p&gt;
&lt;p&gt;Director: 客户端代码，定义了哪些部分应该被组合在一起来创建具体的Product&lt;/p&gt;
&lt;p&gt;Product: 这是通过组合很多部分创建的对象&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1 id=&#34;使用代码&#34;&gt;使用代码&lt;/h1&gt;
&lt;p&gt;我们现在跟随上述的定义，然后试着去实现一个基本的生成器模式&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;我们先在合适的地方定义Product的不同部分，我们简单的定义一些枚举类型，那么我们就可以通过组合不同的部分创建Product了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;// 一些helper枚举定义各种零件

public enum ScreenType

{

    ScreenType_TOUCH_CAPACITIVE,

    ScreenType_TOUCH_RESISTIVE,

    ScreenType_NON_TOUCH

};

public enum Battery

{

    MAH_1000,

    MAH_1500,

    MAH_2000

};

public enum OperatingSystem

{

    ANDROID,

    WINDOWS_MOBILE,

    WINDOWS_PHONE,

    SYMBIAN

};

public enum Stylus

{

    YES,

    NO

};&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;然后，我们看一下Product类，我们需要有一个可以通过装配创建的Product类，这里我们定义一个MobilePhone类，也就是概念里的Product类了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;// 这是 &#34;Product&#34; 类

class MobilePhone

{

    // 不同部分的字段

    string phoneName;      

    ScreenType phoneScreen;

    Battery phoneBattery;

    OperatingSystem phoneOS;

    Stylus phoneStylus;

    public MobilePhone(string name)

    {

        phoneName = name;

    }

    //公有属性访问这些部分

    public string PhoneName

    {

        get { return phoneName; }           

    }

    public ScreenType PhoneScreen

    {

        get { return phoneScreen; }

        set { phoneScreen = value; }

    }       

    public Battery PhoneBattery

    {

        get { return phoneBattery; }

        set { phoneBattery = value; }

    }       

    public OperatingSystem PhoneOS

    {

        get { return phoneOS; }

        set { phoneOS = value; }

    }      

    public Stylus PhoneStylus

    {

        get { return phoneStylus; }

        set { phoneStylus = value; }

    }

    // 显示手机相关信息的方法

    public override string ToString()

    {

        return string.Format(&#34;Name: {0}\nScreen: {1}\nBattery {2}\nOS: {3}\nStylus: {4}&#34;,

            PhoneName, PhoneScreen, PhoneBattery, PhoneOS, PhoneStylus);

    }

}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>YAXLib---- XML序列化神器</title>
      <link>http://blog.leaver.me/2012/10/05/yaxlib----xml%E5%BA%8F%E5%88%97%E5%8C%96%E7%A5%9E%E5%99%A8/</link>
      <pubDate>Fri, 05 Oct 2012 16:24:31 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/05/yaxlib----xml%E5%BA%8F%E5%88%97%E5%8C%96%E7%A5%9E%E5%99%A8/</guid>
      <description>&lt;p&gt;今天早上翻译了&lt;a href=&#34;http://www.codeproject.com/Articles/34045/Yet-Another-XML-Serialization-Library-for-the-NET&#34;&gt;Yet-Another-XML-Serialization-Library-for-the-NET&lt;/a&gt;，刚开始以为很短。翻译着发现不对。。然后你不逼你自己。怎么知道自己做不到。于是。将近4个小时把30页的文档翻译完了。因为文章很长。所以本文只列出前两部分。我把翻译好的做成了pdf，&lt;/p&gt;
&lt;p&gt;文档下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=74284&amp;amp;uk=1493685990&#34;&gt;XML序列化神器&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;1-介绍&#34;&gt;1 介绍&lt;/h2&gt;
&lt;p&gt;在本文中，会把要提到的XML序列化库叫做YAXLib，我们知道。.Net 还是提供了一些序列化功能的，尤其是XmlSerializer，该类被程序员广泛使用用来序列化对象成XML，当然，反序列化也是可以的。我认为XmlSerializer类的问题有几下几点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;程序员不能自由的选择生成的xml的结构&lt;/li&gt;
&lt;li&gt;不支持序列化一些集合类，比如Dictionary&amp;lt;,&amp;gt; 或者IEnumerable&amp;lt;&amp;gt;的属性&lt;/li&gt;
&lt;li&gt;当反序列化的时候，如果缺失了一些域，则反序列化失败，这就使得用来存储一ixekeyi被用户编辑的配置文件变得不合适了。
 &lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;2-为什么使用yaxlib&#34;&gt;2 为什么使用YAXLib&lt;/h2&gt;
&lt;p&gt;YAXLib解决上述问题的特点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;程序员可以决定xml文件的结构，一个属性可以是一个子元素，或者是其他属性的属性，或者是一个在类中没有对应属性的元素。&lt;/li&gt;
&lt;li&gt;集合类也可以被序列化成一个逗号分隔（也可以是其他任何分隔符）的数据项列表，而且。为Dictionary&amp;lt;,&amp;gt;对象实现了一些特殊的格式化功能，这样，使得程序员可以完全控制生成的xml文件的结构&lt;/li&gt;
&lt;li&gt;他支持System.Collections.Generic 命名空间中的所有泛型集合类（像&lt;code&gt;Dictionary&lt;/code&gt;, &lt;code&gt;HashSet&lt;/code&gt;, &lt;code&gt;LinkedList&lt;/code&gt;, &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Queue&lt;/code&gt;,&lt;code&gt;SortedDictionary&lt;/code&gt;, &lt;code&gt;SortedList&lt;/code&gt;, 和 &lt;code&gt;Stack&lt;/code&gt;） 和在&lt;code&gt;System.Collections&lt;/code&gt;  命名空间中的非泛型集合类（ &lt;code&gt;ArrayList&lt;/code&gt;, &lt;code&gt;BitArray&lt;/code&gt;, &lt;code&gt;Hashtable&lt;/code&gt;, &lt;code&gt;Queue&lt;/code&gt;, &lt;code&gt;SortedList&lt;/code&gt;, 和 &lt;code&gt;Stack&lt;/code&gt;）非泛型集合类可以包含多种不同的对象，而且，库还支持序列化和反序列化一维，多维，不规则的数组。&lt;/li&gt;
&lt;li&gt;支持通过对基类/接口的引用，实现对一些对象集合的序列化和反序列化。&lt;/li&gt;
&lt;li&gt;支持多级反序列化&lt;/li&gt;
&lt;li&gt;程序员可以为生成的xml提供注释&lt;/li&gt;
&lt;li&gt;当进行反序列化的时候，程序员可以选择性对于那些与类的属性相关，但没有出现在xml文件中的数据应该如何处理。这种情况下可以看错是一个错误，然后类库抛出一些异常，或者记录错误，或者可以被看成一个警告，然后用程序员预定义的值赋给对应的属性，而且，程序可以可以选择忽略这个问题，相关的异常将既不抛出也不作任何记录。请查看保留空引用标识那一节 看看什么时候可以忽略孤立的数据也许对你有帮助&lt;/li&gt;
&lt;li&gt;程序员可以自己选择错误处理规则，对于数据敏感的应用程序，程序员可以选择在任何异常的情况下，库都应该抛出并且记录异常，对于其他的一些情况（比如要求不那么高的配置文件的存储），程序员可以选择把异常仅仅看成一个警告，仅仅记录一下，让程序的其他部分继续运行。
文档下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=74284&amp;amp;uk=1493685990&#34;&gt;XML序列化神器&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;著作权声明：本文由&lt;a href=&#34;http://leaver.me/&#34;&gt;http://leaver.me&lt;/a&gt; 翻译，欢迎转载分享。请尊重作者劳动，转载时保留该声明和作者博客链接，谢谢！&lt;/p&gt;</description>
    </item>
    <item>
      <title>简单扩展方法增强代码可读性</title>
      <link>http://blog.leaver.me/2012/10/04/%E7%AE%80%E5%8D%95%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E5%A2%9E%E5%BC%BA%E4%BB%A3%E7%A0%81%E5%8F%AF%E8%AF%BB%E6%80%A7/</link>
      <pubDate>Thu, 04 Oct 2012 09:03:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/04/%E7%AE%80%E5%8D%95%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E5%A2%9E%E5%BC%BA%E4%BB%A3%E7%A0%81%E5%8F%AF%E8%AF%BB%E6%80%A7/</guid>
      <description>&lt;p&gt;本文技术含量不高，但是思路可以借鉴。。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当你处理计时器，时间间隔，或是其他关于日期的计算的时候。你必然会使用TimeSpan类。&lt;/p&gt;
&lt;p&gt;我觉得写出下面的代码可读性并不好。。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;// 1个表示5小时的时间间隔
var theTimespan = new TimeSpan(0, 5, 0, 0, 0);&lt;/pre&gt;
&lt;p&gt;而下面的代码就要好一些&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;//一个表示5小时的时间间隔
var theTimespan = 5.Hours();&lt;/pre&gt;
&lt;p&gt;** 扩展方法**&lt;/p&gt;
&lt;p&gt;使用这些扩展了int类的方法。可以使得创建TimeSpan可读性更好&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public static TimeSpan Days(this int value)
{
    return new TimeSpan(value, 0, 0, 0, 0);
}

public static TimeSpan Years(this int value)
{
    var dt = DateTime.Now.AddYears(value);
    return (dt - DateTime.Now).Duration();
}

public static TimeSpan Hours(this int value)
{
    return new TimeSpan(0, value, 0, 0, 0);
}

public static TimeSpan Minutes(this int value)
{
    return new TimeSpan(0, 0, value, 0, 0);
}

public static TimeSpan Seconds(this int value)
{
    return new TimeSpan(0, 0, 0, value, 0);
}

public static TimeSpan Milliseconds(this int value)
{
    return new TimeSpan(0, 0, 0, 0, value);
}&lt;/pre&gt;
&lt;p&gt;许可&lt;/p&gt;
&lt;p&gt;本文所有源代码包括文件在CPOL下授权。。&lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href=&#34;http://www.codeproject.com/Tips/469097/Simple-extension-methods-for-code-readability&#34;&gt;Simple-extension-methods-for-code-readability&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;著作权声明：本文由&lt;a href=&#34;http://leaver.me/&#34;&gt;http://leaver.me&lt;/a&gt; 翻译，欢迎转载分享。请尊重作者劳动，转载时保留该声明和作者博客链接，谢谢！&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>11个高效的VS调试技巧</title>
      <link>http://blog.leaver.me/2012/10/03/11%E4%B8%AA%E9%AB%98%E6%95%88%E7%9A%84vs%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7/</link>
      <pubDate>Wed, 03 Oct 2012 10:45:15 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/03/11%E4%B8%AA%E9%AB%98%E6%95%88%E7%9A%84vs%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7/</guid>
      <description>&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;调试是软件开发周期中的一个很重要的部分，有时很有挑战性，有时候则让程序员迷惑，有时候让程序员发疯，但是。可以肯定的是，对于任何不是太那个微不足道的程序来说，调试是不可避免的。近年来，调试工具的发展已经使得很多调试任务简单省时了。&lt;/p&gt;
&lt;p&gt;本文总结了十个调试技巧，当你使用VS的时候可以节省你很多时间。&lt;/p&gt;
&lt;p&gt;1. 悬停鼠标查看表达式&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27679_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5b9e01a5158e02f8079c7dc331f56110f3e0b82d.png&#34; title=&#34;1&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;调试有时候很有挑战性，当你步入一个函数想看看哪块出错的时候，查看调用栈来想想值是从哪来的。另一些情况下，则需要添加一些监视表达式，或者查看局部变量列表，这通常还是花费一些时间的，但是。如果你把你鼠标指向你感兴趣的一个变量。你会发现事情简单多了。而且，类和结构体可以通过单击展开。这样。你就可以方便快捷的找到你想查看的变量了。&lt;/p&gt;
&lt;p&gt;2. 实时改变值
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27680_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/eade577f5ea39d3b970613ac3123610b67e427cb.png&#34; title=&#34;2&#34;&gt;&lt;/a&gt;
调试器不仅仅是一个分析程序崩溃或是异常结果的工具了，许多bug都可以通过步入新写的函数，检查函数是否如期望的那样运行来预防。有时候你可能会好奇“如果条件为真函数会正确运行吗”大多数情况下，根本不需要改变代码重启挑起，仅仅把鼠标悬停到一个变量上，双击值然后输入一个新值就可以了。。&lt;/p&gt;
&lt;p&gt;3．设置下一条语句
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27690_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1c86cc15b16c98adc1563eb1660481fa249beaf0.png&#34; title=&#34;3&#34;&gt;&lt;/a&gt;
一个典型的调试情况就是通过单步跟踪分析为什么一个函数调用失败了。当你发现一个函数调用的另一个函数返回错误的时候你会怎么做？重启调试？有更好的方法。拖动这个黄色的语句标识到你想下一步执行的语句前就可以了。比如你刚才失败的那块，然后步入。简单，不是吗？&lt;/p&gt;
&lt;p&gt;4.编辑然后继续
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27682_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8117d2025d49155485268fc1b56041e96cefaeac.png&#34; title=&#34;4&#34;&gt;&lt;/a&gt;
调试一个复杂的程序，或是一个插件的时候，在一个被调用很多次的函数处发现一个错误。但是不想浪费时间停下来，重新编译然后重新调试。没问题，仅仅在该处改正代码然后继续单步就可以。VS会修正程序然后继续调试不需要重启&lt;/p&gt;
&lt;p&gt;注意，编辑然后继续有大量的已知限制，首先，64位代码是不行的。如果他如果为你的C#程序工作。就去工程设置的生成选项，然后目标平台为x86.不要担心。发布版的目标平台和调试的时候是分开的。可以被设置为任何平台。。&lt;/p&gt;
&lt;p&gt;第二．编辑然后继续改变在一个方法里应该是局部的。。如果你改变了方法签名，添加一些新方法或是类。你就不得不重启程序了。或者撤销改变来继续。改变方法也包含lambda表达式隐式修改的自动生成的代理类，因此也不能继续。&lt;/p&gt;
&lt;p&gt;5.方便的监视窗口
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27683_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a204da1e7bb82719b4a965da45d1cfcc51a90cd3.png&#34; title=&#34;5&#34;&gt;&lt;/a&gt;
大概现代的调试器都有一个监视窗口，无论如何。VS允许你简单的添加或移除变量。单击空行，输入你的表达式按下回车，或者是在不需要的表达式上按下Delete键就可以删除了。
而且。从监视窗口你不仅仅可以看到“正常”的变量。你可以输入$handles 来追踪你的程序打开了多少句柄（可以方便的修复内存泄漏） ，输入$err 可以看到上一个函数的错误码，然后使用工具-错误信息可以看到更详细的描述，或者输入@eax（64位是@rax）来查看包含函数返回值的寄存器。&lt;/p&gt;
&lt;p&gt;6.带注释的反汇编
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27684_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d61b64ed0a189bec2f34f2faaf059916cce8e525.png&#34; title=&#34;6&#34;&gt;&lt;/a&gt;
使用交互式的反汇编模式可以使得优化程序的关键部分变得很容易，VS给出对应你代码每一行的汇编指令，并且运行单步运行。同时，可以在任何位置设置断点。而且，表达式的查看和修改也像在C++代码里一样&lt;/p&gt;
&lt;p&gt;7.带有栈的线程窗口
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27691_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5b212033679007829bb5c0684d62ab8f27a0514b.png&#34; title=&#34;7&#34;&gt;&lt;/a&gt;
调试多线程的程序是痛苦的。。或者也可以是很有趣的。取决于你的调试器。VS2010真正优美的特性是线程窗口的栈视图，通过窗口的调用栈你可以方便的总览线程。&lt;/p&gt;
&lt;p&gt;8.条件断点
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27686_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/e93436bf72af22e533fe859971913a3d3c555789.png&#34; title=&#34;8&#34;&gt;&lt;/a&gt;
如果你尝试通过断点再现一个罕见的事件，该情况引发了一些严重的错误。你可以添加条件断点。定义一个断点的条件，然后如果条件不成立，VS会忽略该断点&lt;/p&gt;
&lt;p&gt;9.内存窗口
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27687_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/0cfda80c7dbe3d0c50bb5646155914b5e3f07f4f.png&#34; title=&#34;9&#34;&gt;&lt;/a&gt;
有些bug由不正确的结构体定义引起，忽略的对齐属性等等。查看内存中的内容可以定位然后修复bug。VS提供了一个放百年的内存窗口，可以把值以8/16/32/64位的形式展示。还有浮点值。也允许实时改变他们。就像在文本编辑器里一样。&lt;/p&gt;
&lt;p&gt;10.转到定义
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27688_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3593aad0199fbed2f8faaef908e151a068e14d09.png&#34; title=&#34;10&#34;&gt;&lt;/a&gt;
这个特性不是直接关于调试的，而是关于浏览大项目的。如果你尝试找到一些不是你自己写的代码中的错误，快速知道“这个类型是什么”或者“这个函数是干嘛的”，可以节省很多时间，VS通过一个转到定义命令方便了你。&lt;/p&gt;
&lt;p&gt;11.命令窗口
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27689_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2af5b37764b18abe3ae34c1a67e4398721fbd04b.png&#34; title=&#34;11&#34;&gt;&lt;/a&gt;
第十一的技巧&lt;a href=&#34;http://www.codeproject.com/script/Membership/View.aspx?mid=4917930&#34;&gt;chaau&lt;/a&gt;已经建议过了。确实可以节省很多时间，VS支持命令窗口，可以通过，视图-其他窗口-命令窗口来启动。一旦激活，你可以输入不同的命令来自动化调试。举个例子。你可以通过如下命令 简单的模拟MFC COleDateTime 变量。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;? dt.Format(&#34;%Y-%m-%d %H:%M:%S&#34;)&lt;/pre&gt;
&lt;p&gt;许可
本文包括源代码和文件在CPOL下授权。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href=&#34;http://www.codeproject.com/Articles/359801/10plus-powerful-debugging-tricks-with-Visual-Studi&#34;&gt;10plus-powerful-debugging-tricks-with-Visual-Studi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;著作权声明：本文由&lt;a href=&#34;http://leaver.me/&#34;&gt;http://leaver.me&lt;/a&gt; 翻译，欢迎转载分享。请尊重作者劳动，转载时保留该声明和作者博客链接，谢谢！&lt;/p&gt;</description>
    </item>
    <item>
      <title>CSV导入导出工具</title>
      <link>http://blog.leaver.me/2012/09/30/csv%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E5%B7%A5%E5%85%B7/</link>
      <pubDate>Sun, 30 Sep 2012 22:33:19 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/30/csv%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E5%B7%A5%E5%85%B7/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27639_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/650890bebf13c4d041d3113af4b40fb93a2cc0c5.png&#34; title=&#34;form1&#34;&gt;&lt;/a&gt;
&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本文介绍并且实现了在平面文件CSV和SQL server之间的导入导出功能。使用VS2005写的。使用了.net 2.0&lt;/p&gt;
&lt;p&gt;本文基于前一篇文章：&lt;a href=&#34;http://www.codeproject.com/KB/database/FinalCSVReader.aspx&#34;&gt;从CSV导入数据并存储到数据库&lt;/a&gt;，本文包含了新功能，比如，导出功能，在数据库创建表，批量拷贝。接下来的例子中有很多注释。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;导入&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过ODBC驱动连接到一个CSV文件，然后把文件读到一张表了（基于前面提到的那篇文章）
使用不同的编码和不同的行分隔符（基于前文）
加载CSV文件到DataSet（基于前文）
如何显示对CSV文件的预览（基于前文）
通过SqlBulkCopy的对象向SQL server转移数据，原始数据是DataSet实例&lt;/p&gt;
&lt;p&gt;使用结构表，基于CSV文件，创建一个新表
使用事件来处理批量拷贝的进程
&lt;strong&gt;导出&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;浏览SQL 数据库中的用户表
使用不同的编码和分隔符
使用SqlDataReader读取数据，使用StreamWriter转移数据到平面文件&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27640_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b131fd0af27287ab9270df33d1a313ab957dfb12.png&#34; title=&#34;form2&#34;&gt;&lt;/a&gt;
使用&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;下载工程&lt;/li&gt;
&lt;li&gt;新建一个数据库，或者使用一个存在的数据库&lt;/li&gt;
&lt;li&gt;修改软件中的数据库连接字符串，在prop.cs文件中&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;public static string sqlConnString = &#34;server=(local);
	database=Test_CSV_impex;Trusted_Connection=True&#34;;&lt;/pre&gt; 
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;运行工程&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;一些代码段&lt;/strong&gt;
加载CSV到DataSet中&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
/*
 *加载CSV到DataSet.
 * 
 * 如果numberOfRows parameter 是 -1, 就加载所有行, 否则就加载指定数目的行
 */

public DataSet LoadCSV(int numberOfRows)
{
	DataSet ds = new DataSet();
	try
	{
		// 创建并打开ODBC连接
		string strConnString = &#34;Driver={Microsoft Text Driver (*.txt; *.csv)};
			Dbq=&#34; + this.dirCSV.Trim() + &#34;;
			Extensions=asc,csv,tab,txt;Persist Security Info=False&#34;;
		string sql_select;
		OdbcConnection conn;
		conn = new OdbcConnection(strConnString.Trim());
		conn.Open();

		//创建SQL语句
		if (numberOfRows == -1)
		{
			sql_select = &#34;select * from [&#34; + 
					this.FileNevCSV.Trim() + &#34;]&#34;;
		}
		else
		{
			sql_select = &#34;select top &#34; + numberOfRows + 
				&#34; * from [&#34; + this.FileNevCSV.Trim() + &#34;]&#34;;
		}

		//创建数据适配器 
		OdbcDataAdapter obj_oledb_da = new OdbcDataAdapter(sql_select, conn);

		//用CSV的数据填充DataSet
		obj_oledb_da.Fill(ds, &#34;csv&#34;);

		//关闭连接
		conn.Close();
	}
	catch (Exception e) //异常处理
	{
		MessageBox.Show(e.Message, &#34;Error - LoadCSV&#34;,
				MessageBoxButtons.OK,MessageBoxIcon.Error);
	}
	return ds;
}&lt;/pre&gt;
&lt;p&gt;通过SqlBulkCopy从ODBC连接中转移数据到数据库&lt;/p&gt;</description>
    </item>
    <item>
      <title>ListView布局管理器</title>
      <link>http://blog.leaver.me/2012/09/29/listview%E5%B8%83%E5%B1%80%E7%AE%A1%E7%90%86%E5%99%A8/</link>
      <pubDate>Sat, 29 Sep 2012 10:14:54 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/29/listview%E5%B8%83%E5%B1%80%E7%AE%A1%E7%90%86%E5%99%A8/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27575_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3908a54221845d3b8f0b2ad7c3c0b559dae7a979.jpg&#34; title=&#34;listview&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;介绍&#34;&gt;介绍&lt;/h3&gt;
&lt;p&gt;使用ListViewLayoutManager  可以控制ListView/GridView列的布局&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;固定列宽：有着固定列宽的列&lt;/li&gt;
&lt;li&gt;范围列宽：有着最小最大宽度的列&lt;/li&gt;
&lt;li&gt;比例列宽：成比例的列宽&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;范围列宽可以限制列的宽度，也包括填充列的剩余可视区域。&lt;/p&gt;
&lt;p&gt;据我们了解的Html中的表格和Grid空间。比例列以一个百分比来定义列宽，以下几个因素共同确定了比例列的宽度。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;垂直ListView滚动条的可视与否&lt;/li&gt;
&lt;li&gt;ListView控件宽度的改变&lt;/li&gt;
&lt;li&gt;非比例列宽度的改变&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;本程序支持通过XAML或是后台代码来控制ListView。如果通过XAML来控制。则允许ListViewLayoutManager 被附加到一个存在的ListView控件上。&lt;/p&gt;
&lt;p&gt;ConverterGridColumn 类通过接口IValueConverter 提供了对象绑定。使用ImageGridViewColumn 类则允许通过DataTemplate（数据模板）将列显示成图片等。&lt;/p&gt;
&lt;p&gt;在 &lt;a href=&#34;http://www.codeproject.com/Articles/25829/User-Settings-Applied&#34;&gt;User Setting Applied&lt;/a&gt;中，我展示了如何固定ListViewlieder顺序和大小&lt;/p&gt;
&lt;h3 id=&#34;xaml中listviewgridview布局&#34;&gt;XAML中ListView/GridView布局&lt;/h3&gt;
&lt;p&gt;固定列
下面的例子展示了通过XAML使用固定列宽控制列&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;&amp;lt;ListView
    Name=&#34;MyListView&#34;
    ctrl:ListViewLayoutManager.Enabled=&#34;true&#34;&amp;gt;

    &amp;lt;ListView.View&amp;gt;
      &amp;lt;GridView&amp;gt;
        &amp;lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=Name}&#34;

          ctrl:FixedColumn.Width=&#34;100&#34;
          Header=&#34;Name&#34; /&amp;gt;

        &amp;lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=City}&#34;
          ctrl:FixedColumn.Width=&#34;300&#34;

          Header=&#34;City&#34; /&amp;gt;
      &amp;lt;/GridView&amp;gt;

    &amp;lt;/ListView.View&amp;gt;
  &amp;lt;/ListView&amp;gt;
&lt;/pre&gt; 
&lt;p&gt;设置附加到ListView控件上的ListViewLayoutManager 的Enabled属性为True。然后FixedColumn.Width 就会阻止鼠标拖动改变列的宽度。&lt;/p&gt;
&lt;p&gt;比例列&lt;/p&gt;
&lt;p&gt;下面的例子展示了使用XAML通过比例来控制列&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;&lt;ListView
    Name=&#34;MyListView&#34;
    ctrl:ListViewLayoutManager.Enabled=&#34;true&#34;&gt;
    &lt;ListView.View&gt;

      &lt;GridView&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=Name}&#34;
          ctrl:ProportionalColumn.Width=&#34;1&#34;

          Header=&#34;Name&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=City}&#34;

          ctrl:ProportionalColumn.Width=&#34;3&#34;
          Header=&#34;City&#34; /&gt;
      &lt;/GridView&gt;

    &lt;/ListView.View&gt;

  &lt;/ListView&gt;&lt;/pre&gt;
&lt;p&gt;对比Grid控件的RowDefinition.Width 属性，ProportionalColumn.Width会计算百分比。简单来说，就是上面的例子中Name列会占到总宽度的25%，而City列占到75%。
与固定列相似。鼠标将不能改变列的宽度。&lt;/p&gt;
&lt;p&gt;范围列&lt;/p&gt;
&lt;p&gt;下面的例子展示了使用XAML通过最小/最小宽度来控制列&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
&lt;ListView
    Name=&#34;MyListView&#34;
    ctrl:ListViewLayoutManager.Enabled=&#34;true&#34;&gt;
    &lt;ListView.View&gt;

      &lt;GridView&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=Name}&#34;
          ctrl:RangeColumn.MinWidth=&#34;100&#34;
          Width=&#34;150&#34;

          Header=&#34;Name&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=City}&#34;
          ctrl:RangeColumn.MaxWidth=&#34;200&#34;
          Width=&#34;150&#34;

          Header=&#34;City&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=Country}&#34;
          Width=&#34;100&#34;
          ctrl:RangeColumn.MinWidth=&#34;50&#34;

          ctrl:RangeColumn.MaxWidth=&#34;150&#34;
          Header=&#34;Country&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=State}&#34;
          Width=&#34;100&#34;

          ctrl:RangeColumn.MinWidth=&#34;100&#34;
          ctrl:RangeColumn.IsFillColumn=&#34;true&#34;
          Header=&#34;Country&#34; /&gt;

      &lt;/GridView&gt;

    &lt;/ListView.View&gt;
  &lt;/ListView&gt;&lt;/pre&gt;
&lt;p&gt;第一个范围列的IsFillColumn 属性被设置为True，因此将会自动改变大小来填满剩余的空间，而如果ListView包含一个比例列的话，范围列将不会填充&lt;/p&gt;
&lt;p&gt;通过鼠标可以拖动范围列的宽度。鼠标指针会有一些提示。。&lt;/p&gt;
&lt;p&gt;组合使用&lt;/p&gt;
&lt;p&gt;在真实的世界里。组合使用很普遍。他们的顺序可以多种多样。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
&lt;ListView
    Name=&#34;MyListView&#34;
    ctrl:ListViewLayoutManager.Enabled=&#34;true&#34;&gt;

    &lt;ListView.View&gt;
      &lt;GridView&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=State}&#34;
          ctrl:FixedColumn.Width=&#34;25&#34;
          Header=&#34;Name&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=Name}&#34;

          Width=&#34;150&#34;
          ctrl:RangeColumn.MinWidth=&#34;100&#34;
          ctrl:RangeColumn.MaxWidth=&#34;200&#34;

          Header=&#34;City&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=City}&#34;
          ctrl:ProportionalColumn.Width=&#34;1&#34;
          Header=&#34;Zip&#34; /&gt;

        &lt;GridViewColumn
          DisplayMemberBinding=&#34;{Binding Path=Country}&#34;

          ctrl:ProportionalColumn.Width=&#34;2&#34;
          Header=&#34;Country&#34; /&gt;
      &lt;/GridView&gt;

    &lt;/ListView.View&gt;
  &lt;/ListView&gt;&lt;/pre&gt;
&lt;h3 id=&#34;使用后台代码控制listviewgridview布局&#34;&gt;使用后台代码控制ListView/GridView布局&lt;/h3&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
ListView listView = new ListView();
 new ListViewLayoutManager( listView ); // attach the layout manager

 GridView gridView = new GridView();
 gridView.Columns.Add( FixedColumn.ApplyWidth( new MyGridViewColumn( &#34;State&#34; ), 25 ) );
 gridView.Columns.Add( RangeColumn.ApplyWidth( new MyGridViewColumn( &#34;Name&#34; ), 100,
     150, 200 ) ); // 100...200
 gridView.Columns.Add( ProportionalColumn.ApplyWidth( new MyGridViewColumn( &#34;City&#34; ),
     1 ) ); // 33%
 gridView.Columns.Add( ProportionalColumn.ApplyWidth( new MyGridViewColumn(
     &#34;Country&#34; ), 2 ) ); // 66%

 listView.View = gridView;
&lt;/pre&gt;
&lt;h3 id=&#34;定制列的效果&#34;&gt;定制列的效果&lt;/h3&gt;
&lt;p&gt;类ConverterGridColumn 作为一个基类，用来绑定列到独立的对象。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#编写youtube下载器</title>
      <link>http://blog.leaver.me/2012/09/25/c%23%E7%BC%96%E5%86%99youtube%E4%B8%8B%E8%BD%BD%E5%99%A8/</link>
      <pubDate>Tue, 25 Sep 2012 09:33:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/25/c%23%E7%BC%96%E5%86%99youtube%E4%B8%8B%E8%BD%BD%E5%99%A8/</guid>
      <description>&lt;h3 id=&#34;介绍&#34;&gt;介绍&lt;/h3&gt;
&lt;p&gt;本文将会暂时如何仅仅使用C#来下载youtub视频，代码简单也容易理解，每个人都可以把它整合到自己的工程项目里。&lt;/p&gt;
&lt;p&gt;我没有使用任何第三方的库来完成这段代码，你所要做的仅仅是把两个.cs文件整合进你的项目里。&lt;/p&gt;
&lt;h3 id=&#34;使用代码&#34;&gt;使用代码&lt;/h3&gt;
&lt;p&gt;这个工程里有两个主要的类&lt;/p&gt;
&lt;p&gt;YouTubeVideoQuality Class（youtube视频质量类）&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;public class YouTubeVideoQuality 
{
    /// &amp;lt;summary&amp;gt;
    /// Gets or Sets 文件名
    /// &amp;lt;/summary&amp;gt;
    public string Videotitle: { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets or Sets 文件扩展
    /// &amp;lt;/summary&amp;gt;
    public string Extention { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets or Sets 文件地址
    /// &amp;lt;/summary&amp;gt;
    public string DownloadUrl { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets or Sets 视频地址
    /// &amp;lt;/summary&amp;gt;
    public string VideoUrl { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets or Sets 文件大小
    /// &amp;lt;/summary&amp;gt;
    public Size Dimension { get; set; }

    public override string ToString()
    {
        return Extention + &#34; File &#34; + Dimension.Width + 
                           &#34;x&#34; + Dimension.Height;
    }

    public void SetQuality(string Extention, Size Dimension)
    {
        this.Extention = Extention;
        this.Dimension = Dimension;
    }
}&lt;/pre&gt; 
&lt;p&gt;YouTubeDownloader Class(youtube下载类)&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;public class YouTubeDownloader
{
    public static List&amp;lt;YouTubeVideoQuality&amp;gt; GetYouTubeVideoUrls(params string[] VideoUrls)
    {
        List&amp;lt;YouTubeVideoQuality&amp;gt; urls = new List&amp;lt;YouTubeVideoQuality&amp;gt;();
        foreach (var VideoUrl in VideoUrls)
        {
            string html = Helper.DownloadWebPage(VideoUrl);
            string title: = GetTitle(html);
            foreach (var videoLink in ExtractUrls(html))
            {
                YouTubeVideoQuality q = new YouTubeVideoQuality();
                q.VideoUrl = VideoUrl;
                q.Videotitle: = title;
                q.DownloadUrl = videoLink + &#34;&amp;amp;title=&#34; + title;
                if (getQuality(q))
                    urls.Add(q);
            }
        }
        return urls;
    }

    private static string GetTitle(string RssDoc)
    {
        string str14 = Helper.GetTxtBtwn(RssDoc, &#34;&#39;VIDEO_TITLE&#39;: &#39;&#34;, &#34;&#39;&#34;, 0);
        if (str14 == &#34;&#34;) str14 = Helper.GetTxtBtwn(RssDoc, &#34;\&#34;title\&#34; content=\&#34;&#34;, &#34;\&#34;&#34;, 0);
        if (str14 == &#34;&#34;) str14 = Helper.GetTxtBtwn(RssDoc, &#34;&amp;amp;title=&#34;, &#34;&amp;amp;&#34;, 0);
        str14 = str14.Replace(@&#34;\&#34;, &#34;&#34;).Replace(&#34;&#39;&#34;, &#34;&#39;&#34;).Replace(
                &#34;\&#34;&#34;, &#34;&#34;&#34;).Replace(&#34;&amp;lt;&#34;, &#34;&amp;lt;&#34;).Replace(
                &#34;&amp;gt;&#34;, &#34;&amp;gt;&#34;).Replace(&#34;+&#34;, &#34; &#34;);
        return str14;
    }

    private static List&amp;lt;string&amp;gt; ExtractUrls(string html)
    {
        html = Uri.UnescapeDataString(Regex.Match(html, &#34;url_encoded_fmt_stream_map=(.+?)&amp;amp;&#34;, 
                                      RegexOptions.Singleline).Groups[1].ToString());
        MatchCollection matchs = Regex.Matches(html, 
          &#34;url=(.+?)&amp;amp;quality=(.+?)&amp;amp;fallback_host=(.+?)&amp;amp;type=(.+?)&amp;amp;itag=(.+?),&#34;, 
          RegexOptions.Singleline);
        bool firstTry = matchs.Count &amp;gt; 0;
        if (!firstTry)
            matchs = Regex.Matches(html, 
                     &#34;itag=(.+?)&amp;amp;url=(.+?)&amp;amp;type=(.+?)&amp;amp;fallback_host=(.+?)&amp;amp;sig=(.+?)&amp;amp;quality=(.+?),{0,1}&#34;, 
                     RegexOptions.Singleline);
        List&amp;lt;string&amp;gt; urls = new List&amp;lt;string&amp;gt;();
        foreach (Match match in matchs)
        {
            if (firstTry)
                urls.Add(Uri.UnescapeDataString(match.Groups[1] + &#34;&#34;));
            else urls.Add(Uri.UnescapeDataString(match.Groups[2] + &#34;&#34;) + &#34;&amp;amp;signature=&#34; + match.Groups[5]);
        }
        return urls;
    }

    private static bool getQuality(YouTubeVideoQuality q)
    {
        if (q.DownloadUrl.Contains(&#34;itag=5&#34;))
            q.SetQuality(&#34;flv&#34;, new Size(320, 240));
        else if (q.DownloadUrl.Contains(&#34;itag=34&#34;))
            q.SetQuality(&#34;flv&#34;, new Size(400, 226));
        else if (q.DownloadUrl.Contains(&#34;itag=6&#34;))
            q.SetQuality(&#34;flv&#34;, new Size(480, 360));
        else if (q.DownloadUrl.Contains(&#34;itag=35&#34;))
            q.SetQuality(&#34;flv&#34;, new Size(640, 380));
        else if (q.DownloadUrl.Contains(&#34;itag=18&#34;))
            q.SetQuality(&#34;mp4&#34;, new Size(480, 360));
        else if (q.DownloadUrl.Contains(&#34;itag=22&#34;))
            q.SetQuality(&#34;mp4&#34;, new Size(1280, 720));
        else if (q.DownloadUrl.Contains(&#34;itag=37&#34;))
            q.SetQuality(&#34;mp4&#34;, new Size(1920, 1280));
        else if (q.DownloadUrl.Contains(&#34;itag=38&#34;))
            q.SetQuality(&#34;mp4&#34;, new Size(4096, 72304));
        else return false;
        return true;
    }
}&lt;/pre&gt; 
&lt;h3 id=&#34;有趣的地方&#34;&gt;有趣的地方&lt;/h3&gt;
&lt;p&gt;使用这个代码，你可以根据你的网速来选择不同品质的视频来下载&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#删除文件和文件夹到回收站</title>
      <link>http://blog.leaver.me/2012/09/24/c%23%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E5%92%8C%E6%96%87%E4%BB%B6%E5%A4%B9%E5%88%B0%E5%9B%9E%E6%94%B6%E7%AB%99/</link>
      <pubDate>Mon, 24 Sep 2012 08:04:45 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/c%23%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E5%92%8C%E6%96%87%E4%BB%B6%E5%A4%B9%E5%88%B0%E5%9B%9E%E6%94%B6%E7%AB%99/</guid>
      <description>&lt;p&gt;如果使用C#代码来删除文件或是文件夹。会将文件和文件夹直接删除，而不是删除到回收站。可以调用Microsoft.VisualBasic.dll提供的方法。&lt;/p&gt;
&lt;p&gt;首先对项目添加名为Microsoft.VisualBasic.dll的引用，然后添加命名空间&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;using Microsoft.VisualBasic.FileIO;&lt;/pre&gt; 
&lt;p&gt;最后示例代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;using System;
using Microsoft.VisualBasic.FileIO;
namespace leaver
{
    class Program
    {

        static void Main(string[] args)
        {

            Console.WriteLine(&#34;删除文件到回收站&#34;);
            string filepath = &#34;leaver.txt&#34;;
            FileSystem.DeleteFile(filepath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
            Console.WriteLine(&#34;删除文件完成&#34;);

            Console.WriteLine(&#34;删除文件夹到回收站&#34;);
            string dirpath = &#34;leaver&#34;;
            FileSystem.DeleteDirectory(dirpath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
            Console.WriteLine(&#34;删除文件夹完成&#34;);
        }
    }
}&lt;/pre&gt; 
&lt;p&gt;很简单。。就不多说了。。&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用Microsoft Web Deploy技术自动部署</title>
      <link>http://blog.leaver.me/2012/09/04/%E4%BD%BF%E7%94%A8microsoft-web-deploy%E6%8A%80%E6%9C%AF%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/</link>
      <pubDate>Tue, 04 Sep 2012 14:03:18 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/04/%E4%BD%BF%E7%94%A8microsoft-web-deploy%E6%8A%80%E6%9C%AF%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/</guid>
      <description>&lt;p&gt;　　在前段时间使用WCF的时候。部署到服务器上一直不得要领。出现各种问题。最终搞定。原文图很多，我给个摘要，大家还是原文看。因为原文写于2010年。自动部署工具已经更新至第3版。所以有些按钮得好好找找。不过相信对大家都不是难事。&lt;/p&gt;
&lt;p&gt;　　本篇文章将提供一个循序渐进的教程，教你如何在一台Web服务期上安装和启用Web Deploy。接着我们演示如何使用Visual Studio通过Web Deploy直接（将文件）发布到服务器上，以及如何使用Visual Studio创建自动部署你的应用程序的安装包。&lt;/p&gt;
&lt;p&gt;　　&lt;strong&gt;Web Deploy—为什么你会喜欢它&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　部署一个Web应用程序或站点包含好几个步骤。您通常需要：&lt;/p&gt;
&lt;p&gt;　　1. 拷贝文件和文件夹；&lt;/p&gt;
&lt;p&gt;　　2. 提供数据库结构，或许还要生成一些数据库数据；&lt;/p&gt;
&lt;p&gt;　　3. 在文件和文件夹上设置相应的读写和安全访问控制列表；&lt;/p&gt;
&lt;p&gt;　　4. 安装和配置SSL认证；&lt;/p&gt;
&lt;p&gt;　　5. 部署其它杂七杂八的依赖项（事件日志，GAC库，COM对象等等）。&lt;/p&gt;
&lt;p&gt;　　手工执行上面的步骤又累又慢又危险（因为手工部署总是容易出错）。使用自动化流程，可以让你在一台服务器上快速维护和部署应用程序，减少出错的几率，并极大加快你在应用程序上的改动放到作业服务器上的周期。&lt;/p&gt;
&lt;p&gt;　　去原文看看吧。&lt;a href=&#34;http://blog.joycode.com/scottgu/archives/2010/11/03/116148.joy&#34;&gt;使用Microsoft Web Deploy技术自动部署&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>超时时间已到，但是尚未从池中获取连接</title>
      <link>http://blog.leaver.me/2012/09/03/%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B7%B2%E5%88%B0%E4%BD%86%E6%98%AF%E5%B0%9A%E6%9C%AA%E4%BB%8E%E6%B1%A0%E4%B8%AD%E8%8E%B7%E5%8F%96%E8%BF%9E%E6%8E%A5/</link>
      <pubDate>Mon, 03 Sep 2012 08:47:31 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/03/%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B7%B2%E5%88%B0%E4%BD%86%E6%98%AF%E5%B0%9A%E6%9C%AA%E4%BB%8E%E6%B1%A0%E4%B8%AD%E8%8E%B7%E5%8F%96%E8%BF%9E%E6%8E%A5/</guid>
      <description>&lt;p&gt;　　前段时间数据库的时候，出现这个问题。一般是读到20多万条的时候。会出现这个问题。&lt;/p&gt;
&lt;p&gt;　　找了一下。主要是这两个问题：&lt;/p&gt;
&lt;p&gt;　　一、看所有open的连接是否都close了。&lt;/p&gt;
&lt;p&gt;　　二、如果访问量很大，加上Max   Pool   Size=512这一句，当然这是要以损失系统性能为代价的！&lt;/p&gt;
&lt;p&gt;　　我查了一下。数据库连接所有的open都关闭了。 max pool size也确实加上了。但是。问题依旧。。&lt;/p&gt;
&lt;p&gt;　　哦，还有的说在数据库连接字串中添加Connect Timeout=500，也就是设置连接超时更长一些。问题依旧。。&lt;/p&gt;
&lt;p&gt;　　后来看到一篇文章中说：&lt;/p&gt;
&lt;p&gt;　　DataReader是独占连接 的，每个DataReader都要占用一个连接。当然这个情况是偶尔出现的，所以会很长时间出现一次，因为只有同时有超过连接池最大连接数量的并发操作才 会发生。而且你加大并发数量只能暂时缓解问题。&lt;/p&gt;
&lt;p&gt;　　文中建议用使用dataset来读取。然后我就把读取数据中使用DataReader的地方全部用DataAdapter和DataSet来获取数据库数据，因为DataSet非独占。会将数据保存在内存中，一次连接后释放，问题解决。&lt;/p&gt;
&lt;p&gt;　　记录一下。&lt;/p&gt;</description>
    </item>
    <item>
      <title>面试体验：Google 篇</title>
      <link>http://blog.leaver.me/2012/08/11/%E9%9D%A2%E8%AF%95%E4%BD%93%E9%AA%8Cgoogle-%E7%AF%87/</link>
      <pubDate>Sat, 11 Aug 2012 14:30:10 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/08/11/%E9%9D%A2%E8%AF%95%E4%BD%93%E9%AA%8Cgoogle-%E7%AF%87/</guid>
      <description>&lt;p&gt;　　尝试在&lt;a href=&#34;http://www.cnblogs.com/cathsfz/archive/2012/08/08/google-interview-experience.html&#34;&gt;自己的博客&lt;/a&gt;上搜索点东西，结果发现 4 年多以前还在博客上写过一系列的 recruiting events，把大四时候参加过的各种笔试面试都记录下来了。我从去年准备离开百度开始，到现在总过面试过 4 家公司：Google、Microsoft、Yahoo、Facebook，原本去年也想把面试经验写一写的，结果一拖就拖到现在。我不想写面试经验，因为我个人不喜欢漏题和背题的做法。我自己作为面试官，知道要设计出来一道好用的题目有多难，所以我希望面试者都是如实表现自己解题能力的。我更喜欢写面试体验，就是在整个面试过程中一家公司给人的印象是怎样的，HR 和面试官是否专业，能否让人信服这是一家值得长期工作的公司。&lt;/p&gt;
&lt;p&gt;　　我想写的第一家公司是 Google，因为它是我在想要离开百度时第一家联系到我的公司。2010 年 12 月底的某一天早上，我突然感觉到我应该离开百度，因为如果这个时候已经没有勇气离开这家公司了，很可能就不会再想要离开了。当天中午在百度大厦西餐厅吃午饭，接到一个 Google 上海 HR 的电话，问我有没有兴趣去面试，我想既然你打电话来的时机那么好，我就答应你去面试吧。（在那一天之前，我对猎头的标准回复是「有美国或者香港的职位吗？」）她问我将来希望在北京还是上海工作，当时我对北京的厌恶程度还没有现在那么高，同时觉得搬家到上海又比较麻烦，于是就说在北京，接着我就变成跟北京 HR 沟通了。&lt;/p&gt;
&lt;p&gt;　　Google 的 HR 会负责做两件简单得不需要面试官做的事情，这能够很好的提高招聘流程的效率。第一件是确认你能够适应工作环境中的英语，为此 HR 要我用英语跟她对话两三分钟，主要就是让我说说工作经验和其中的亮点。习惯在私企工作的人不要以为外企对英语的要求很高，其实大多数长期在中国工作的人说话或者发邮件都会很 Chinglish 啦，所以关键是要敢于用英语进行沟通。&lt;/p&gt;
&lt;p&gt;　　然后 HR 发了一个 Codility 的地址给我，让我有空抽时间去做题。一个小时 3 道难度相当于 OI 基础题的题目，平均 20 分钟一道。最简单的题目一看就知道是 O(n) 能解决的，最复杂的题目看上去是 O(n^2) 但想一下就能优化为 O(n log n)。对于有算法训练背景的人来说，这样的题目会让人感觉到很有把握。对于没有经受过算法训练的人来说，掉进陷阱里是很容易的。很可能没有把 O(n^2) 优化为 O(n log n)，结果超时；可能没仔细看题目说明的数值取值范围，某些变量选错了数值类型，结果溢出。考虑到 Google 重视算法的程度，再加上 Google 中国面试的额外难度，算法训练还是很必要的。&lt;/p&gt;
&lt;p&gt;　　在我通过 Codility 测试后，HR 问我了对题目难度的反馈，然后约了一轮电话面试，并且告知面试主要围绕算法、数据结构、系统设计、编码来进行。Google 面试的格式都很固定，45 分钟内期望你能做出 3 道题来。这 3 道题最起码要能把人人都能想出来的「笨办法」用代码写出来，否则会让面试官感到不满意。如果有些题目能够比较快地做出来，面试官就会让你优化。就算你第一次给出的答案已经是业界已知最优解，面试官都还是会让你优化，因为谁也不知道有没有人能在面试过程中突然爆发，想出一些过去没人想到过的解法。如果面试官心中已有优化的方案，在你想不出优化方案时他可能会给你提供一些提示。&lt;/p&gt;
&lt;p&gt;　　一轮电话面试后，HR 就开始约到 Google 办公室的面试了。第一次约了下午 3 轮面试，还是那个很固定的格式：每轮面试 45 分钟，两轮间隔 15 分钟。整个面试流程让人感觉到很人性化：在 Google 签到后，HR 会先带你去 kitchen 拿点吃的喝的，然后把你带到面试所用的会议室。多轮面试的话，HR 中间还会来问一下你要不要去洗手间，或者多拿两瓶水。面试完毕后 HR 会来问你感觉如何，同时也会让你知道面试官的初步反馈是否跟你的感觉一致。我在 3 轮面试中有一轮感觉不太好，因为面试官只给了 2 道题，并且我最终都没办法解出来，HR 也确认了就是这一轮的反馈不好。&lt;/p&gt;
&lt;p&gt;　　此外，Google 的招聘流程还让人感觉到很有效率。作为面试官，我也知道自己写面试反馈有多喜欢拖延，而且公司填写面试反馈的系统越不人性化我就越想要拖延，然而公司内部系统做得人性化的又实在罕见。Google 的面试基本上隔天就有结果，然后 HR 就会约下一轮的面试。因为我在百度的时候每周哪个时间没有会议是很确定的，所以我总是选择下周同一个时间段来面试。在经过总共 4 轮面试后，HR 说因为前面有一轮的面试官反馈不好，所以希望再加一轮面试。因为前面反馈不好的面试官比较 senior，所以这次找了一位同样 senior 的面试官来面试，于是我又去了一次 Google 办公室。&lt;/p&gt;
&lt;p&gt;　　完成 5 轮面试后，HR 把材料提交给 Google 的北京招聘委员会，结果没有通过。HR 说，因为 Google 都是按照后端工程师的标准来招聘，看重算法和数据结构，前端工程师要通过不容易。因为 Google 没有专门的前端工程师，只有一个软件工程师职位，所以所有人还是必须按照一个标准来衡量。她问我如果找到专门需要前端工程师的团队，并且需要额外再面试的话，我是否感兴趣。当时 Google 是我的第一选择，我当然说感兴趣啦。&lt;/p&gt;
&lt;p&gt;　　后来 HR 跟我说，她帮忙问过 Google Maps，可惜对方说不要专才只要通才。又过了几个星期，HR 发现 IME 需要专门做前端的人，于是帮我再约了一轮面试。这轮面试是在 Google 办公室做的，但实际上是视频会议，因为面试官在美国。（不确定面试官是在美国出差，还是美籍华人。）面试过程跟电话面试类似，用 Google Docs 写代码，比电话面试要好的是说话时能够见到人。&lt;/p&gt;
&lt;p&gt;　　这一轮面试结束后，我的材料再次进入 Google 的北京招聘委员会。HR 说这次专门找了对前端有经验的人来审阅我的材料，结果顺利通过了。接着 HR 问我要了一大堆的补充材料，包括高考成绩和 GPA（连同成绩单），还包括当前薪酬和竞争对手的 offer（我当时有 Yahoo 的 offer），甚至包括过去的获奖和晋升经历。所有这些材料都会发往 Google 美国总部审阅，具体流程 HR 没有细说，但看 Don Dodge 的文章可以了解一些。最后我被 Google 美国总部给拒绝了，然后 HR 还是一如既往地及时沟通，并且安慰了我几句。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#调用Matlab引擎</title>
      <link>http://blog.leaver.me/2012/08/09/c%23%E8%B0%83%E7%94%A8matlab%E5%BC%95%E6%93%8E/</link>
      <pubDate>Thu, 09 Aug 2012 22:39:57 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/08/09/c%23%E8%B0%83%E7%94%A8matlab%E5%BC%95%E6%93%8E/</guid>
      <description>&lt;p&gt;　　最近在使用matlab的时候。求多元函数取得最小值的时候。变量的值。于是就用到了sym符号。结果在C#中调用时总是出错。后来Google了N久发现是符号工具箱是无法编译的。。后来找到了替代方法。就是调用matlab 引擎。当然要稍微麻烦一点。因为调用引擎这种方法参数传递比较麻烦。我只想到了通过C#把需要计算的值保存到文本中。然后matlab中load进来。计算完成后 save出去。。&lt;/p&gt;
&lt;p&gt;　　调用matlab引擎类似于在C#中新开了一个进程。然后执行一些命令。之前需要引用Matlab Application Type Library。这是个com组件&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/25657_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b938768405ede59db17f36bdc27e700bf3cbf1dc.jpg&#34; title=&#34;type&#34;&gt;&lt;/a&gt;
然后在程序里使用 using语句&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;using MLApp;&lt;/pre&gt; 
&lt;p&gt;然后就可以正常使用了。使用我试过的有两种方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;MLApp.MLAppClass matlab = new MLApp.MLAppClass();  
matlab.Visible = 1;  
string command=&#34;figure(1)&#34;;
matlab.Execute(command);  
matlab.Quit();&lt;/pre&gt; 
&lt;p&gt;很简单。Visible设置可见性。。command表示要执行的命令。&lt;/p&gt;
&lt;p&gt;另一种是&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;MLApp.DIMLApp matlab = null;  
Type matlabAppType = System.Type.GetTypeFromProgID(&#34;Matlab.Application&#34;);  
matlab = System.Activator.CreateInstance(matlabAppType) as MLApp.DIMLApp;  
matlab.Visible = 1;  
string command=&#34;figure(2)&#34;;
matlab.Execute(command);  
matlab.Quit();&lt;/pre&gt; 
&lt;p&gt;不知什么原因，第一种方法我没有调用成功。第二种调用成功。欢迎讨论。&lt;/p&gt;</description>
    </item>
    <item>
      <title>WPF实现控件拖动效果</title>
      <link>http://blog.leaver.me/2012/07/27/wpf%E5%AE%9E%E7%8E%B0%E6%8E%A7%E4%BB%B6%E6%8B%96%E5%8A%A8%E6%95%88%E6%9E%9C/</link>
      <pubDate>Fri, 27 Jul 2012 07:18:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/27/wpf%E5%AE%9E%E7%8E%B0%E6%8E%A7%E4%BB%B6%E6%8B%96%E5%8A%A8%E6%95%88%E6%9E%9C/</guid>
      <description>&lt;p&gt;首先很简单，当然是去添加两个控件了，这里我添加了两个控件，都是label，然后我想实现的是将label1拖动到label2上的时候，label1的内容会被复制到label2上。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt; &amp;lt;Label Content=&#34;TestDrop&#34; 
Height =&#34;28&#34; HorizontalAlignment=&#34;Left&#34; Margin=&#34;70,35,0,0&#34; Name =&#34;label1&#34; 
VerticalAlignment=&#34;Top&#34; MouseDown=&#34;label1_MouseDown&#34;  /&amp;gt;

&amp;lt;Label Content =&#34;ToHere&#34; Height=&#34;28&#34; HorizontalAlignment=&#34;Left&#34; 
Margin =&#34;342,107,0,0&#34; Name=&#34;label2&#34; VerticalAlignment=&#34;Top&#34; AllowDrop =&#34;True&#34;
 Drop=&#34;tagert_drop&#34;   /&amp;gt;&lt;/pre&gt; 
&lt;p&gt;需要注意的代码是label1中的MouseDown事件。和label2中的AllowDrop =&amp;ldquo;True&amp;rdquo;  Drop=&amp;ldquo;tagert_drop&amp;rdquo;&lt;/p&gt;
&lt;p&gt;然后对应的处理事件&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;     private void label1_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Label lbl = (Label )sender;
            DragDrop.DoDragDrop(lbl, lbl.Content, DragDropEffects .Copy);
        }

        private void tagert_drop(object sender, DragEventArgs e)
        {
            (( Label)sender).Content = e.Data.GetData(DataFormats.Text);
        }&lt;/pre&gt; 
&lt;p&gt;其他的效果可以仿照这个来做。比如拖动以后的效果可以DragDropEffects来设置。。&lt;/p&gt;</description>
    </item>
    <item>
      <title>DevExpress DXperience Universal 12.1.5 破解补丁</title>
      <link>http://blog.leaver.me/2012/07/21/devexpress-dxperience-universal-12.1.5-%E7%A0%B4%E8%A7%A3%E8%A1%A5%E4%B8%81/</link>
      <pubDate>Sat, 21 Jul 2012 12:08:08 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/21/devexpress-dxperience-universal-12.1.5-%E7%A0%B4%E8%A7%A3%E8%A1%A5%E4%B8%81/</guid>
      <description>&lt;p&gt;　　因为要用到wpf开发软件，而作为一个审美能力和制作美的能力完全不匹配的人。。需要有一个基本的主题框架来作为基础进行开发。。于是我找了找。。刚开始找的是http://www.telerik.com/这个商业库，不过这个用的不太顺手，于是还是试试DevExpress，，果断很不错，找到了破解补丁。
给一个官方的Demo示例图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/25025_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5de045da9ce167999bd9e8df93580d0c93579daf.jpg&#34; title=&#34;Demo&#34;&gt;&lt;/a&gt;
安装文件：&lt;a href=&#34;http://downloads.devexpress.com/d0577ccc-5137-4622-b397-a128d153f2aa/0.0.0.0/DXperience/2012.1/5/DXperience-12.1.5.exe&#34;&gt;DXperience-12.1.5安装包&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;帮助文档：&lt;a href=&#34;http://downloads.devexpress.com/24614371-d026-41ab-89c8-b2c3769f9059/0.0.0.0/DXperience/2012.1/Help/DXperienceHelp2010-12.1.5.exe&#34;&gt;DXperience 12.1.5 Universal 帮助文档&lt;/a&gt;：&lt;/p&gt;
&lt;p&gt;破解补丁：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=34831&amp;amp;uk=1493685990&#34;&gt;DevExpress.Registration.Setup.v12.1.5.E3.msi&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>未能加载文件或程序集“App_Web_xxxx”</title>
      <link>http://blog.leaver.me/2012/07/14/%E6%9C%AA%E8%83%BD%E5%8A%A0%E8%BD%BD%E6%96%87%E4%BB%B6%E6%88%96%E7%A8%8B%E5%BA%8F%E9%9B%86app_web_xxxx/</link>
      <pubDate>Sat, 14 Jul 2012 23:18:13 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/14/%E6%9C%AA%E8%83%BD%E5%8A%A0%E8%BD%BD%E6%96%87%E4%BB%B6%E6%88%96%E7%A8%8B%E5%BA%8F%E9%9B%86app_web_xxxx/</guid>
      <description>&lt;p&gt;　　今天在用WCF写服务的时候，服务一直连不上，直接查看svc文件，发现如下错误
未能加载文件或程序集“&amp;lsquo;App_Web_****, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null&amp;quot;,****是一个随机字符串。&lt;/p&gt;
&lt;p&gt;解决方法中：&lt;/p&gt;
&lt;p&gt;　　在web.config里配置成这样子：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt; &amp;lt;compilation debug=&#34;true&#34; batch=&#34;false&#34;&amp;gt;&lt;/pre&gt;
&lt;p&gt;　　就好了。中午和下午一直在搞javascript连接WCF的demo，总算是晚上搞定了，，还是老样子，，最大的体会就是很多东西就是看着简单，写起来会有各种各样的问题，比如这次，即使照着微软的官方文档来，也会有错误。动手才是王道，不管做什么。这几天忙完了，写篇文章出来。&lt;/p&gt;
&lt;p&gt;　　最后分享一下微软官方的&lt;a href=&#34;http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/WCF_Ajax.aspx&#34;&gt;WCF与Ajax开发实践系列课程&lt;/a&gt;，我只能说WCF这东西没有哪一本书比微软官方的技术培训讲的更好了，非常建议学习。&lt;/p&gt;
&lt;p&gt;　　武汉最近下雨了，天气挺凉爽，过几天准备回家吧。。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SQLServer启用xp_cmdshell</title>
      <link>http://blog.leaver.me/2012/07/11/sqlserver%E5%90%AF%E7%94%A8xp_cmdshell/</link>
      <pubDate>Wed, 11 Jul 2012 14:20:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/11/sqlserver%E5%90%AF%E7%94%A8xp_cmdshell/</guid>
      <description>&lt;p&gt;忘了当时是执行哪条命令的时候需要启动xp_cmdshell了。。反正是必须用的。。&lt;/p&gt;
&lt;p&gt;默认情况下,sql server安装完后,xp_cmdshell是禁用的(可能是安全考虑),如果要使用它,可按以下步骤&lt;/p&gt;
&lt;pre class=&#34;lang:pgsql decode:true&#34;&gt;-- 允许配置高级选项
EXEC sp_configure &#39;show advanced options&#39;, 1
GO
-- 重新配置
RECONFIGURE
GO
-- 启用xp_cmdshell
EXEC sp_configure &#39;xp_cmdshell&#39;, 1
GO
--重新配置
RECONFIGURE
GO

--执行想要的xp_cmdshell语句
Exec xp_cmdshell &#39;query user&#39;
GO

--用完后,要记得将xp_cmdshell禁用(出于安全考虑)
-- 允许配置高级选项
EXEC sp_configure &#39;show advanced options&#39;, 1
GO
-- 重新配置
RECONFIGURE
GO
-- 禁用xp_cmdshell
EXEC sp_configure &#39;xp_cmdshell&#39;, 0
GO
--重新配置
RECONFIGURE
GO&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 线程优秀文章汇总</title>
      <link>http://blog.leaver.me/2012/07/11/c%23-%E7%BA%BF%E7%A8%8B%E4%BC%98%E7%A7%80%E6%96%87%E7%AB%A0%E6%B1%87%E6%80%BB/</link>
      <pubDate>Wed, 11 Jul 2012 14:04:07 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/11/c%23-%E7%BA%BF%E7%A8%8B%E4%BC%98%E7%A7%80%E6%96%87%E7%AB%A0%E6%B1%87%E6%80%BB/</guid>
      <description>&lt;p&gt;最近在看线程的东西，整理一些文档以便学习。分享。&lt;/p&gt;
&lt;h3 id=&#34;刚刚&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/xugang&#34;&gt;刚刚&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42528&#34;&gt;C#多线程学习(一) 多线程的相关概念&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42529&#34;&gt;C#多线程学习(二) 如何操纵一个线程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42530&#34;&gt;C#多线程学习(三) 生产者和消费者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42531&#34;&gt;C#多线程学习(四) 多线程的自动管理(线程池)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42532&#34;&gt;C#多线程学习(五) 多线程的自动管理(定时器)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42533&#34;&gt;C#多线程学习(六) 互斥对象&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/xugang/archive/2011/03/20/1989782.html&#34;&gt;C# 实现多线程的同步方法详解&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;jimmyzheng&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng&#34;&gt;JimmyZheng&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html&#34;&gt;C# 温故而知新： 线程篇(一)&lt;/a&gt; &lt;strong&gt;Thread&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/07/07/2580253.html&#34;&gt;C# 温故而知新： 线程篇(二)&lt;/a&gt; 线程池和异步线程&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;zhoufoxcn&#34;&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn&#34;&gt;zhoufoxcn&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/4402999&#34;&gt;C#多线程编程（1）：线程的启动&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/5170815&#34;&gt;多线程编程(2)：线程的同步&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/5177579&#34;&gt;多线程编程(3)：线程池ThreadPool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/5205690&#34;&gt;多线程编程(4)：多线程与UI操作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/2453803&#34;&gt;一个简单的C#多线程间同步的例子&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;老赵&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao&#34;&gt;老赵&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html&#34;&gt;浅谈线程池（上）：线程池的作用及CLR线程池&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao/archive/2009/07/24/thread-pool-2-dedicate-pool-and-io-pool.html&#34;&gt;浅谈线程池（中）：独立线程池的作用及IO线程池&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao/archive/2009/10/20/thread-pool-3-lab.html&#34;&gt;浅谈线程池（下）：相关试验及注意事项&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;bloodish&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/bloodish&#34;&gt;bloodish&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/bloodish/archive/2011/03/21/1990025.html&#34;&gt;C# Tip &amp;ndash; 如何优雅的控制线程状态&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;autumoon&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/Autumoon&#34;&gt;Autumoon&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/Autumoon/archive/2008/06/19/1225684.html&#34;&gt;白话多线程&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>CSV批量导入解决</title>
      <link>http://blog.leaver.me/2012/07/06/csv%E6%89%B9%E9%87%8F%E5%AF%BC%E5%85%A5%E8%A7%A3%E5%86%B3/</link>
      <pubDate>Fri, 06 Jul 2012 18:28:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/06/csv%E6%89%B9%E9%87%8F%E5%AF%BC%E5%85%A5%E8%A7%A3%E5%86%B3/</guid>
      <description>&lt;p&gt;　　最近的一个事就是那个诡异的CSV导入，后来决定用最笨的方法。就是readline，然后确实是可以正常识别了。思路就是一行行读入，然后构造sql语句，保存为sql文件，然后去批量执行sql文件。其实在codeproject找到了一些类似的工具，都有不如意的地方，但是时间关系还没能自己去定制，这件事完成后，就去完善一下大牛们的工具。&lt;/p&gt;
&lt;p&gt;　　因为是多个csv文件，每个文件对应于我们想建的一个表，实际是大约2000个csv文件，每个文件大约4000行数据，构造成对应的sql语句比较简单，需要注意的就是如果sql server表中的字段和关键字重名，那么需要加[]，比如我们有个字段是open，那么实际sql语句中使用的时候，比如&lt;/p&gt;
&lt;pre class=&#34;lang:pgsql decode:true &#34; &gt;CREATE TABLE 
(
   [open] decimal not null,
)&lt;/pre&gt; 
&lt;p&gt;　　简单的读写以后我们构造了2000个sql文件，然后我们需要执行这些sql文件。。必然需要写个代码来批量执行了。。为此，我先用C#生成一个批处理文件，然后来执行&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;void GetBat(string InputPath,string OutFile)
        {
            DirectoryInfo di = new DirectoryInfo(InputPath);
            FileInfo[] fi = di.GetFiles();  // Create an array representing the files in the current directory
            StringBuilder strtemp = new StringBuilder();
            foreach (FileInfo fiTemp in fi)
            {
                string temp = &#34;osql -S \&#34;127.0.0.1\&#34;  -U \&#34;sa\&#34; -P \&#34;broker\&#34; -d \&#34;test_money\&#34; -i \&#34;&#34;;
                temp += fiTemp.FullName.ToString() + &#34;\&#34;\n&#34;;
                strtemp.Append(temp);
            }

            FileStream fs = new FileStream(OutFile, FileMode.OpenOrCreate);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(strtemp);
            sw.Close();
            fs.Close();
        }&lt;/pre&gt; 
&lt;p&gt;　　简单封装了一下，输入参数是文件夹。里面包含我们的所有sql文件。输出为一个批处理文件。。后来。执行下生成的bat文件就可以了。。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;osql -S &#34;127.0.0.1&#34;  -U &#34;sa&#34; -P &#34;broker&#34; -d &#34;test_money&#34; -i &#34;D:\test\AMKR.sql&#34;
osql -S &#34;127.0.0.1&#34;  -U &#34;sa&#34; -P &#34;broker&#34; -d &#34;test_money&#34; -i &#34;D:\test\AMLJ.sql&#34;
osql -S &#34;127.0.0.1&#34;  -U &#34;sa&#34; -P &#34;broker&#34; -d &#34;test_money&#34; -i &#34;D:\test\AMLN.sql&#34;
&lt;/pre&gt; 
&lt;p&gt;600M的sql文件执行起来三个多小时。。因为只算一次，所以就不考虑优化了。。鄙视我们吧。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#调用MatLab实现N阶幻方</title>
      <link>http://blog.leaver.me/2012/07/02/c%23%E8%B0%83%E7%94%A8matlab%E5%AE%9E%E7%8E%B0n%E9%98%B6%E5%B9%BB%E6%96%B9/</link>
      <pubDate>Mon, 02 Jul 2012 18:39:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/02/c%23%E8%B0%83%E7%94%A8matlab%E5%AE%9E%E7%8E%B0n%E9%98%B6%E5%B9%BB%E6%96%B9/</guid>
      <description>&lt;p&gt;　　MatLab的计算能力太强大了。最近需要通过C#来调用MatLab来进行一些计算，可是MatLab没用过。安装文件在我硬盘里躺了整整一年。&lt;/p&gt;
&lt;p&gt;　　我们希望的是由外部程序调用MatLab函数。所以。希望可以完全脱离MATLAB环境，实现软件的快速开发。为此需要先介绍一下MCR。&lt;/p&gt;
&lt;h3 id=&#34;mcr简介&#34;&gt;MCR简介&lt;/h3&gt;
&lt;p&gt;　　 MCR的全称是MATLAB Compiler Runtime，即MATLAB编译器运行时。是一个由MATLAB共享类库构成的执行引擎，他能够使MATLAB文件在没有MATLAB的机器上运行。这一点和.NET Framework相对于.NET程序一样，即为程序的运行提供了底层支持。当发布程序的时候，需要将MCR也打包进来，这样没有MATLAB的机器上也能执行，MCR随MATLAB软件一同发布，可以在MATLAB中输入命令“mcr”或者“mcrinstaller”获取其保存路径：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;&amp;gt;&amp;gt; mcr
The WIN32 MCR Installer, version 7.15, is:
    D:\Program Files\MATLAB\R2011a\toolbox\compiler\deploy\win32\MCRInstaller.exe

MCR installers for other platforms are located in:
    D:\Program Files\MATLAB\R2011a\toolbox\compiler\deploy\&amp;lt;ARCH&amp;gt;
  &amp;lt;ARCH&amp;gt; is the value of COMPUTER(&#39;arch&#39;) on the target machine.

Full list of available MCR installers:
D:\Program Files\MATLAB\R2011a\toolbox\compiler\deploy\win32\MCRInstaller.exe

For more information, read your local MCR Installer help.
Or see the online documentation at MathWorks&#39; web site. (Page may load slowly.)&lt;/pre&gt; 
&lt;p&gt;　　根据上面的运行结果，可知该文件的完整路径是：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;D:\Program Files\MATLAB\R2011a\toolbox\compiler\deploy\win32\MCRInstaller.exe&lt;/pre&gt; 
&lt;h3 id=&#34;mwarray-api简介&#34;&gt;MWArray API简介&lt;/h3&gt;
&lt;p&gt;　MCR包含了文件MWArray.dll，该文件中的API承担了用户程序和MCR之间数据交换的任务，因此，每一个独立文件都需要包含对该文件的引用，否则程序就不能使用MATLAB中的函数，为使用该文件，需要先使用上一步找到的安装MCR，我安装在D:\Program Files\MATLAB\MATLAB Compiler Runtime目录，然后该dll该文件在安装完MCR后位于：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;D:\Program Files\MATLAB\MATLAB Compiler Runtime\v715\toolbox\dotnetbuilder\bin\win32\v2.0，名字是MWArray.dll，&lt;/pre&gt; 
&lt;p&gt;　　另外，该文件中有两个重要的命名空间，MathWorks.MATLAB.NET.Arrays和MathWorks.MATLAB.NET.Utility，Arrays命名空间下的类提供从其他任何兼容CLS（Common Language Specification） 语言访问MATLAB中数组的功能，这些类支持数组格式化、类型的特定索引和错误处理的功能。而Utility命名空间下的类提供了对MWArray类架构和MATLAB公共运行时的托管API的通用支持。&lt;/p&gt;
&lt;h3 id=&#34;实施&#34;&gt;实施&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;为了将MATLAB中的程序作为组件提供给其他.NET程序使用，需要做两方面的工作：&lt;/p&gt;
&lt;p&gt;1.将M文件打包为与.NET兼容的程序集&lt;/p&gt;
&lt;p&gt;2.在外部程序中添加对程序集的引用&lt;/p&gt;
&lt;h3 id=&#34;matlab端的工作&#34;&gt;MATLAB端的工作&lt;/h3&gt;
&lt;p&gt;　　以我这个功能为例。打开MatLab，然后File-&amp;gt;New-&amp;gt;Deployment Project.然后在Type里选择.net Assembly,Ok即可。我选择的工程名是test，注意，这个test就会生成一个名为test.dll的程序集，所以起个好名字，，我没起好。如图1
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23964_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/494daca0321a65539ea6b2c7d6d3155345c3c32d.jpg&#34; title=&#34;start&#34;&gt;&lt;/a&gt;
　　然后在图2的视图中定位到你选择的工程目录，并依次点击。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23966_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b2e74076bfe76e6aeac6b3b7365668d2f23431fe.jpg&#34; title=&#34;step&#34;&gt;&lt;/a&gt;
　　添加一个test.m的文件。图3
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23965_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/110d97e0942789e04445dd3d3eee89873c49de11.jpg&#34; title=&#34;test&#34;&gt;&lt;/a&gt;这个名称随意。但是要注意，这个名字必须和你里面将要写的那个函数名称一致，这个很好理解。好了以后，双击test.m就会打开。输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;function m=test(n)
m=magic(n);
end&lt;/pre&gt; 
&lt;p&gt;　　创建一个test方法。该方法在C#调用的时候要用到，接受一个参数，然后输出一个幻方。保存关闭m文件，然后回到上图，双击test.prj也就是工程文件。
来到图4
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23967_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5ab49b4504bc1aba33d62b3c2cfbf897656c751d.jpg&#34; title=&#34;add&#34;&gt;&lt;/a&gt;
　　点击Add Class，就是向test.dll的程序集中添加类。我添加了一个类叫做Func1.这个类用来在C#中创建一个对象，然后调用test（n）这个函数，然后出现Add Files，点击打开浏览框，把刚才写好的test.m选上。就可以了
　　最后看窗口右上角，，点击那个build图标就ok，等个几分钟，就会在目录里生成test.dll文件了。图5
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23968_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4e21f5823ece422097e73e2321e43b3b09a2cb7a.jpg&#34; title=&#34;build&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;vs端的代码&#34;&gt;VS端的代码&lt;/h3&gt;
&lt;p&gt;　　现在，打开vs，创建C#工程，添加两个引用，分别是MWArray.dll和test.dll，添加引用的方法就是在解决方案资源管理器中，的引用上，点击，然后添加引用-&amp;gt;浏览-&amp;gt;找到这两个dll，为了方便，我一般会把这两个dll复制到我的C#工程目录里，然后添加引用，如前面所说，MWArray.dll里有两个命名空间，我们使用using语句都添加上。也包括生成的test.dll&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;using test;
using MathWorks.MATLAB.NET.Arrays;
using MathWorks.MATLAB.NET.Utility;&lt;/pre&gt; 
&lt;p&gt;　　然后设计C#界面，很简单的拖一个界面，图6
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23969_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/07a97d0fe021665574597469b813e53dc6b48677.jpg&#34; title=&#34;ui&#34;&gt;&lt;/a&gt;
　　然后单击事件代码：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;            Func1 f = new Func1(); 
            MWNumericArray na = null;
            MWArray[] ansArray = null; 
            int i = Convert.ToInt16(textBox1.Text); 
            ansArray = f.test(1, i); 
            na = (MWNumericArray)ansArray[0];//只有一个数组返回
            MessageBox.Show(na.ToString());&lt;/pre&gt; 
&lt;p&gt;　　看到test有两个参数，第一个参数是指返回结果书，我们只需要一个就好了。所以为1，后面那个是阶数了。运行结果如图7：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23970_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/891d04e30b4742ae3ca5b851d5fc379cc3d10950.jpg&#34; title=&#34;result&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#中的const和readonly</title>
      <link>http://blog.leaver.me/2012/06/28/c%23%E4%B8%AD%E7%9A%84const%E5%92%8Creadonly/</link>
      <pubDate>Thu, 28 Jun 2012 17:29:13 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/28/c%23%E4%B8%AD%E7%9A%84const%E5%92%8Creadonly/</guid>
      <description>&lt;p&gt;　　本文来自《你必须知道的.NET》这本书，是我看书过程中的笔记整理。&lt;/p&gt;
&lt;p&gt;　　不变的量是程序设计中的平衡剂，是系统中恒定不变的量，在.NET中提供哦你了两种方式来实现，const和readonly。其中，const是静态常量，readonly是动态常量。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;const，readonly和static readonly定义的常量，一旦初始值指定，（包括在构造函数内指定初始值），将不可更改，可读不可写。&lt;/li&gt;
&lt;li&gt;const必须在声明的时候指定初始值，而readonly和static readonly在在声明时可以指定，也可以不指定初始值，同时也可以在构造函数中指定初始值，如果同时在声明时和构造函数中指定了初始值，以构造函数内指定的值为准。&lt;/li&gt;
&lt;li&gt;const和static readonly定义的常量是静态的，只能由类型来访问，不能和static同时使用，否则可能出现编译错误，而readonly定义的常量是非静态的，只能由实例对象来访问。可以显式使用static定义静态成员&lt;/li&gt;
&lt;li&gt;static readonly常量，如果在构造函数内指定初始值，那么必须是在静态无参构造函数中。不同的构造函数可以为readonly常量实现不同的初始值。&lt;/li&gt;
&lt;li&gt;const可以用于定义局部常量和字段常量，而readonly和static readonly不能定义局部变量，只能定义字段常量，实际上，readonly应该被称之为只读字段，因此局限于定义字段，而const才是常量，可以定义字段和局部量。&lt;/li&gt;
&lt;li&gt;const常量编译后保存在模块的元数据中，无需在托管堆中分配内存，并且const常量只能是百年机器能够识别的基元类型，比如Int32，string等，而readonly需要分配独立的存储空间，并且可以是任意类型。&lt;/li&gt;
&lt;li&gt;const只能应用在值类型和string类型上，其他引用类型常量只能定义为null，否则以new为const引用类型常量赋值，编译器会引发“只能用null对引用类型（字符串除外）的常量进行初始化”错误提示，原因是构造函数初始化是在运行时，而非编译时，readonly只读字段，可以是任意类型，但是对于引用类型字段来说，readonly不能限制对该对象实例成员的访问控制。
　　总结：尽可能以只读属性来实现对类型读写特性的控制，而不是只读字段，但是在某些情况下，只读字段更简化些。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;　　const是编译时常量，readonly是运行时常量，const较高效，readonly更灵活，在应用上，推荐以static readonly代替const，以平衡const在灵活性上的不足，同时克服编译器优化const性能时，所带来的程序集引用不一致问题。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>c#温故而知新： 线程篇</title>
      <link>http://blog.leaver.me/2012/06/24/c%23%E6%B8%A9%E6%95%85%E8%80%8C%E7%9F%A5%E6%96%B0-%E7%BA%BF%E7%A8%8B%E7%AF%87/</link>
      <pubDate>Sun, 24 Jun 2012 10:57:38 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/24/c%23%E6%B8%A9%E6%95%85%E8%80%8C%E7%9F%A5%E6%96%B0-%E7%BA%BF%E7%A8%8B%E7%AF%87/</guid>
      <description>&lt;p&gt;上次的&lt;a href=&#34;http://leaver.me/archives/431.html&#34;&gt;C#温故而知新：Stream篇&lt;/a&gt; 已经完结了，这次，&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/&#34;&gt;JimmyZheng&lt;/a&gt; 开始更新线程了，转发收藏，持续更新，当然你也可以直接去看JimmyZheng的文章，欢迎学习交流&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html&#34;&gt;c#温故而知新： 线程篇(一)：&lt;strong&gt;Thread&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/07/07/2580253.html&#34;&gt;c#温故而知新： 线程篇(二)：&lt;strong&gt;线程池和异步线程&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>WPF实现不规则窗体</title>
      <link>http://blog.leaver.me/2012/06/23/wpf%E5%AE%9E%E7%8E%B0%E4%B8%8D%E8%A7%84%E5%88%99%E7%AA%97%E4%BD%93/</link>
      <pubDate>Sat, 23 Jun 2012 06:22:49 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/23/wpf%E5%AE%9E%E7%8E%B0%E4%B8%8D%E8%A7%84%E5%88%99%E7%AA%97%E4%BD%93/</guid>
      <description>&lt;p&gt;这几天在想C# winform程序界面实在太单一，而我&lt;a href=&#34;http://leaver.me/archives/990.html&#34;&gt;C#实现不规则窗体&lt;/a&gt;中也说了，如果用背景这种东西来做的话，效果很差，抗锯齿能力基本为0，所以我当时在博客园提问，然后园友有了很给力的回答，比如WPF来做，或者第三方插件，或者深入底层改写ONPaint函数的，今天没事，恰好看到了一篇文章讲这个的，于是，就做一个简单的Demo出来，华丽的效果有木有，先看效果图&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23622_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ba031241897a97ce5f76970d0787694511d3960a.jpg&#34; title=&#34;效果&#34;&gt;&lt;/a&gt;
在win 7下使用win+Tab切换效果也很华丽。就不演示了。&lt;/p&gt;
&lt;p&gt;做起来还算比较简单，首先使用Microsoft Expression Design 4 设计一个界面，破解版什么的太多了，，软件界面和ps挺像，不过功能弱很多，自己操作操作就好了，我说一个问题，就是我当时想画一个空心的圆，也就是一个圆环，ps里大家都知道，直接选区相减就可以了，但是这个死活没找到，基本上最后这个界面所有的地方被找了一遍，猜了猜，才发现了，&lt;/p&gt;
&lt;p&gt;具体操作如下，首先汇出一个圆形，然后在圆里面再绘出一个圆形，这时候选中第二次的这个小圆，点击屏幕右侧的那个箭头会出现高级选项，&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23623_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7bb961d46945780dd51bf752d4109eb6dfec9583.jpg&#34; title=&#34;高级&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;然后选择混合模式为橡皮擦，就会擦去这个小圆，于是就只剩下一个圆环了。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23624_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/47a442eae19c0450c9de4ef532d026c4608439f1.jpg&#34; title=&#34;橡皮擦&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;画好以后，选择文件-&amp;gt;导出，按如下设置，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23625_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5a4dc13cbe7e3ade5841d175eace74870fd42395.jpg&#34; title=&#34;导出&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;会得到一个xaml文件，一会用&lt;/p&gt;
&lt;p&gt;然后新建wpf项目，然后在解决方案资源管理器视图右键点击项目 导入现有项，把上一步的xaml文件导入&lt;/p&gt;
&lt;p&gt;然后需要在app.xaml文件中进行设置，具体在&amp;lt;Application.Resources&amp;gt;标签内添加如下代码，中间那个文件名看情况而定。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;        &amp;lt;ResourceDictionary&amp;gt;
            &amp;lt;ResourceDictionary.MergedDictionaries&amp;gt;
                &amp;lt;ResourceDictionary Source=&#34;bystander.xaml&#34;/&amp;gt;
            &amp;lt;/ResourceDictionary.MergedDictionaries&amp;gt;
        &amp;lt;/ResourceDictionary&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;然后打开“MainWindow.xaml”文件的设计视图，点击窗体边缘以选中窗体，在属性面板中更改AllowsTransparency及WindowStyle属性。
AllowsTransparency 指示窗体是否支持透明。选中
WindowStyle指示窗体边框样式，设为 None 为无边框。&lt;/p&gt;
&lt;p&gt;然后呢在 MainWindow.xaml文件中添加如下代码，&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Background=&#34;{StaticResource back}&#34;
MouseDown=&#34;Window_MouseDown&#34;&amp;gt;&lt;/pre&gt;
&lt;p&gt;最终代码是：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Window x:Class=&#34;WpfDemo.MainWindow&#34;
        xmlns=&#34;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#34;
        xmlns:x=&#34;http://schemas.microsoft.com/winfx/2006/xaml&#34;
        Title=&#34;MainWindow&#34; Height=&#34;350&#34; Width=&#34;525&#34; AllowsTransparency=&#34;True&#34; WindowStyle=&#34;None&#34; Background=&#34;{StaticResource back}&#34; MouseDown=&#34;Window_MouseDown&#34;&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/pre&gt;
&lt;p&gt;其中background那个是固定的，而MouseDown是为了给窗体写可以拖动的函数，函数名为Window_MouseDown你也可以自己制定&lt;/p&gt;
&lt;p&gt;然后对着那个函数名点右键，如下图&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23626_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2bda8545e86b4ffc4155d5c63505252bb57506bf.jpg&#34; title=&#34;导航&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;导航到事件处理程序，然后在打开的函数里写上&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;if(e.ChangedButton==MouseButton.Left)
    this.DragMove();&lt;/pre&gt;
&lt;p&gt;拖动功能就实现了。&lt;/p&gt;
&lt;p&gt;至于添加关闭按钮的，我就不写了，很简单，代码里都有。可以参考源文件。&lt;/p&gt;
&lt;p&gt;工程源码下载：&lt;a href=&#34;http://115.com/file/c2aq7abt#WpfDemo.7z&#34;&gt;WPFDemo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;参考：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.cnblogs.com/SkyD/archive/2008/07/13/1242044.html&#34;&gt;http://www.cnblogs.com/SkyD/archive/2008/07/13/1242044.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.cnblogs.com/yinyao/archive/2011/05/23/2054056.html&#34;&gt;http://www.cnblogs.com/yinyao/archive/2011/05/23/2054056.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>GET和POST有什么区别？及为什么网上的多数答案都是错的。</title>
      <link>http://blog.leaver.me/2012/06/19/get%E5%92%8Cpost%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E5%8F%8A%E4%B8%BA%E4%BB%80%E4%B9%88%E7%BD%91%E4%B8%8A%E7%9A%84%E5%A4%9A%E6%95%B0%E7%AD%94%E6%A1%88%E9%83%BD%E6%98%AF%E9%94%99%E7%9A%84/</link>
      <pubDate>Tue, 19 Jun 2012 18:04:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/19/get%E5%92%8Cpost%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E5%8F%8A%E4%B8%BA%E4%BB%80%E4%B9%88%E7%BD%91%E4%B8%8A%E7%9A%84%E5%A4%9A%E6%95%B0%E7%AD%94%E6%A1%88%E9%83%BD%E6%98%AF%E9%94%99%E7%9A%84/</guid>
      <description>&lt;p&gt;今天突然看到很多好的技术文章，转载收藏备用分享。&lt;/p&gt;
&lt;p&gt;如果有人问你，&lt;strong&gt;GET&lt;strong&gt;&lt;strong&gt;和POST&lt;/strong&gt;&lt;/strong&gt;，有什么区别？你会如何回答？&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;我的经历&#34;&gt;我的经历&lt;/h2&gt;
&lt;p&gt;前几天有人问我这个问题。我说GET是用于获取数据的，POST，一般用于将数据发给服务器之用。&lt;/p&gt;
&lt;p&gt;这个答案好像并不是他想要的。于是他继续追问有没有别的区别？我说这就是个名字而已，如果服务器支持，他完全可以把GET改个名字叫GET2。他反问道，那就是单纯的名字上的区别喽？我想了想，我觉得如果说再具体的区别，只能去看RFC文档了，还&lt;strong&gt;要取决于服务器（指&lt;strong&gt;&lt;strong&gt;Apache&lt;/strong&gt;&lt;/strong&gt;，IIS****）的具体实现&lt;/strong&gt;。但我不得不承认，我的确没有仔细看过HTTP的RFC文档。于是我说，我对HTTP协议不太熟悉。这个问题也就结束了。&lt;/p&gt;
&lt;h2 id=&#34;最普遍的答案&#34;&gt;最普遍的答案&lt;/h2&gt;
&lt;p&gt;回来之后寻思了很久，他到底是想问我什么？我一直就觉得GET和POST没有什么除了语义之外的区别，自打我开始学习Web编程开始就是这么理解的。&lt;/p&gt;
&lt;p&gt;可能很多人都已经猜到了，他要的答案是：&lt;/p&gt;
&lt;p&gt;1. GET使用URL或Cookie传参。而POST将数据放在BODY中。&lt;/p&gt;
&lt;p&gt;2. GET的URL会有长度上的限制，则POST的数据则可以非常大。&lt;/p&gt;
&lt;p&gt;3. POST比GET安全，因为数据在地址栏上不可见。&lt;/p&gt;
&lt;p&gt;但是很不幸，**这些区别全是错误的，**更不幸的是，&lt;a href=&#34;https://www.google.com/search?q=get%E5%92%8Cpost%E7%9A%84%E5%8C%BA%E5%88%AB&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:zh-CN:official&amp;amp;client=firefox-a&amp;amp;channel=fflb&#34;&gt;这个答案还是Google搜索的头版头条&lt;/a&gt;，然而我根本没想着这些是答案，因为在我看来他们都是错的。我来一一解释一下。&lt;/p&gt;
&lt;h3 id=&#34;get和post与数据如何传递没有关系&#34;&gt;GET和POST与数据如何传递没有关系&lt;/h3&gt;
&lt;p&gt;GET和POST是由&lt;a href=&#34;http://www.w3.org/Protocols/rfc2616/rfc2616.html&#34;&gt;HTTP协议定义&lt;/a&gt;的。在HTTP协议中，Method和Data（URL， Body， Header）是正交的两个概念，也就是说，&lt;strong&gt;使用哪个Method与应用层的数据如何传输是没有相互关系的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;HTTP没有要求，如果Method是POST数据就要放在BODY中。也没有要求，如果Method是GET，数据（参数）就一定要放在URL中而不能放在BODY中。&lt;/p&gt;
&lt;p&gt;那么，网上流传甚广的这个说法是从何而来的呢？我&lt;a href=&#34;http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.1&#34;&gt;在HTML标准中，找到了相似的描述&lt;/a&gt;。这和网上流传的说法一致。但是这只是HTML标准对HTTP协议的用法的约定。怎么能当成GET和POST的区别呢？&lt;/p&gt;
&lt;p&gt;而且，现代的Web Server都是支持GET中包含BODY这样的请求。虽然这种请求不可能从浏览器发出，但是现在的Web Server又不是只给浏览器用，已经完全地超出了HTML服务器的范畴了。&lt;/p&gt;
&lt;p&gt;知道这个有什么用？我不想解释了，有时候就得自己痛一次才记得住。&lt;/p&gt;
&lt;h3 id=&#34;http协议对get和post都没有对长度的限制&#34;&gt;HTTP协议对GET和POST都没有对长度的限制&lt;/h3&gt;
&lt;p&gt;HTTP协议明确地指出了，HTTP头和Body都没有长度的要求。而对于URL长度上的限制，有两方面的原因造成：&lt;/p&gt;
&lt;p&gt;1. 浏览器。据说早期的浏览器会对URL长度做限制。据说IE对URL长度会限制在2048个字符内（流传很广，而且无数同事都表示认同）。但我自己试了一下，我构造了90K的URL通过IE9访问live.com，是正常的。网上的东西，哪怕是Wikipedia上的，也不能信。&lt;/p&gt;
&lt;p&gt;2. 服务器。URL长了，对服务器处理也是一种负担。原本一个会话就没有多少数据，现在如果有人恶意地构造几个几M大小的URL，并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是，把告诉服务器Content-Length是一个很大的数，然后只给服务器发一点儿数据，嘿嘿，服务器你就傻等着去吧。哪怕你有超时设置，这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此，多数服务器出于安全啦、稳定啦方面的考虑，会给URL长度加限制。但是这个限制是针对所有HTTP请求的，与GET、POST没有关系。&lt;/p&gt;
&lt;h3 id=&#34;安全不安全和getpost没有关系&#34;&gt;安全不安全和GET、POST没有关系&lt;/h3&gt;
&lt;p&gt;我觉得这真是中国特色。我讲个小段子，大家应该可以体会出这个说法多么的可笑。&lt;/p&gt;
&lt;p&gt;觉得POST数据比GET数据安全的人会说&lt;/p&gt;
&lt;p&gt;_    “防君子不防小人；中国小白多，能防小白用户就行了。”_&lt;/p&gt;
&lt;p&gt;_    “哼，”&lt;em&gt;我不以为然，&lt;/em&gt;“那你怎么不说，_&lt;em&gt;URL__参数都Encode__过了，或是Base64__一下，小白也看不懂啊。”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;那人反驳道，_“_&lt;em&gt;Encode__太简单了，聪明点儿的小白很容易就可以Decode__并修改掉。”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;我笑道，_“五十步笑百步耳，再聪明点儿的小白还会截包并重发呢，_&lt;em&gt;Opera__就有这功能。”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;那人阴险地祭出&lt;strong&gt;神器——最终解释权&lt;/strong&gt;，说，&lt;strong&gt;&lt;em&gt;“这个不算小白。”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我日啊。&lt;/p&gt;
&lt;h2 id=&#34;最后一点儿感想&#34;&gt;最后一点儿感想&lt;/h2&gt;
&lt;p&gt;我之前一直做Windows桌面应用，对Web开发无甚了解，直到一年多前转做服务器端开发，才开始接触到HTTP。（注意，我说的是HTTP，不是HTML。服务器开放接口是基于REST理念设计的，使用的协议是HTTP，但是传输的内容不是HTML。这不是Web Server，而是一个Web Service）&lt;/p&gt;
&lt;p&gt;所以我对于GET和POST的理解，是纯粹地来源于HTTP协议。他们只有&lt;strong&gt;一点&lt;/strong&gt;根本区别，简单点儿说，一个用于获取数据，一个用于修改数据。具体的请参考RFC文档。&lt;/p&gt;
&lt;p&gt;如果一个人一开始就做Web开发，很可能把HTML对HTTP协议的使用方式，当成HTTP协议的唯一的合理使用方式。从而犯了以偏概全的错误。&lt;/p&gt;
&lt;p&gt;可能有人会觉得我钻牛角尖。我只是不喜欢模棱两可，不喜欢边界不清、概念不明，不喜欢“拿来主义”，也不喜欢被其它喜欢钻牛角尖的人奚落得无地自容。&lt;/p&gt;
&lt;p&gt;“知之为知之，不知为不知，是知也。”&lt;/p&gt;
&lt;p&gt;原文链接：&lt;a href=&#34;http://www.cnblogs.com/nankezhishi/archive/2012/06/09/2542968.html&#34;&gt;http://www.cnblogs.com/nankezhishi/archive/2012/06/09/2542968.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>gif反转工具</title>
      <link>http://blog.leaver.me/2012/06/15/gif%E5%8F%8D%E8%BD%AC%E5%B7%A5%E5%85%B7/</link>
      <pubDate>Fri, 15 Jun 2012 17:33:29 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/15/gif%E5%8F%8D%E8%BD%AC%E5%B7%A5%E5%85%B7/</guid>
      <description>&lt;p&gt;首先看下效果图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23424_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b38ddf634b3f63f7f6e7f6016218ba55907c67b5.jpg&#34; title=&#34;gif反转工具&#34;&gt;&lt;/a&gt;
然后是两张gif的对比
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23425_o.gif&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3b7f81c3127dc8ebb3eb51d13a29d45751861ea7.gif&#34; title=&#34;旧图&#34;&gt;&lt;/a&gt;   //原本图是正着走的
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23426_o.gif&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/576d8c2f7990984cd6927c59d24684f2ae94fcb4.gif&#34; title=&#34;新图&#34;&gt;&lt;/a&gt;   //处理后是倒着走的&lt;/p&gt;
&lt;p&gt;gif是动态的嘛。然后我昨天和一个朋友聊天的时候发了一串相同的gif图，然后看着千篇一律的东西。我想能不能写个程序实现gif的初始状态不同呢。什么意思呢。我们知道，gif是由帧构成的，我想实现的功能是比如一个gif共有十帧，那么我写出来的程序能够生成10个gif文件，分别对应不同的初始状态来进行循环。后来一想，gif帧太多的话，比较慢，而且也不实用，于是决定简化一下，只做一个反转工具，比如一个gif是从左到右播放的，通过这个成功可以生成一个相同的gif图，不过是倒着播放的。&lt;/p&gt;
&lt;p&gt;思路很简单，就是先把gif分解成很多帧，然后对帧进行合并，合并帧之前把帧的位置反转一下就可以了。因为我自己对图像处理的知识不懂，只想到了思路，所以这些功能都要找些资料，然后修改，测试。&lt;/p&gt;
&lt;p&gt;分割帧的代码如下&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34; title=&#34;分割gif&#34;&gt;        //解码gif图片
        public List&amp;lt;string&amp;gt; GetFrames(string pPath, string pSavedPath)
        {
            Image gif = Image.FromFile(pPath);
            FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]);

            //获取帧数(gif图片可能包含多帧，其它格式图片一般仅一帧)
            int count = gif.GetFrameCount(fd);
            List&amp;lt;string&amp;gt; gifList=new List&amp;lt;string&amp;gt;();
            //以Jpeg格式保存各帧

            for (int i = 0; i &amp;lt; count; i++)
              {
                  gif.SelectActiveFrame(fd, i);
                  gif.Save(pSavedPath + &#34;\\frame_&#34; + i + &#34;.png&#34;, ImageFormat.Png);
                  gifList.Add(pSavedPath + &#34;\\frame_&#34; + i + &#34;.png&#34;);
              }
            return gifList;
         }&lt;/pre&gt;
&lt;p&gt;可以看到，返回了一个包含所有生成的帧地址的list列表。然后就是使用gifList作为参数来合并了。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34; title=&#34;合并gif&#34;&gt;//获取系统临时目录存放解码后的png图片
                string temppath = System.Environment.GetEnvironmentVariable(&#34;TEMP&#34;); 

                List&amp;lt;string&amp;gt; gifList = GetFrames(tBoxFile.Text, temppath);
                gifList.Reverse();
                String outputFilePath = &#34;new.gif&#34;;
                AnimatedGifEncoder ae = new AnimatedGifEncoder();
                ae.Start(outputFilePath);
                ae.SetDelay(100);    // 延迟间隔
                ae.SetRepeat(0);  //-1:不循环,0:总是循环 播放  
                for (int i = 0, count = gifList.Count; i &amp;lt; count; i++)
                {
                    ae.AddFrame(Image.FromFile(gifList[i]));
                }
                ae.Finish();
                MessageBox.Show(&#34;成功!新文件已保存在同目录&#34;);&lt;/pre&gt;
&lt;p&gt;这里面使用了AnimatedGifEncoder这个类，这是Gif.Components.dll动态连接库里的类（此库开源，文末给出地址），是我在codeProject上找到的。首先我把gifList反转，然后合并保存到同目录。中间生成的帧为了方便我保存到了temp目录。&lt;/p&gt;
&lt;p&gt;本来这个库里是分割gif的功能的。但是我实际测试后发现效果非常差，图片黑条泛滥，根本没法看。所以还是使用上面那段代码，相关代码我依然保存在工程里，有兴趣可以自己测试。&lt;/p&gt;
&lt;p&gt;明天四级考试，求人品。。&lt;/p&gt;
&lt;p&gt;项目源码:&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=125360&amp;amp;uk=1493685990&#34;&gt;gif反转工具&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;参考：
&lt;a href=&#34;http://www.cnblogs.com/top5/archive/2011/03/19/1988595.html&#34;&gt;C#图片处理：获取GIF 动画图片中的各个帧&lt;/a&gt;
&lt;a href=&#34;http://www.codeproject.com/Articles/11505/NGif-Animated-GIF-Encoder-for-NET&#34;&gt;NGif, Animated GIF Encoder for .NET&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Think-Aloud 可用性测试介绍</title>
      <link>http://blog.leaver.me/2012/05/29/think-aloud-%E5%8F%AF%E7%94%A8%E6%80%A7%E6%B5%8B%E8%AF%95%E4%BB%8B%E7%BB%8D/</link>
      <pubDate>Tue, 29 May 2012 09:10:22 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/29/think-aloud-%E5%8F%AF%E7%94%A8%E6%80%A7%E6%B5%8B%E8%AF%95%E4%BB%8B%E7%BB%8D/</guid>
      <description>&lt;p&gt;中文是指出声思考：出声思考。可用性测试中常用也很有用的一个数据收集方法，来改善产品。要求被测试者把在测试过程中即时的把自己的想法大声说出来。比如，你说我不知道干什么，这个好像有点问题，等等。然后有人来记录。&lt;/p&gt;
&lt;p&gt;SSD4给出的具体步骤翻译添加解释如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define the study&amp;rsquo;s framework,
定义该测试报告的框架。比如系统准备解决什么问题，适合什么类型的用户，希望评估首次使用还是其他什么，希望最终的目标是什么，比如希望90%的用户可以初次顺利使用。&lt;/li&gt;
&lt;li&gt;Choose what to observe,
选择打算观察测试者的什么行为，比如用户如何打开，先干了什么&lt;/li&gt;
&lt;li&gt;Prepare for the think-aloud usability test,
为测试做准备，比如模拟真实情景，写个流程。开个会，招募实验人员。&lt;/li&gt;
&lt;li&gt;Introduce the participants to the observation procedure,
给实验人员介绍步骤。抚慰一下他们的情绪。告诉他们目的，并且希望他们think aloud。&lt;/li&gt;
&lt;li&gt;Conduct the observation,
进行观察&lt;/li&gt;
&lt;li&gt;Analyze the observation,
分析观察结果 。&lt;/li&gt;
&lt;li&gt;Find possible redesigns,
找到可能需要进行重新设计的地方&lt;/li&gt;
&lt;li&gt;Write a report.
写个总结报告出来。完成
这不也就这样嘛。&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>UAR报告的简单说明</title>
      <link>http://blog.leaver.me/2012/05/29/uar%E6%8A%A5%E5%91%8A%E7%9A%84%E7%AE%80%E5%8D%95%E8%AF%B4%E6%98%8E/</link>
      <pubDate>Tue, 29 May 2012 08:15:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/29/uar%E6%8A%A5%E5%91%8A%E7%9A%84%E7%AE%80%E5%8D%95%E8%AF%B4%E6%98%8E/</guid>
      <description>&lt;h3 id=&#34;uar报告由以下几个部分构成就这个例子简单说一下&#34;&gt;UAR报告由以下几个部分构成。就这个例子简单说一下。&lt;/h3&gt;
&lt;h3 id=&#34;example-uar--time-zone-listbox-is-not-good-标题&#34;&gt;&lt;strong&gt;Example UAR — Time Zone ListBox Is Not Good  //标题&lt;/strong&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;h4 id=&#34;uar-identifier--问题编号从1开始每个问题都这样的格式来说明就构成了uar报告&#34;&gt;&lt;strong&gt;UAR Identifier   //问题编号，从1开始，每个问题都这样的格式来说明，就构成了UAR报告&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;HE18—Problem  //后面这个problem表示有问题，也可以是Good，表示这部分很好。没问题。&lt;/p&gt;
&lt;h4 id=&#34;succinct-description-简短的描述&#34;&gt;&lt;strong&gt;Succinct description: //简短的描述&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Time Zone pull-down ListBox provides too much irrelevant information.&lt;/p&gt;
&lt;h4 id=&#34;evidence-for-the-aspect-违反了哪条规则共有十条规则&#34;&gt;&lt;strong&gt;Evidence for the aspect:  //违反了哪条规则，共有十条规则。&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Heuristic: Aesthetics and minimalist design&lt;/p&gt;
&lt;p&gt;**Interface aspect: **&lt;/p&gt;
&lt;p&gt;The pull-down ListBox has 50 lines of information—in very small font. There are many competing items of information to visually search, the vast majority of which are irrelevant to any one user&amp;rsquo;s particular task of finding a single desired time zone&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;center style=&#34;text-align: -webkit-auto;&#34;&gt;&lt;span style=&#34;font-size: small;&#34;&gt;&lt;span style=&#34;line-height: normal;&#34;&gt;[![](/images/ &#34;uar&#34;)](http://seqcc.icarnegie.com/content/SSD/SSD4/3.1/normal/pg-creatng-evaltng-interfaces/pg-crt-eval-list-combo/pg-he-clean-beauty/Ex5.png)&lt;/span&gt;&lt;/span&gt;&lt;/center&gt;In addition, the information is structured as follows:The string &#34;[GMT &#34; begins each line (which means Greenwich Mean Time). If the time zone is behind GMT, then a &#34;-&#34; indicates this fact, which is followed by the number of hours and minutes the time zone is behind GMT. If the time zone is ahead of GMT, a &#34;+&#34; is used instead. Finally, some words follow the GMT offset, which are either city or country names, or the names of regions.&amp;nbsp;
&lt;p&gt;The presentation of this structured information violates the &lt;strong&gt;aesthetics and minimalist design&lt;/strong&gt; heuristic because the structure is not preserved visually from item to item. For example, the words are not always lined up vertically; see the entries for:&lt;/p&gt;</description>
    </item>
    <item>
      <title>10条可用性准则（Heuristics）</title>
      <link>http://blog.leaver.me/2012/05/29/10%E6%9D%A1%E5%8F%AF%E7%94%A8%E6%80%A7%E5%87%86%E5%88%99heuristics/</link>
      <pubDate>Tue, 29 May 2012 06:52:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/29/10%E6%9D%A1%E5%8F%AF%E7%94%A8%E6%80%A7%E5%87%86%E5%88%99heuristics/</guid>
      <description>&lt;p&gt;SSD4第二单元其实就讲了这么一点东西，包括一点VB的控件常识&lt;/p&gt;
&lt;p&gt;可用性测试（Usability testing），是一项通过用户的使用来评估产品的技术，由于它反应了用户的真实使用经验，所以可以视为一种不可或缺的可用性检验过程[1]。也就是说，可用性测试是指让用户使用产品（服务）的设计原型或者成品，通过观察，记录和分析用户的行为和感受，以改善产品（服务）可用性的一系列方法。它适用于产品（服务）前期设计开发，中期改进和后期维护完善的各个阶段，是用户中心设计的思想的重要体现。&lt;/p&gt;
&lt;p&gt;10条可用性准则（Heuristics）
These are ten general principles for user interface design. They are called &amp;ldquo;heuristics&amp;rdquo; because they are more in the nature of rules of thumb than specific usability guidelines.&lt;/p&gt;
&lt;p&gt;1.Visibility of system status——系统状态的可见性&lt;/p&gt;
&lt;p&gt;The system should always keep users informed about what is going on, through appropriate feedback within reasonable time.&lt;/p&gt;
&lt;p&gt;系统应该始终在合理的时间以适当的反馈信息让用户知道系统正在做什么。&lt;/p&gt;
&lt;p&gt;2.Match between system and the real world——系统和现实世界之间的吻合&lt;/p&gt;
&lt;p&gt;The system should speak the users&amp;rsquo; language, with words, phrases and concepts familiar to the user, rather than system-oriented terms. Follow real-world conventions, making information appear in a natural and logical order.&lt;/p&gt;
&lt;p&gt;系统应该用用户熟悉的词，短语和概念来说用户的语言，而不是用面向系统的术语。遵循现实世界中的惯例，让信息以自然的合乎逻辑的次序展现在用户面前。&lt;/p&gt;
&lt;p&gt;3.User control and freedom——用户控制和自由&lt;/p&gt;
&lt;p&gt;Users often choose system functions by mistake and will need a clearly marked &amp;ldquo;emergency exit&amp;rdquo; to leave the unwanted state without having to go through an extended dialogue. Support undo and redo.&lt;/p&gt;
&lt;p&gt;用户经常错误地选择系统功能，所以在不需要查看由于误操作而延伸出来地对话的情况下有一个明显地标志为“紧急退出”的操作来离开不想要的状态。另外，系统需要支持“撤销操作”和“重做”的功能。&lt;/p&gt;
&lt;p&gt;4.Consistency and standards——一致性和标准&lt;/p&gt;
&lt;p&gt;Users should not have to wonder whether different words, situations, or actions mean the same thing. Follow platform conventions.&lt;/p&gt;</description>
    </item>
    <item>
      <title>VS2010 编译安装boost库</title>
      <link>http://blog.leaver.me/2012/05/24/vs2010-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85boost%E5%BA%93/</link>
      <pubDate>Thu, 24 May 2012 11:39:55 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/24/vs2010-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85boost%E5%BA%93/</guid>
      <description>&lt;p&gt;实践是最好的办法。。学习C++，想试试线程，然后打算用boost库，结果boost库编译差点吓到我。。没看到比较完整的安装教程。。一直耽搁。今天动手。完成了。方法记录如下：
1.下载boost
从boost官网( &lt;a href=&#34;http://www.boost.org&#34;&gt;http://www.boost.org&lt;/a&gt; )上下载最新的boost版本，现在最新是1.49版本，解压到自定义目录(我解压到了D:/program files,最终的目录结构是D:\Program Files\boost_1_49_0)&lt;/p&gt;
&lt;p&gt;2.编译安装&lt;/p&gt;
&lt;p&gt;在D:\Program Files\boost_1_49_0的目录下，有一个bootstrap.bat文件，直接双击运行。就会在同目录生成b2.exe；bjam.exe两个文件。&lt;/p&gt;
&lt;p&gt;3.设定编译环境
修改user-config.jam (D:\Program Files\boost_1_49_0\tools\build\v2\user-config.jam) 的MSVC configuration&lt;/p&gt;
&lt;h1 id=&#34;msvc-configuration&#34;&gt;MSVC configuration&lt;/h1&gt;
&lt;h1 id=&#34;configure-msvc-default-version-searched-for-in-standard-locations-and-path&#34;&gt;Configure msvc (default version, searched for in standard locations and PATH).&lt;/h1&gt;
&lt;h1 id=&#34;using-msvc-&#34;&gt;using msvc ;&lt;/h1&gt;
&lt;p&gt;在上面这段的下面直接添加如下的文字。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using msvc : 10.0 : :/wd4819/D_CRT_SECURE_NO_DEPRECATE/D_SCL_SECURE_NO_DEPRECATE/D_SECURE_SCL=0 ;&lt;/pre&gt;
&lt;p&gt;保存关闭。&lt;/p&gt;
&lt;p&gt;4.开始编译
点击开始-&amp;gt;所有程序-&amp;gt;“Microsoft Visual Studio 2010”，指向“Visual Studio tools(工具)”，然后单击“Visual Studio 2010 command prompt（命令提示）” 使用cd切换到D:\Program Files\boost_1_49_0目录。这个就不说了
然后输入如下的代码：&lt;/p&gt;
&lt;pre class=&#34;lang:sh decode:true  crayon-selected&#34;&gt;b2 toolset=msvc-10.0 architecture=x86 instruction-set=i686 address-model=32 link=static 
variant=debug,release threading=multi runtime-link=shared --without-python --without-mpi 
--without-wave --without-graph --without-math --without-serialization stage&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;解释一下命令的意思：
1.toolset：表示编译器工具，我安装的是VS2010，所以是msvc-10(如果你是VS2005，可以使用msvc-8.0 VS2008是msvc-9.0)
2.architecture：表示架构，也就是你的CPU架构，x86,x64，因为我安装的是win7 32位，所以使用了x86的架构
3.instruction-set：表示指令集，依然是8086指令集
4.address-model：表示地址长度为32位
5.link：表示生成动态/静态链接库，动态链接库是shared，静态链接库是static，一般都会编译成静态库，因为给出程序的时候打包boost的库会非常庞大
6.variant：表示生成的Debug或者release版本，一般情况下会两种版本都会编译出来的
7.threading：表示单/多线程编译，一般我们的程序都会用到多线程，所以选择了multi
8.runtime-link：表示动态/静态链接C/C++运行时库(C/C++ Runtime)，我们选择了动态链接
9.without/with：表示不需要编译/需要编译哪些库，一些自己不用的库可以无需编译
10.stage/install：stage表示只生成库文件(DLL和Lib)，install还会生成包含头文件的include目录，推荐使用stage，因为boost_1_49\boost中就是boost库完整的头文件，所以无需再拷贝一份出来。编译出来的库会放在stage文件夹中
这样一份完整的boost库就生成了，剩下就是直接使用到项目中了。&lt;/p&gt;
&lt;p&gt;其实编译的具体命令都是可以自己写的。如果你需要编译所有。只需要使用下面的这行代码
b2 &amp;ndash;toolset=msvc-10.0 &amp;ndash;build-type=complete
就可以了。&lt;/p&gt;
&lt;p&gt;不出问题的话。就开始编译了。。登个半个多小时吧。就会完成了。
5.设置vs
打开vs，新建一个工程。然后工程属性。配置属性-&amp;gt;C/C++ ，附加包含目录
填上
D:\Program Files\boost_1_49_0;%(AdditionalIncludeDirectories)
这个是最终的结果，你也可以手动添加&lt;/p&gt;
&lt;p&gt;在左侧选择链接器-&amp;gt;附加库目录，填上
D:\Program Files\boost_1_49_0\stage\lib;%(AdditionalLibraryDirectories)
就可以了。&lt;/p&gt;
&lt;p&gt;6.测试
在你新建的工程里输入如下的代码。运行成功就说明可以了&lt;/p&gt;
&lt;pre class=&#34;lang:c++ decode:true &#34;&gt;#include &amp;lt;boost/thread/thread.hpp&amp;gt;
#include &amp;lt;iostream&amp;gt;

void hello()
{
        std::cout &amp;lt;&amp;lt;
        &#34;Hello world, I&#39;m a thread!&#34;
        &amp;lt;&amp;lt; std::endl;
}

int main(int argc, char* argv[])
{
        boost::thread thrd(&amp;amp;hello);
        thrd.join();
        return 0;
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;参考：
&lt;a href=&#34;http://www.cppfans.org/1317.html&#34;&gt;http://www.cppfans.org/1317.html&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/ComputerG/archive/2011/03/10/1979730.html&#34;&gt;http://www.cnblogs.com/ComputerG/archive/2011/03/10/1979730.html&lt;/a&gt;
&lt;a href=&#34;http://www.cppblog.com/shaker/archive/2011/11/30/33583.html&#34;&gt;http://www.cppblog.com/shaker/archive/2011/11/30/33583.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C&#43;&#43; 独立引用，为什么？</title>
      <link>http://blog.leaver.me/2012/05/23/c-%E7%8B%AC%E7%AB%8B%E5%BC%95%E7%94%A8%E4%B8%BA%E4%BB%80%E4%B9%88/</link>
      <pubDate>Wed, 23 May 2012 07:25:04 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/23/c-%E7%8B%AC%E7%AB%8B%E5%BC%95%E7%94%A8%E4%B8%BA%E4%BB%80%E4%B9%88/</guid>
      <description>&lt;p&gt;问题：&lt;/p&gt;
&lt;p&gt;I read in some good C++ tutorial that independent references do exist, and act like aliasing.
我读了一些好的C++文章，发现独立引用确实存在，并且很像别名。
But&amp;hellip; I wonder what it is made for.
但是，，，我想知道他适用于什么情况。
Why should one want to use aliasing.Besides, some piece of code that is not clear to me:
为什么有人想使用别名呢，另外，下面这段代码我不太清楚。&lt;/p&gt;
&lt;pre class=&#34;lang:c++ decode:true&#34;&gt;int a;
int &amp;amp;ref = a; // independent reference
int b = 19;
ref = b;
cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &#34; &#34; &amp;lt;&amp;lt; ref &amp;lt;&amp;lt; &#34;\n&#34;;
ref--;
cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; &#34; &#34; &amp;lt;&amp;lt; ref &amp;lt;&amp;lt; &#34;\n&#34;;&lt;/pre&gt;
&lt;span style=&#34;font-family: monospace;&#34;&gt;
&lt;/span&gt;
&lt;p&gt;First, ref is a &amp;lsquo;reference&amp;rsquo; to a.I understand from second line of code that address for ref (hence the ampershead) is
首先，ref是一个对a的引用，从第二行代码那我认为ref的地址也就是a，（括号里面不清楚什么意思。貌似是作者写错了）&lt;/p&gt;
&lt;p&gt;a. Then, integer ref is assigned the value of b (19). First cout returns a and ref, both equal to 19.
然后呢，整数ref被b（19）被赋值，第一次输出a和ref，都是19，&lt;/p&gt;
&lt;p&gt;Why? Isn&amp;rsquo;t integer a the address for ref? Then, decrements ref, and last cout gives two times 18. a and ref where decremented.
为什么，难道整数a不是给ref的地址？然后ref自减，最后输出了2个18，a和ref都减少了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>c &amp; c&#43;&#43;中sizeof返回值不同?</title>
      <link>http://blog.leaver.me/2012/05/22/c-c-%E4%B8%ADsizeof%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%8D%E5%90%8C/</link>
      <pubDate>Tue, 22 May 2012 11:28:27 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/22/c-c-%E4%B8%ADsizeof%E8%BF%94%E5%9B%9E%E5%80%BC%E4%B8%8D%E5%90%8C/</guid>
      <description>&lt;p&gt;问题:
A character array is defined globally and a structure with same name is defined within a function.
一个字符数组被定义为全局变量，一个相同名字的结构体被定义在一个函数内部。&lt;/p&gt;
&lt;p&gt;Why sizeof operator returns different values for c &amp;amp; c++ ?
为什么sizeof操作符对于C和C++返回了不同的值呢？&lt;/p&gt;
&lt;pre lang=&#34;c&#34;&gt;char S[13];
void fun()
{
    struct S
    {
        int v;
    };
    int v1 = sizeof(S);
}
// returns 4 in C++ and 13 in C&lt;/pre&gt;
&lt;p&gt;答案：
Because in C++, the struct you defined is named S, while in C,
因为在C++中，你定义的结构体的名称是S，而在C中，&lt;/p&gt;
&lt;p&gt;it&amp;rsquo;s named struct S (which is why you often see typedef struct used in C code).
他叫做struct S（这也是为什么我们可以经常看到typedef struct 被用在C代码中）。&lt;/p&gt;
&lt;p&gt;In C, to refer to the struct type, you need to say struct S. Therefore, sizeof(S) refers to the array.
在C中，引用一个结构类型的时候，你必须说struct S，因此，sizeof（S）调用的是数组S。&lt;/p&gt;
&lt;p&gt;In C++, struct is unnecessary. So the local S hides the global S.
在C++中，struct这个字不是必需的，所以局部变量S隐藏了全局变量S。&lt;/p&gt;
&lt;p&gt;If you were to change the code to the following, you would get the expected results:
如果你把代码改成下面的样子，你就能得到你期望的结果了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>为什么sizeof(str.substr(0,3).c_str())=8?</title>
      <link>http://blog.leaver.me/2012/05/21/%E4%B8%BA%E4%BB%80%E4%B9%88sizeofstr.substr03.c_str8/</link>
      <pubDate>Mon, 21 May 2012 06:59:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/21/%E4%B8%BA%E4%BB%80%E4%B9%88sizeofstr.substr03.c_str8/</guid>
      <description>&lt;p&gt;问题：
&lt;code&gt;string str = &amp;quot;abcdefgdcb&amp;quot;; cout &amp;amp;lt; &amp;amp;lt; sizeof(str.substr(0,3).c_str());&lt;/code&gt;
For some reason, the above string is giving me 8. I assumed c_str() returns a null string,
由于某些原因，上面的这个字符串得到的结果是8，我估计c_str()返回了一个null，&lt;/p&gt;
&lt;p&gt;and sizeof uses the null to determine the size of the string.
并且sizeof函数使用这个null来定义这个字符串的大小。&lt;/p&gt;
&lt;p&gt;答案：
Because sizeof doesn&amp;rsquo;t give you the length of a string,
因为sizeof给你的不是一个字符串的长度，&lt;/p&gt;
&lt;p&gt;it gives you the size of the type (const char * in this case). Try strlen.
他给你的是这个类型的大小（这种情况下的类型是c_str()返回的const char*类型），想要得到正确的结果，试试strlen函数吧。&lt;/p&gt;
&lt;p&gt;On your system, sizeof (const char &lt;em&gt;) == 8, like any other pointer.
在你的系统上，sizeof(const char&lt;/em&gt;)=8,和其他所有的指针类型一样。&lt;/p&gt;
&lt;p&gt;8 is the size of a pointer on your machine (64-bit)
8是在你的64位电脑上一个指针的大小&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s your problem. sizeof tells you the size of a variable,
别乱假设，sizeof告诉你一个变量的大小，&lt;/p&gt;
&lt;p&gt;which has nothing to do with the value inside the variable, ever.
他不会进入变量里面对变量做任何改变的。。永远不会。&lt;/p&gt;
&lt;p&gt;问题:&lt;a href=&#34;http://stackoverflow.com/q/10668764/764869&#34;&gt;http://stackoverflow.com/q/10668764/764869&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>快速排序算法</title>
      <link>http://blog.leaver.me/2012/05/19/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/</link>
      <pubDate>Sat, 19 May 2012 09:04:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/19/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/</guid>
      <description>&lt;pre lang=&#34;c&#34;&gt;
#include &lt;iostream&gt;
using namespace std;

//化分区间,找到最后元素的排序位置。并返回分隔的点（即最后一数据排序的位置）。
//划分的区间是[nBegin, nEnd). pData是保存数据的指针
int Partition(int* pData, int nBeging, int nEnd)
{
                int i = nBeging - 1;    //分隔符号，最后nD保存在这里
                --nEnd;
                int nD = pData[nEnd]; //比较的数据。
                int nTemp; // 交换用的临时数据

                //遍历数据比较，找到nD的位置，这里注意，比较结果是,
                //i的左边是小于等于nD的，i的右边是大于nD的
                for (int j = nBeging; j &lt; nEnd; ++j)
                {
                                if (pData[j] &lt;= nD)        //如果数据比要比较的小，则在该数据的左边，与i+1交换
                                {
                                                ++i;                //小于nD的数据多一个，所以要加1，i的左边数据都比nD小
                                                nTemp = pData[i];    //交换数据
                                                pData[i] = pData[j];
                                                pData[j] = nTemp;
                                }
                }

                //最后不要忘了吧nD和i+1交换，因为这里就是nD的位置咯。
                ++i;
                pData[nEnd] = pData[i];
                pData[i] = nD;

                return i;   //返回nD的位置，就是分割的位置。
}

//排序的递归调用。
int QuickSortRecursion(int* pData, int nBeging, int nEnd)
{
                if (nBeging &gt;= nEnd -1)        //如果区域不存在或只有一个数据则不递归排序
                {
                                return 1;
                }

                //这里因为分割的时候，分割点处的数据就是排序中他的位置。
                //也就是说他的左边的数据都小于等于他，他右边的数据都大于他。
                //所以他不在递归调用的数据中。
                int i = Partition(pData, nBeging, nEnd);        //找到分割点
                QuickSortRecursion(pData, nBeging, i);            //递归左边的排序
                QuickSortRecursion(pData, i + 1, nEnd);            //递归右边的排序
                return 1;
}

//快速排序
int QuickSort(int* pData, int nLen)
{
                //递归调用，快速排序。
                QuickSortRecursion(pData, 0, nLen);
                return 1;
}
int main()
{
                int nData[10] = {5,9,3,2,1,6,20,45,88,75};        //测试数据
                QuickSort(nData, 10);            //调用快速排序
                for (int i = 0; i &lt; 10; ++i)        //输出结果
                {
                                cout&lt;&lt;nData[i]&lt;&lt;&#34; &#34;;
                }
                cout&lt;&lt;endl;

                return 0;
}
&lt;/pre&gt;</description>
    </item>
    <item>
      <title>对象数组的Xml序列化和反序列化</title>
      <link>http://blog.leaver.me/2012/05/18/%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%E7%9A%84xml%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/</link>
      <pubDate>Fri, 18 May 2012 09:38:27 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/18/%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%E7%9A%84xml%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/</guid>
      <description>&lt;p&gt;使用Serialization来进行序列化和反序列化，因此需要引入System.Xml.Serialization；命名空间。&lt;/p&gt;
&lt;p&gt;为什么要做序列化和反序列化？
.Net程序执行时，对象都驻留在内存中；内存中的对象如果需要传递给其他系统使用；或者在关机时需要保存下来以便下次再次启动程序使用就需要序列化和反序列化。&lt;/p&gt;
&lt;p&gt;本文的原始例子在参考文中，但是参考文中没有给出反序列化的例子，且xml文件不清晰。于是修改了代码，同时实现对象数组序列化和反序列化。&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace UseXmlSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            //声明一个猫对象
            var cWhite = new Cat { Color = &#34;White&#34;, Speed = 10, Saying = &#34;I am a good WHITE cat&#34; };
            var cBlack = new Cat { Color = &#34;Black&#34;, Speed = 10, Saying = &#34;I am a good BLACK cat&#34; };

            CatCollection cc = new CatCollection { Cats = new Cat[] { cWhite, cBlack } };

            //序列化这个对象
            XmlSerializer serializer = new XmlSerializer(typeof(CatCollection));

            StringWriter sw = new StringWriter();
            serializer.Serialize(sw, cc);  //序列化到StringWriter对象sw里
            string strXml = sw.ToString();
            Console.WriteLine(&#34;对象数组序列化后：&#34;);
            Console.WriteLine(strXml);
            Console.WriteLine(&#34;xml反序列化后：&#34;);
            StringReader sr = new StringReader(strXml);
            CatCollection c2 = serializer.Deserialize(sr) as CatCollection;
            for (int i = 0; i &lt; 2; i++)  //验证xml文件是否已经被反序列化为对象数组
            {
                Console.WriteLine(&#34;I am Cat &#34; + i);
                Console.WriteLine(c2.Cats[i].Color);
                Console.WriteLine(c2.Cats[i].Saying);
                Console.WriteLine();

            }
        }
    }
    //以下为类定义
    [XmlRoot(&#34;Cats&#34;)]
    public class CatCollection
    {
        [XmlElement(&#34;Cat&#34;)]
        public Cat[] Cats { get; set; }
    }

    public class Cat
    {
        //定义Color属性的序列化为cat节点的属性
        [XmlAttribute(&#34;color&#34;)]
        public string Color { get; set; }

        //要求不序列化Speed属性
        [XmlIgnore]
        public int Speed { get; set; }

        //设置Saying属性序列化为Xml子元素
        [XmlElement(&#34;saying&#34;)]
        public string Saying { get; set; }
    }
}
&lt;/pre&gt;
&lt;p&gt;参考：
　　&lt;a href=&#34;http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html&#34;&gt;http://www.cnblogs.com/yukaizhao/archive/2011/07/22/xml-serialization.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>从hash函数到王小云的MD5破解</title>
      <link>http://blog.leaver.me/2012/05/15/%E4%BB%8Ehash%E5%87%BD%E6%95%B0%E5%88%B0%E7%8E%8B%E5%B0%8F%E4%BA%91%E7%9A%84md5%E7%A0%B4%E8%A7%A3/</link>
      <pubDate>Tue, 15 May 2012 13:26:14 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/15/%E4%BB%8Ehash%E5%87%BD%E6%95%B0%E5%88%B0%E7%8E%8B%E5%B0%8F%E4%BA%91%E7%9A%84md5%E7%A0%B4%E8%A7%A3/</guid>
      <description>&lt;p&gt;　　以前一直纳闷不是说md5是不可逆的吗，那王小云怎么能破解呢。看到此文，豁然开朗，所谓的破解只是可以获得一个碰撞，使得两个文件的md5值一样。并不是说给定一个md5，能够得到原文。&lt;/p&gt;
&lt;p&gt;　　密码学是理论计算机的一个很大的方向。之前准备先写密码学概论再提在hash函数破解上做出重大贡献的王小云教授的工作，不过前两天&lt;a href=&#34;http://www.cast.org.cn/n435777/n435799/n928596/n930124/35475.html&#34;&gt;王小云获得求是杰出科学家奖以及100万奖金&lt;/a&gt;，在媒体上又掀起了一轮宣传狂潮，但是有些报道极端弱智，错误百出，所以我趁机纠正一下，并介绍密码学的一个组成部分——hash函数，以及王小云在这上面的工作。&lt;/p&gt;
&lt;p&gt;　　王小云的主要工作是关于hash函数的破解工作。她在2005一个密码学会议上宣布破解了SHA-1，震惊了全世界。所以要介绍和理解她的工作，先看一下hash函数具体是怎么回事。&lt;/p&gt;
&lt;p&gt;　　简单的说，&lt;strong&gt;hash函数&lt;/strong&gt;就是&lt;span style=&#34;color: #ff0000;&#34;&gt;把任意长的输入字符串变化成固定长的输出字符串&lt;/span&gt;的一种函数。通俗得说，hash函数用来生成信息的摘要。输出字符串的长度称为hash函数的&lt;strong&gt;位数&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;　　目前应用最为广泛的hash函数是**&lt;a href=&#34;http://en.wikipedia.org/wiki/SHA_hash_functions&#34;&gt;SHA-1&lt;/a&gt;&lt;strong&gt;和&lt;/strong&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Md5&#34;&gt;MD5&lt;/a&gt;**，大多是128位和更长。&lt;/p&gt;
&lt;p&gt;　　hash函数在现实生活中应用十分广泛。很多下载网站都提供下载文件的MD5码校验，可以用来判别文件是否完整。另外，比如在WordPress的数据库，所有密码都是保存的MD5码，这样即使数据库的管理员也无法知道用户的原始密码，避免隐私泄露（很多人在不同地方都是用的同一个密码）。&lt;/p&gt;
&lt;p&gt;　　如果两个输入串的hash函数的值一样，则称这两个串是一个&lt;strong&gt;碰撞&lt;/strong&gt;(&lt;strong&gt;Collision&lt;/strong&gt;)。既然是把任意长度的字符串变成固定长度的字符串，所以，必有一个输出串对应无穷多个输入串，碰撞是必然存在的。&lt;/p&gt;
&lt;p&gt;　　一个“优良”的hash函数 _f _应当满足以下三个条件：　&lt;/p&gt;
&lt;p&gt;　　1.任意y，找x，使得f(x)=y，非常困难。&lt;/li&gt;
　　2.给定x1，找x2，使得f(x1)=f(x2)，非常困难。&lt;/li&gt;
　　3.找x1，x2，使得f(x1)=f(x2)，非常困难。&lt;/li&gt;&lt;/p&gt;
&lt;p&gt;　　上面的“非常困难”的意思是除了枚举外不可能有别的更快的方法。比如第3条，根据&lt;a href=&#34;http://en.wikipedia.org/wiki/Birthday_paradox&#34;&gt;生日定理&lt;/a&gt;，要想找到这样的x1，x2，理论上需要大约2^(n/2)的枚举次数。&lt;/p&gt;
&lt;p&gt;　　几乎所有的hash函数的破解，都是指的破坏上面的第三条性质，即找到一个碰撞（前两条都能被破坏的hash函数也太弱了点，早就被人抛弃了）。在密码学上还有一个概念是&lt;strong&gt;理论破解&lt;/strong&gt;，指的是提出一个算法，使得可以用低于理论值得枚举次数找到碰撞。&lt;/p&gt;
&lt;p&gt;　　王小云的主要工作是给出了MD5，&lt;a href=&#34;http://en.wikipedia.org/wiki/SHA_hash_functions&#34;&gt;SHA-0&lt;/a&gt;的碰撞，以及SHA-1的理论破解，她证明了160位SHA-1，只需要大约2^69次计算就能找出来，而理论值是2^80次。她的寻找MD5碰撞的方法是极端高效的。传说王小云当时在会议上把碰撞写出来，结果被下面的人验证发现不对，原来她把MD5算法的一个步骤弄错了。但是她立马联系她的当时留在中国的学生，修正算法，并找到一个新的碰撞。这一个是对的。&lt;/p&gt;
&lt;p&gt;　　看到这里，那些认为中国国安局应该将这些结果封存作为秘密武器甚至幻想用这些成果来袭击美国之徒可以停住你们的YY了。这种形式上的破解，在大多数情况下没有实际性的作用。更别提MD5早就被美国人抛弃了。&lt;/p&gt;
&lt;p&gt;　　但是，说这种破解一点实际意义都没有，那就侮辱了广大密码学家的智商，密码学家不会无缘无故的弄出碰撞这么一个概念来。下面简单的介绍一下在特定情况下，怎么利用给定的碰撞来做坏事(翻译自&lt;a href=&#34;http://th.informatik.uni-mannheim.de/people/lucks/HashCollisions/&#34;&gt;Attacking Hash Functions&lt;/a&gt;)：&lt;/p&gt;
&lt;p&gt;　　Caesar给实习生Alice叫写了一封推荐信(letter)。同一天，Alice叫Caesar在推荐信上数字签名，并提供了一份推荐信的电子板。Caesar打开文件，发现和原件一模一样。所以他在文件上签了名。&lt;/p&gt;
&lt;p&gt;　　几个月后，Caesar发现他的秘密文件被非法察看。这到底是怎么回事呢？&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/letter_of_rec.ps&#34;&gt;&lt;img alt=&#34;letter&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/867e9ee66a7ab1aed4342dcb1a98489a6ab17134.png&#34;&gt; &lt;/a&gt;&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/order.ps&#34;&gt;&lt;img alt=&#34;order&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1a84f3c37a7c98c13605362aa25991c19b6d2d7b.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　&lt;img alt=&#34;(apply MD5 to both documents)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bf67e539f3da6867fc8a9070b940b83ff6daed5d.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;　　a25f7f0b 29ee0b39 68c86073 8533a4b9&lt;/p&gt;
&lt;p&gt;　　事实上，Alice要求Caesar签名的文件&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/letter_of_rec.ps&#34;&gt;letter&lt;/a&gt;已经被Alice做了手脚，准确地说，Alice还准备了另外一个文件&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/order.ps&#34;&gt;order&lt;/a&gt;，它们的MD5码完全一致。而Caesar的数字签名还依赖于MD5算法，所以Alice用order文件替换Letter文件之后，Caesar的数字签名依然有效。那封order给Alice提供了察看秘密文件的权限。&lt;/p&gt;
&lt;p&gt;　　具体的实现方法可见&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/rump_ec05.pdf&#34;&gt;Hash Functions and the Blind Passenger Attack&lt;/a&gt;。我在这里简单的解释一下(只是大致思路，具体实现方式，需要对文件结构信息有所了解)：&lt;/p&gt;
&lt;p&gt;　　letter文件的内容是：
　　　　if(x1==x1) show &amp;ldquo;letter&amp;rdquo; else show &amp;ldquo;order&amp;rdquo;
　　order文件的内容是：　　　
　　　　if(x2==x1) show &amp;ldquo;letter&amp;rdquo; else show &amp;ldquo;order&amp;rdquo;
　　其中字符串&amp;quot;letter&amp;quot;和&amp;quot;order&amp;quot;代表两封信实际显示的内容。x1，x2是一个MD5的碰撞。&lt;/p&gt;
&lt;p&gt;　　上面的方法，只供参考和学术用途，实际使用所引起的后果概不负责。　　
　　参考：
　　１.&lt;a href=&#34;http://th.informatik.uni-mannheim.de/people/lucks/HashCollisions/&#34;&gt;Attacking Hash Functions by Poisoned Messages &amp;ldquo;The Story of Alice and her Boss&amp;rdquo;&lt;/a&gt;
　　２.&lt;a href=&#34;http://en.wikipedia.org/wiki/Hash_function&#34;&gt;Hash function&lt;/a&gt;, wikipedia　
　　３.&lt;a href=&#34;http://en.wikipedia.org/wiki/SHA_hash_functions&#34;&gt;SHA&lt;/a&gt;, wikipedia
　　４.Interview with Yiqun Lisa Yin concerning the attack on SHA-1　&lt;/p&gt;
&lt;p&gt;　　原文来自：&lt;a href=&#34;http://zhiqiang.org/blog/science/computer-science/preliminary-computer-theory-xiao-yun-wang-from-the-hash-function-to-crack-md5.html&#34;&gt;http://zhiqiang.org&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>一个简单实例的LR分析过程</title>
      <link>http://blog.leaver.me/2012/05/14/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E5%AE%9E%E4%BE%8B%E7%9A%84lr%E5%88%86%E6%9E%90%E8%BF%87%E7%A8%8B/</link>
      <pubDate>Mon, 14 May 2012 11:38:49 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/14/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E5%AE%9E%E4%BE%8B%E7%9A%84lr%E5%88%86%E6%9E%90%E8%BF%87%E7%A8%8B/</guid>
      <description>&lt;p&gt;　　经过前面两篇文章。已经讲清楚了LR语法分析中最重要的分析表的构造过程。先补充一个小问题，就是LR(0)项目的分类&lt;/p&gt;
&lt;p&gt;　　根据圆点所在的位置和圆点后是终结符还是非终结符或为空把项目分为以下几种：&lt;/p&gt;
&lt;p&gt;　　移进项目： 形如 A→α .a β ，a是终结符, a ,b∈V* 以下同
　　待约项目：A→α .B β , 其中B是非终结符　
　　归约项目：A→α . 表明产生式已分析完成。　
　　接受项目：形如 S’→S .　　
　　特别的。A→ε的LR(0)项目只有A→ • 是归约项目&lt;/p&gt;
&lt;p&gt;　　因为LR分析表的构造前面两篇文章已经讲的很清楚了，所以这个题目重要是解释一下如何使用分析表来构造，分析表的构造也许你得自己参考前面两篇文章来构造了。题目来自网络。&lt;/p&gt;
&lt;p&gt;　　好，下面看题目，已知文法G[S]：&lt;/p&gt;
&lt;p&gt;　　(1) S → aAcBe
　　(2) A → b　
　　(3) A → Ab　　
　　(4) B → d&lt;/p&gt;
&lt;p&gt;　　写出对输入串 abbcde#的LR分析 过程。&lt;/p&gt;
&lt;p&gt;　　在分析的时候，因为我们的手工分析，所以还需要一个表来记录我们的步骤。否则记不住啊。该表共需7列。行数不定。做到哪是哪。&lt;/p&gt;
&lt;p&gt;　　&lt;pre lang=&#34;php&#34;&gt; 步骤   符号栈   输入符号栈     动作   状态栈    ACTION    GOTO &lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;　　其中，步骤就是从1向下递增。符号栈用来保存运算中的结果，初始为#，输入符号栈保存输入串，初始值为给定的。动作里面就是用来注释是进行移进，还是规约。状态栈就是保持LR分析表的那个状态了。Action 和Goto同理&lt;/p&gt;
&lt;p&gt;　　通过前两篇文章的步骤，此题可以构造出如下的一张LR分析表&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21467_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5b2465bb8d435fab286faf6634217380656ce008.jpg&#34; title=&#34;lr分析表&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　分析表中有Si和rj大家都知道的。s是shift的缩写，也就是移进，r是reduce的缩写，也就是规约。规约是推导的逆操作，大家都懂。&lt;/p&gt;
&lt;p&gt;　　先来看看在进行分析的时候s和j操作的规则&lt;/p&gt;
&lt;p&gt;　　Si:移进，把i移入到状态栈，把a移入到文法符号栈。其中i，j表示状态号。&lt;/p&gt;
&lt;p&gt;　　ri:归约，用第i个产生式归约，同时状态栈与符号栈退出相应个符号，并把GOTO表相应状态和第i个产生式的左部非终结符入栈。&lt;/p&gt;
&lt;p&gt;　　文法中有A→β的产生式，若β的长度为r(即|β|=r)，则从状态栈和文法符号栈中自栈顶向下去掉r个符号，即栈指针P减去r。并把A移入文法符号栈内，Sj=GOTO[Si，A]移进状态栈，其中Si为修改指针后的栈顶状态。&lt;/p&gt;
&lt;p&gt;　　当归约到文法符号栈中只剩文法的开始符号S时，并且输入符号串已结束即当前输入符是&amp;rsquo;#&amp;rsquo;，则为分析成功。&lt;/p&gt;
&lt;p&gt;　　然后使用我们将要使用的辅助表来分析吧，为了简单。我还是直接给出答案。然后分析一下典型的情况。&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21466_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d6565babf03f2f230fb9d8933518bc1cb55bf7cc.jpg&#34; title=&#34;分析结果&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　第一步，符号栈中是#，输入符号串就是给定的要分析的串，状态栈因为从0开始，所以状态栈直接填0，大家都知道，LR分析是从左到右扫描的。所以心里想着一根指针p，p首先指向输入串的a，然后我们查分析表的（0，a）,0就是状态0，a就是指针的当前字符。分析表中的（0，a）是s2，填入第一步的action，并且动作列填入移进，根据规则，将2入状态栈，a入符号栈，&lt;/p&gt;
&lt;p&gt;　　进入第二步，指针p肯定要前进一步了，所以输入符号串就进入b了。此步同上一步，不多解释。&lt;/p&gt;
&lt;p&gt;　　关键是进入第三步后，此时，符号栈中为#ab，输入符号串是bcde#，状态栈是024，此时去查表，差的是（4，b），4是状态栈顶，b是p指针的当前位置。发现是r2，根据规则，用第二条产生式(2) A → b来规约。把动作栏先填了，同时状态栈与符号栈退出相应个符号，也即是说，把状态栏的栈顶4，退出来，同时符号栈的b也退出，心里想着，不填表，并把GOTO表相应状态和第i个产生式的左部非终结符入栈。Goto表需要查的是(2,A)=3,2是r2的2，A是第二个产生式的左部嘛。所以，就把3入状态栈，A入符号栈。&lt;/p&gt;
&lt;p&gt;　　后面的都是一样的。不解释了。要想学懂编译原理。多动手是必需的。你也手工试试吧。&lt;/p&gt;
&lt;p&gt;参考：
　　 &lt;a href=&#34;http://leaver.me/archives/574.html&#34;&gt;http://leaver.me/archives/574.html&lt;/a&gt;
　　 &lt;a href=&#34;http://leaver.me/archives/548.html&#34;&gt;http://leaver.me/archives/548.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>LR(0)和SLR分析表的构造</title>
      <link>http://blog.leaver.me/2012/05/13/lr0%E5%92%8Cslr%E5%88%86%E6%9E%90%E8%A1%A8%E7%9A%84%E6%9E%84%E9%80%A0/</link>
      <pubDate>Sun, 13 May 2012 10:45:13 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/13/lr0%E5%92%8Cslr%E5%88%86%E6%9E%90%E8%A1%A8%E7%9A%84%E6%9E%84%E9%80%A0/</guid>
      <description>&lt;p&gt;　　&lt;a href=&#34;http://leaver.me/archives/548.html&#34;&gt;上篇文章中&lt;/a&gt;，我已经说到了，LR(0)分析表是LR(0)分析器的重要组成部分，它是总控程序分析动作的依据，他是由LR(0)项目集规范族来进行构造的。他的结构主要有两个部分ACTION 和GOTO&lt;/p&gt;
&lt;p&gt;　　先看看指导原则，可以直接跳过，看例题的时候可以返回来对照参考。&lt;/p&gt;
&lt;p&gt;　　假设已构造出LR(0)项目集规范族为：C={I0,I1, … , In}，其中Ik为项目集的名字，k为状态名，令包含S′→·S项目的集合Ik的下标k为分析器的初始状态。那么分析表的ACTION表和GOTO表构造步骤为：&lt;/p&gt;
&lt;p&gt;　　① 若项目A→α·aβ属于Ik且转换函数GO(Ik,a)= Ij，当a为终结符时则置ACTION[k,a]为Sj。　
　　② 若项目A→α· 属于Ik，则对任何终结符a 和&amp;rsquo;#&amp;lsquo;号置ACTION[k,a]和ACTION[k,#]为&amp;quot;rj&amp;quot;，j为在文法G′中某产生式A→α的序号。
　　③ 若GO(Ik,A)＝Ij，则置GOTO[k,A]为&amp;quot;j&amp;quot;，其中A为非终结符。　
　　④ 若项目S′→S·属于Ik，则置ACTION[k,#]为&amp;quot;acc&amp;quot;，表示接受。
　　⑤ 凡不能用上述方法填入的分析表的元素，均应填上&amp;quot;报错标志&amp;quot;。为了表的清晰我们仅用空白表示错误标志。&lt;/p&gt;
&lt;p&gt;　　上篇文章的例题是这样的：LR（0）项目集规范簇也已经算出来了，共有6个I，从I0-I5，最终构造的LR(0)的分析表共7行，包括标题行，也就是ACTION和GOTO，然后是状态行，状态行和ACTION的交处分割成三列，分别是终结符号，和#终结符。也就是分割多少列取决于终结符的数目，GOTO列是非终结符，分割多少列也取决于非终结符的数目。，然后就是具体的6个状态了，画出表的结构后，如下，先不用管表的内容怎么写。&lt;/p&gt;
&lt;p&gt;　&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21422_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/0f0ac59f4cab73039ae7f5aecb327def5665da13.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　然后对照构造原则来填写表，这时你会发现要一个个从那么多的GO函数和I项目组中找对应的式子实在太难了，看不清楚，这时候，我们用GO函数把LR(0)项目集规范族连成一个识别该文法所产生的活前缀的DFA，有点像流程图了，首先把各个I项目画出来，然后需要把他们的关系表示出来，关系由GO函数确定，比如I5=GO(I2, S)，则在I2和I5之间画一个箭头，由I2指向I5，线上写上S，由括号里的第二个值确定，此题构造的DFA如下图，很简单吧。&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21397_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34; title=&#34;识别活前缀的DFA&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　&lt;span style=&#34;font-family: Verdana, Arial, Helvetica, sans-serif;&#34;&gt;&lt;span style=&#34;font-size: 12px; line-height: normal;&#34;&gt;然后我们正式开始吧。第一条指导规则说到， 若项目A→α·aβ属于Ik且转换函数GO(Ik,a)= Ij，当a为终结符时则置ACTION[k,a]为Sj，我们先考察对于I0，发现S-&amp;gt;·aS属于I0，且GO(I0,a)=I1,所有我们ACTION[0,a]置为S1.同理S-&amp;gt;·bS属于I0，GO(I0,b)=I2，所以ACTION[0,b]置为S2。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;　　再来看第二条规则，若项目A→α· 属于Ik，则对任何终结符a 和&amp;rsquo;#&amp;lsquo;号置ACTION[k,a]和ACTION[k,#]为&amp;quot;rj&amp;quot;，j为在文法G′中某产生式A→α的序号，也就是说这里的j可不是I项目的标号，而是增广文法&lt;/p&gt;
&lt;p&gt;　　(0)S’→S　
　　(1)S→aS　
　　(2)S→bS
　　(3)S→a&lt;/p&gt;
&lt;p&gt;　　的标号，从0-3啦。我们考察I1，发现S→·aS属于I1，且GO(I1,a)=I1，所以应该置1和a的交的格子为S1，但是此时运用第二条规则会发现S-&amp;gt;a·也属于I1，则又应该置ACTION[1,a]为=r3，ACTION[1,#]为r3，这样就发生了冲突。这是因为大多数文法不能满足LR(0)文法的条件，对于此冲突，我们不能确定看到S-&amp;gt;a的时候是规约还是移进，有些文法是可以直接构造的，为此，此处不能够早LR(0)分析表了，我们构造经过改进后得到了一种新的SLR(1)文法，并没有什么太大差别，主要就是解决冲突。&lt;/p&gt;
&lt;p&gt;　　解决冲突的指导原则如下：&lt;/p&gt;
&lt;p&gt;　* 假设一个LR（0）项目集规范族中有如下项目集合：&lt;/p&gt;
&lt;p&gt;　　{X → α.bβ，A → γ.，B → δ.}&lt;/p&gt;
&lt;p&gt;　　即存在移进-归约冲突和归约-归约冲突&lt;/p&gt;
&lt;p&gt;　　* 如果FOLLOW（A）∩ FOLLOW（B）∩ {b} =ф，则可以如下来解决冲突（假设当前符号是 a ）：　
　　1、若 a = b，则移进
　　2、若 a∈ FOLLOW（A），则用产生式 A → γ归约　
　　3、若 a∈ FOLLOW（B），则用产生式 B → δ归约　
　　4、否则，报错&lt;/p&gt;
&lt;p&gt;　　此处的冲突发生时，当前符号是a，并且此时项目集中无B推导式，且指导规则中的b在此处其实是S-&amp;gt;.aS中的a，所以计算Follow(S)∩ {a} ，发现为空，所以可以解决冲突，因为此时，当前符号是a，此处规则中的b也是a，所以，移进，也就是置ACTION[1,a]为=S1，运用分析表的ACTION表和GOTO表构造步骤的第一步，而不是置为r3，所以冲突解决。&lt;/p&gt;
&lt;p&gt;　　然后再看构造步骤中的第三步，若GO(Ik,A)＝Ij，则置GOTO[k,A]为&amp;quot;j&amp;quot;，其中A为非终结符。此题中，只有S为非终结符，看DFA中的I0，发现GO(I0,S)＝I3，所以置GOTO[0,S]为3，ok&lt;/p&gt;
&lt;p&gt;　　第四个步骤，若项目S′→S·属于Ik，则置ACTION[k,#]为&amp;quot;acc&amp;quot;，很简单，DFA中，I3符合，所以置ACTION[3,#]为&amp;quot;acc&amp;quot;。到此解释完了&lt;/p&gt;
&lt;p&gt;　　反复运用，直到填完表。&lt;/p&gt;
&lt;p&gt;　　完成后的表如图一所示。太复杂了。脑子烧糊了都，下篇有机会的话介绍如何使用来进行分析。其实剩下的部分不怎么难了。应该可以看得懂了&lt;/p&gt;
&lt;p&gt;　　参考：&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://metc.gdut.edu.cn/compile/nandian/n-7.htm&#34;&gt;http://metc.gdut.edu.cn/compile/nandian/n-7.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://jpkc.hdu.edu.cn/computer/byyl/online/4-3.htm&#34;&gt;http://jpkc.hdu.edu.cn/computer/byyl/online/4-3.htm&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>LR(0)项目集规范族的构造</title>
      <link>http://blog.leaver.me/2012/05/12/lr0%E9%A1%B9%E7%9B%AE%E9%9B%86%E8%A7%84%E8%8C%83%E6%97%8F%E7%9A%84%E6%9E%84%E9%80%A0/</link>
      <pubDate>Sat, 12 May 2012 10:38:38 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/12/lr0%E9%A1%B9%E7%9B%AE%E9%9B%86%E8%A7%84%E8%8C%83%E6%97%8F%E7%9A%84%E6%9E%84%E9%80%A0/</guid>
      <description>&lt;p&gt;　　此文略长。我也没想到这写起来这么多，但对构造过程绝对清楚，一步步慢慢看吧。&lt;/p&gt;
&lt;p&gt;　　LR的第一个L和LL的第一个L含义相同，即从左到右扫描句子 ，第二个R表示Right most最右推导。&lt;/p&gt;
&lt;p&gt;　　在通常的描述中，后面还有一个括号里面的数字如，LR(0)、LR(1)这样，括号里面的数字表示用于决策所需的后续token分词数。&lt;/p&gt;
&lt;p&gt;　　首先看一下LR分析器的模型图&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21392_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34; title=&#34;LR模型&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　可惜看出，LR分析器最关键的部分就是 LR分析表了，而LR分析表的构建是由已构造出的LR(0)项目集规范族来进行构造的。LR分析法貌似是不要求掌握的，而且这部分比我想象的还要复杂，今天看了好多。才勉强搞清楚这个项目集规范族的构造，但是用来锻炼思维确实不错啊。&lt;/p&gt;
&lt;p&gt;　　项目集，那么字面上看就是项目的集合了，项目是什么呢。这个也确实不好说，书上是说在文法G中每个产生式的右部适当位置添加一个圆点构成LR(0)项目，举个例子吧。&lt;/p&gt;
&lt;p&gt;　　比如对于&lt;/p&gt;
&lt;p&gt;　　A-&amp;gt;xyz&lt;/p&gt;
&lt;p&gt;　　这条产生式可以构造的LR(0)项目就有4个&lt;/p&gt;
&lt;p&gt;　　A-&amp;gt;.xyz    A-&amp;gt;x.yz    A-&amp;gt;xy.z     A-&amp;gt;xyz.&lt;/p&gt;
&lt;p&gt;　　这样很清楚了吧，就是用.分割。这个分割产生的四个项目在进行真正的语法分析的时候对应不同的操作，比如规约还是移位。这里不讨论。重点是项目集规范族的构造，&lt;/p&gt;
&lt;p&gt;　　在知道了LR(0)项目后，可以来看看项目集规范族的定义，&lt;/p&gt;
&lt;p&gt;　　对于构成识别一个文法活前缀的DFA项目集(状态)的全体我们称之为这个文法的LR(0)项目集规范族。至于什么是活前缀呢，定义如下&lt;/p&gt;
&lt;p&gt;　　对于任一文法G[S]，若S’经过任意次推导得到αAω，继续经过一次推导得到![]}/images/6b23dd171a1f672514a2dbb29175df032a1f63d4.gif)αβω，若γ&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34;&gt;是αβ的前缀，则称γ是G的一个活前缀。&lt;/p&gt;
&lt;p&gt;　　现在知道了LR(0)项目，了解了活前缀，和项目集规范族的定义，还须引入LR(0)项目集的闭包函数CLOSURE和状态转换函数GO两个概念，先给出数学上的定义，如果你觉得麻烦可以跳过，后面会给出一道例题。&lt;/p&gt;
&lt;p&gt;　　① 闭包函数CLOSURE(I)的定义如下：&lt;/p&gt;
&lt;p&gt;　　a）I的项目均在CLOSURE(I)中。&lt;/p&gt;
&lt;p&gt;　　b）若A→α·Bβ属于CLOSURE(I)，则每一形如B→·γ的项目也属于CLOSURE(I)。&lt;/p&gt;
&lt;p&gt;　　c）重复b)直到不出现新的项目为止。即CLOSURE(I)不再扩大。&lt;/p&gt;
&lt;p&gt;　　② 转换函数GO(I，X)的定义：&lt;/p&gt;
&lt;p&gt;　　GO(I，X)＝CLOSURE(J)&lt;/p&gt;
&lt;p&gt;　　其中：I为包含某一项目的状态，就是前面我们说的那四个了。，X为一文法符号，X∈(VN∪VT)，J＝{任何形如A→αX·β的项目| A→α·Xβ属于I}。&lt;/p&gt;
&lt;p&gt;　　这样就可以使用闭包函数和转换函数构造文法G′的LR(0)项目集规范族，其步骤如下：&lt;/p&gt;
&lt;p&gt;　　  a）置项目S′→·S为初态集的核，然后对核求闭包，CLOSURE({S′→·S}）得到初态的项目集。
　　  b）对初态集或其它所构造的项目集应用转换函数GO(I，X)=CLOSURE(J)，求出新状态J的项目集。
　　  c）重复b）直到不出现新的项目为止。&lt;/p&gt;
&lt;p&gt;　　开始拿个例题来说明，定义没例题看起来看难了。&lt;/p&gt;
&lt;p&gt;　　&lt;strong&gt;&lt;em&gt;例题：对于下列文法，S→aS|bS|a，构造该文法的LR(0)项目集规范族&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　思路就是利用闭包函数CLOSURE和转换函数GO来构造。通过计算函数CLOSURE和GO得到文法的LR(0)项目集规范族，而GO函数则把LR(0)项目集规范族连成一个识别该文法所产生的活前缀的DFA。DFA大家都知道，有穷自动机。&lt;/p&gt;
&lt;p&gt;　　(1)将文法G(S)拓广为G(S’)也就是该文法的增广文法，目的是使语法分析器知道何时应该停止并接受该串，也就是说当使用S&amp;rsquo;-&amp;gt;S进行规约的时候，就结束。&lt;/p&gt;
&lt;p&gt;　　(0)S’→S
　　(1)S→aS　　
　　(2)S→bS　　
　　(3)S→a&lt;/p&gt;
&lt;p&gt;　　构造该文法的LR(0)项目集规范族，I就是产生式，至于I0 I1就是往下递增就可以了。没什么特别的意思。：&lt;/p&gt;
&lt;p&gt;　　I0=CLOSURE({S&amp;rsquo; →•S})={S’ →•S, S→•aS, S→•bS, S→•a}&lt;/p&gt;
&lt;p&gt;　　//第一条是固定的，都是求S&amp;rsquo; →•S的闭包。而因为右侧的S又可以推导出后面三个，所以后面三个式子是属于该闭包的。在闭包的规则中可以看出，若A→α·Bβ属于CLOSURE(I)，此时S&amp;rsquo; →•S属于闭包，S相当于规则中的B,则每一形如B→·γ的项目也属于CLOSURE(I),此处相当于S-&amp;gt;后面的三个推导式。加上.就可以了&lt;/p&gt;
&lt;p&gt;　　I1=GO( I0 , a)=CLOSURE({S→a•S , S→a•})={S→a•S , S→a• , S→•aS, S→•bS, S→•a }&lt;/p&gt;
&lt;p&gt;　　//第二条你可能已经看出来了，其实就是把转换函数GO反过来用，在GO函数中，X为一文法符号，J＝{任何形如A→αX·β的项目| A→α·Xβ属于I}。也就是在I0中，找到右侧包含a的项目，然后将.右移一位来求他们的闭包函数，此处，I0中包含.a的项目为 S→•aS和 S→•a，.右移一位变成S→a•S , S→a•，求闭包函数的规则和上面那条是一样的，继续找推导式右边可以推导出来的式子就可以了，此处，右边同样是S可以推导出三个式子，前面加上.就可以了。&lt;/p&gt;
&lt;p&gt;　　I2=GO(I0 , b)=CLOSURE({S→b•S })={ S→b•S, S→•aS, S→•bS, S→•a }&lt;/p&gt;
&lt;p&gt;　　//第三条仿照第二条进行推导，先在I0中找有.b的，然后右移一位，然后推导式右侧的S继续用题目给出的推导，然后前面加上.&lt;/p&gt;
&lt;p&gt;　　I3=GO(I0 , S)=CLOSURE({S’ →S•})={ S’ →S•}&lt;/p&gt;
&lt;p&gt;　　//第四条因为右侧包含.S的只有一项。必须是.S。所以只有一个，右移后求闭包即可。因为S是右侧的第一位，所以不用再向下推导了，规则是：A→α·Bβ属于CLOSURE(I)，此处是S’ →S•，则B→·γ的项目也属于CLOSURE(I)，此处S相当于规则中的α，无B。。。。&lt;/p&gt;
&lt;p&gt;　　因为GO(I1, a)=CLOSURE({S→a•S , S→a•})=I1，&lt;/p&gt;
&lt;p&gt;　　//第五条同理，在I1中找有右侧有.a的项目，右移一位。进行求闭包，发现和I1求闭包的变量是一样的。所以结果必然也和I1是一样的。&lt;/p&gt;
&lt;p&gt;　　GO(I1, b)=CLOSURE(S→b•S)=I2.&lt;/p&gt;
&lt;p&gt;　　//第六条没有新的I产生。&lt;/p&gt;
&lt;p&gt;　　I4=GO(I1, S)=CLOSURE({S→aS•})={S→aS•}&lt;/p&gt;
&lt;p&gt;　　//这第七条在I1找右侧包含.S的项目，只有S→a•S，右移后求闭包，同第四条，无B，所以直接如此。&lt;/p&gt;
&lt;p&gt;　　GO(I2, a)= CLOSURE({S→a•S , S→a•})=I1&lt;/p&gt;
&lt;p&gt;　　GO(I2, b)=CLOSURE({S→b•S})=I2&lt;/p&gt;
&lt;p&gt;　　I5=GO(I2, S)=CLOSURE({S→bS•})={S→bS•}&lt;/p&gt;
&lt;p&gt;　　此时应该继续求GO(I3, a)，GO(I3, b)和，GO(I3, S)，但显然I3中没有.a,没有.b也没有.S，所以不用多此一举了，&lt;/p&gt;
&lt;p&gt;　　继续求GO(I4, a)，GO(I4, b)和，GO(I4, S)，显然同上，也没有。所以也不用求了，&lt;/p&gt;
&lt;p&gt;　　继续求GO(I5, a)，GO(I5, b)和，GO(I5, S),理由同上，没有任何必要了&lt;/p&gt;
&lt;p&gt;　　最终，项目集I0，I1，I2，I3，I4和I5构成了该文法的LR(0)项目集规范族。&lt;/p&gt;
&lt;p&gt;　　编译原理真是博大精深啊。就一个简单的三个推导式就得这么多步骤才构造了一个规范族，还要利用规范族来构造LR分析表，这。。手工果断不是事啊。今天看了几个小时才完全弄清楚LR(0)项目集规范族的构造。例题的步骤是我自己写的。这篇文章写了2个小时。。太费脑子了。。慢慢再写产生活前缀的DFA和LR分析表吧。&lt;/p&gt;
&lt;p&gt;　　参考：&lt;/p&gt;
&lt;p&gt;　　&lt;a href=&#34;http://metc.gdut.edu.cn/compile/nandian/n-7.htm&#34;&gt;http://metc.gdut.edu.cn/compile/nandian/n-7.htm&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>.Net三层架构</title>
      <link>http://blog.leaver.me/2012/05/05/.net%E4%B8%89%E5%B1%82%E6%9E%B6%E6%9E%84/</link>
      <pubDate>Sat, 05 May 2012 15:09:37 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/05/.net%E4%B8%89%E5%B1%82%E6%9E%B6%E6%9E%84/</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;本文来源：&lt;a href=&#34;http://www.cnblogs.com/gaoweipeng/archive/2009/01/18/1377855.html&#34;&gt;http://www.cnblogs.com/gaoweipeng/archive/2009/01/18/1377855.html&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;老规矩。因为是非常不错的文章。所有有必要收藏下来备用。推荐。&lt;/p&gt;
&lt;p&gt;**&lt;span style=&#34;color: #0000ff;&#34;&gt;三层体系结构的概念&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;**&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户界面表示层(USL)&lt;/li&gt;
&lt;li&gt;业务逻辑层(BLL)&lt;/li&gt;
&lt;li&gt;数据访问层(DAL)
&lt;strong&gt;BLL将USL与DAL隔开了，并且加入了业务规则&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&#34;font-size: medium;&#34;&gt;各层的作用&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;1：数据数据访问层:主要是对原始数据（数据库或者文本文件等存放数据的形式）的操作层，而不是指原始数据，也就是说，是对数据的操作，而不是数据库,具体为业务逻辑层或表示层提供数据服务．
&lt;p&gt;2：业务逻辑层:主要是针对具体的问题的操作，也可以理解成对数据层的操作,对数据业务逻辑处理，如果说数据层是积木，那逻辑层就是对这些积木的搭建。&lt;/p&gt;
&lt;p&gt;3：表示层:主要表示WEB方式,也可以表示成WINFORM方式,WEB方式也可以表现成:aspx, 如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务。&lt;/div&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;具体的区分方法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1：数据数据访问层:主要看你的数据层里面有没有包含逻辑处理，实际上他的各个函数主要完成各个对数据文件的操作。而不必管其他操作。&lt;/p&gt;
&lt;p&gt;2：业务逻辑层:主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。&lt;/p&gt;
&lt;p&gt;3：表示层:主要对用户的请求接受，以及数据的返回，为客户端提供应用程序的访问。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;三层结构解释&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所谓三层体系结构，是在&lt;span style=&#34;text-decoration: underline;&#34;&gt;客户端与数据库之间&lt;/span&gt;加入了一个&lt;span style=&#34;text-decoration: underline;&#34;&gt;中间层&lt;/span&gt;，也叫&lt;span style=&#34;text-decoration: underline;&#34;&gt;组件层&lt;/span&gt;。这里所说的三层体系，不是指物理上的三层，不是简单地放置三台机器就是三层体系结构，也不仅仅有B/S应用才是三层体系结构，三层是指逻辑上的三层，即使这三个层放置到一台机器上。 三层体系的应用程序将业务规则、数据访问、合法性校验等工作放到了中间层进行处理。通常情况下，客户端不直接与数据库进行交互，而是通过COM/DCOM通讯与中间层建立连接，再经由中间层与数据库进行交换.&lt;/p&gt;
&lt;p&gt;开发人员可以将应用的商业逻辑放在中间层应用服务器上，把应用的业务逻辑与用户界面分开。在保证客户端功能的前提下，为用户提供一个简洁的界面。这意味着如果需要修改应用程序代码，只需要对中间层应用服务器进行修改，而不用修改成千上万的客户端应用程序。从而使开发人员可以专注于应用系统核心业务逻辑的分析、设计和开发，简化了应用系统的开发、更新和升级工作。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;那么为什么要应用“中间业务层”呢？举些例子:&lt;/strong&gt;
我们假设有一段登录代码，则可以这样处理Web程序，外观层负责接收前台页面的数据，然后传给中间层，中间层对数据进行处理，比如格式化，防SQL注入等等一些，这样的数据再传给数据访问层然后与数据库进行操作，比如与数据库的用户名和密码匹配等等一些代码。**&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;“中间业务层”的用途有很多，例如：验证用户输入数据、缓存从数据库中读取的数据等等……但是，&lt;span style=&#34;text-decoration: underline;&#34;&gt;“中间业务层”的实际目的是将“数据访问层”的最基础的存储逻辑组合起来，形成一种业务规则。&lt;/span&gt;例如：“在一个购物网站中有这样的一个规则：在该网站第一次购物的用户，系统为其自动注册”。这样的业务逻辑放在中间层最合适：&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;在“数据访问层”中，最好不要出现任何“业务逻辑”！也就是说，&lt;span style=&#34;text-decoration: underline;&#34;&gt;要保证“数据访问层”的中的函数功能的原子性！即最小性和不可再分。“数据访问层”只管负责存储或读取数据就可以了。&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;**
**&lt;/div&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ASP.NET中的三层结构说明&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;完善的三层结构的要求是:**修改表现层而不用修改逻辑层,修改逻辑层而不用修改数据层。**否则你的应用是不是多层结构,或者说是层结构的划分和组织上是不是有问题就很难说.不同的应用有不同的理解，这只是一个概念的问题．&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;/div&gt;
*   **理解ASP.NET中的三层结构**——为什么要分三层？
&lt;pre&gt;&lt;code&gt;我们用三层结构主要是使项目结构更清楚，分工更明确，有利于后期的维护和升级。它未必会提升性能，因为当子程序模块未执行结束时，主程序模块只能处于等待状态。这说明将应用程序划分层次，会带来其执行速度上的一些损失。但从团队开发效率角度上来讲却可以感受到大不相同的效果。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;需要说明一下，三层结构不是.NET的专利，也不是专门用在数据库上的技术。它是一种更加普适的架构设计理念。&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
**&lt;span style=&#34;font-size: medium;&#34;&gt;
&lt;/span&gt;**此种架构**要在数据库设计上注意表之间的关系，**尽力满足主与子的关系。在功能上对用户要有一定的限制，不要表现在对于子表的删除操作一定要慎重，以免造成主表与子表的数据在逻辑上出现的主表的外键在子表中没有相对应的值。
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对于表的&lt;strong&gt;综合查询&lt;/strong&gt;方法是：
先对主表查询，调用主表所对应的DL。再根据主表的记录分别对每一个子表进行查询。将自表的查询结果添加的主表后，形成一个大的查询集合。
对于表的操作（增删改）：
此时只对主表进行操作，调用主表对应的DL中的操作方法。
RL层是逻辑判断层，主要是对页面上传入的数据进行逻辑判断。RL层之上就是UI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;&lt;span style=&#34;font-size: medium;&#34;&gt;如何建立一个三层体系结构解决方案&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新建一个空白解决方案。然后：
“添加”－“新建项目”－“其他项目”－“企业级模版项目”－“C#生成块”－“数据访问”（数据层，下简称D层）
“添加”－“新建项目”－“其他项目”－“企业级模版项目”－“C#生成块”－“业务规则”（业务层，下简称C层）
“添加”－“新建项目”－“其他项目”－“企业级模版项目”－“C#生成块”－“Web用户界面”（界面层，下简称U层）
右键点“解决方案”－“项目&lt;strong&gt;依赖项”&lt;/strong&gt;，设置U依赖于D、C，C依赖于D。
对U添加引用D、C，对C添加引用D。
到此为止，一个三层的架子建立起来了。我上面说的很具体很“傻瓜”，知道的人觉得我废话，其实我这段时间很强烈的感觉到非常多的人其实对这个简单的过程完全不了解。虽然不反对建2个“空项目”和1个“Asp    net    Web应用程序项目”也可以作为3层的框架，而且相当多的人认为其实这些“企业级模板项目”其实就是个空项目，这是一个误区。没错，企业级模板项目你从解决方案资源管理器里看它是个什么也没有的，但是你可以用记事本打开项目文件，看见不同了吧？？有些东西在背后，你是看不见的，不过系统已经做好了。也就是说，如果你在C层里的某个类里“using    System    Data    SqlClineit”，或者使用一个SqlConnection对象，编译时候不会出错，但是会在“任务列表”里生成一些“策略警告”，警告你在C层里不要放应该放在D层的东西（虽然就程序来说没错，但是可读性可维护性就打了折扣）而这种功能，空项目是无法給你的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;在新TraceLWord3中，应用了“企业级模板项目”。把原来的LWordTask.cs，并放置到一个单一的项目里，项目名称为：AccessTask。解决方案中又新建了一个名称为：InterService的项目，该项目中包含一个LWordService.cs程序文件，它便是“中间业务层”程序。为了不重复命名，TraceLWord3的网站被放置到了WebUI项目中。&lt;/span&gt;更完整的代码，可以在CodePackage/TraceLWord3目录中找到——&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;**&lt;span style=&#34;font-size: medium;&#34;&gt;面象对象与实际的结合&lt;/p&gt;
&lt;p&gt;&lt;/span&gt;**&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;我们知道建桥需要砖块，应该是先准备好砖再来建桥，不过为了讲解上的顺序性和连贯性，简单性。我们先建桥，建的过程中需要砖块再现做，这样就不会多出来“桥不需要的东西”。注意在实际中，还是应该先准备砖块。&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
U层其实就是桥，C层是砖块，D层是原料（石头、沙子）。这也解释前面为什么U层要引用、依赖D层（而不是U对C，C对D的层次），因为桥除了需要砖头，其实也需要石头沙子。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;“三层结构”的缺点&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有些网友在读完这篇文章前作之后，对我提出了一些质疑，这提醒我文章至此还没有提及“三层结构”的缺点。“三层结构”这个词眼似乎一直都很热门，究其原因，或许是这种开发模式应用的比较普遍。但是“三层结构”却并不是百试百灵的“万灵药”，它也存在着缺点。下面就来说说它的缺点……&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;“三层结构”开发模式的一个非常明显的缺点就是其执行速度不够快。当然这个“执行速度”是相对于非分层的应用程序来说的。&lt;/span&gt;从文中所给出的时序图来看，也明显的暴露了这一缺点。TraceLWord1和TraceLWord2没有分层，直接调用的ADO.NET所提供的类来获取数据。但是，TraceLWord6确要经过多次调用才能获取到数据。在子程序模块程序没有返回时，主程序模块只能处于等待状态。所以在执行速度上，留言板的版本越高，排名却越靠后。&lt;span style=&#34;text-decoration: underline;&#34;&gt;“三层结构”开发模式，不适用于对执行速度要求过于苛刻的系统，例如：在线订票，在线炒股等等……它比较擅长于商业规则容易变化的系统。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;“三层结构”开发模式，入门难度够高，难于理解和学习。这是对于初学程序设计的人来说的。&lt;span style=&#34;text-decoration: underline;&#34;&gt;以这种模式开发出来的软件，代码量通常要稍稍多一些。&lt;/span&gt;这往往会令初学者淹没在茫茫的代码之中。望之生畏，对其产生反感，也是可以理解的……&lt;/p&gt;
&lt;p&gt;其实，无论哪一种开发模式或方法，都是有利有弊的。不会存在一种“万用法”可以解决任何问题。所以“三层结构”这个词眼也不会是个例外！是否采用这个模式进行系统开发，要作出比较、权衡之后才可以。切忌滥用!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&#34;font-size: medium;&#34;&gt;参与资料&lt;/span&gt;&lt;/strong&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://www.bincess.cn/Downloads/MainDoc.rar&#34;&gt;MainDoc.rar    （《浅谈“三层结构”原理与用意》1.30M)      &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.bincess.cn/Downloads/MainDoc.rar&#34;&gt;http://www.bincess.cn/Downloads/MainDoc.rar&lt;/a&gt;     &lt;span style=&#34;color: #0000ff;&#34;&gt;&lt;/p&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;petshop 4.0的体系结构（只是稍微看了一下，了解一下结构）&lt;/p&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;简介：PetShop随着版本的不断更新，至现在基于.Net 2.0的PetShop4.0为止，整个设计逐渐变得成熟而优雅，而且有很多可以借鉴之处。PetShop是一个小型的项目，系统架构与代码都比较简单，却也凸现了许多颇有价值的设计与开发理念。&lt;/div&gt;
&lt;div&gt;下载地址:[http://msdn.microsoft.com/en-us/library/aa479070.aspx](http://msdn.microsoft.com/en-us/library/aa479070.aspx)&lt;/div&gt;
&lt;div&gt;**PetShop架构设计**
三层”应用结构：数据访问层、业务逻辑层（领域层）、表示层
分层的设计的特点：
结构清晰、耦合度低
便于系统的扩展
利于开发任务同步进行
降低了一定的性能&lt;/div&gt;
&gt; &lt;div&gt;.Net    PetShop    4.0    配置文件属性管理&lt;/div&gt;
&gt; &lt;div&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;http://blog.csdn.net/fengfangfang/archive/2006/09/07/1189061.aspx&lt;/span&gt;
&gt; 
&gt;     .Net    PetShop    4.0    缓存处理
&gt; &lt;span style=&#34;text-decoration: underline;&#34;&gt;http://blog.csdn.net/fengfangfang/archive/2006/09/06/1185077.aspx&lt;/span&gt;
&gt; 
&gt;     .Net    PetShop    4.0    消息处理
&gt; [http://blog.csdn.net/fengfangfang/archive/2006/09/08/1194896.aspx](http://blog.csdn.net/fengfangfang/archive/2006/09/08/1194896.aspx)
&gt; 
&gt;     每个功能都使用了工厂模式 &lt;span style=&#34;color: #0000ff;&#34;&gt;
&gt; &lt;/span&gt;&lt;/div&gt;
&gt; &lt;div&gt;&lt;/div&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;参考了Duwamish
&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;Web Search&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>System.Web中不存在类型或命名空间名称UI解决</title>
      <link>http://blog.leaver.me/2012/04/13/system.web%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%B1%BB%E5%9E%8B%E6%88%96%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E5%90%8D%E7%A7%B0ui%E8%A7%A3%E5%86%B3/</link>
      <pubDate>Fri, 13 Apr 2012 16:52:29 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/13/system.web%E4%B8%AD%E4%B8%8D%E5%AD%98%E5%9C%A8%E7%B1%BB%E5%9E%8B%E6%88%96%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E5%90%8D%E7%A7%B0ui%E8%A7%A3%E5%86%B3/</guid>
      <description>&lt;p&gt;今天打算用C#写个模拟登录的程序。从类库里找到一个HTMLHelper的类。用来处理html的请求接收等处理。为了让类能够先运行起来，先把该类拖入解决方案，引用就不用添加了，因为该类没写命名空间，可以直接用，我测试其中一个最简单的函数&lt;/p&gt;
&lt;pre lang=&#34;C#&#34;&gt; private void btnGet_Click(object sender, EventArgs e)
        {
            txtContent.Text=HTMLHelper.Get_Http(&#34;http://leaver.me&#34;);
        }&lt;/pre&gt;
&lt;p&gt;获取我网站的首页源代码。到TextBox控件
编译，运行。出现如题错误。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20479_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/54e8c1e1dd772294c6666aa9a404276089188b20.png&#34;&gt;
&lt;/a&gt;
命名空间“System.Web”中不存在类型或命名空间名称“UI”。是否缺少程序集引用? E:\project\C#\GTest\GTest\HTMLHelper.cs
直接对着错误点右键，复制。然后删掉后面的路径。使关键字包括前面几个就行了，到Google中搜索。大部分人给的说明都是
原因是缺少System.web的引用，只要右键单击项目，添加引用就行了！
那咱就添加呗 对着工程点击引用-&amp;gt;添加引用&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20480_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a0a47e17fbab5a4472ba94d77e51f8d372c64121.png&#34;&gt;&lt;/a&gt;
悲剧发生了。。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20481_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/64261ab1e4ed043cf5aa5c973c324795405e4201.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;根本就没有该dll文件。。泪奔了。。于是Google之。。发现没有一个讲清楚的。都是夸夸其谈。。没有任何实质性方案。于是换英语搜。
关键字：Cannot add System.Web.dll reference
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20482_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d2f3cc95979d5c583471580599b36d269791eae4.png&#34;&gt;
&lt;/a&gt;
第一个是stackoverflow，大名鼎鼎的栈溢出啊。。进去看看。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For people that cant find &amp;ldquo;System.Web&amp;rdquo; at .Net References, this might be the answer:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;you need to right-click the project -&amp;gt; properties -&amp;gt; then change the &amp;ldquo;Target framework&amp;rdquo; which will probably be &amp;ldquo;.NET Framework 4 Client Profile&amp;rdquo; to just &amp;ldquo;.NET Framework 4&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The answer was given by Tinister (thanks) as a reply to a previuos post. But I thought it was a little bit hidden at his original post. So i put it here to make it easer to be seen. Hope it helps.
大牛的我就不翻译了，很简单。项目-&amp;gt;项目属性-&amp;gt;目标框架 改成.net framework 4
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20483_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/457f4431088a7cb6b474f3d36cbc9ec738499ab1.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20484_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a7ba54a6e73b0b536554c04415d6a72d4cd89491.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个步骤完成后，重复前面的添加引用的步骤就会发现已经有了System.Web引用了
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20487_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/9379ef1ef5dba7bad0d039ce91ea9174d1610f65.png&#34;&gt;&lt;/a&gt;
编译运行。一切ok
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20485_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8e5ae5c835f250b1bceca5e8d3a8bda384df2bab.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果你遇到了这样的问题也可以试试吧。&lt;/p&gt;
&lt;p&gt;转自请注明：&lt;a href=&#34;http://leaver.me/archives/177.html&#34;&gt;http://leaver.me/archives/177.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>andorid 实现拖动滑动效果</title>
      <link>http://blog.leaver.me/2012/04/12/andorid-%E5%AE%9E%E7%8E%B0%E6%8B%96%E5%8A%A8%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/</link>
      <pubDate>Thu, 12 Apr 2012 11:05:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/12/andorid-%E5%AE%9E%E7%8E%B0%E6%8B%96%E5%8A%A8%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/</guid>
      <description>&lt;p&gt;这个大家都有过体会，就是当你左右拖动的时候，能够做到向左向右翻页。代码我写了很详细的注释。包括xml的注释，所以就不怎么解释了。先测试下代码高亮能用不.我当前用的是&lt;strong&gt;WP-Syntax&lt;/strong&gt;插件。将就着还行吧。如果你知道更好的话。不妨给我推荐一下。&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt;package com.android.flip;

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.ViewFlipper;

/**
 * Android实现左右滑动效果
 * @author byStander
 *
 */&lt;/pre&gt;</description>
    </item>
  </channel>
</rss>
