<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>设计 on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/%E8%AE%BE%E8%AE%A1/</link>
    <description>Recent content in 设计 on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sun, 10 May 2015 17:23:10 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/%E8%AE%BE%E8%AE%A1/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>关于重构和设计模式</title>
      <link>http://blog.leaver.me/2015/05/10/%E5%85%B3%E4%BA%8E%E9%87%8D%E6%9E%84%E5%92%8C%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link>
      <pubDate>Sun, 10 May 2015 17:23:10 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/05/10/%E5%85%B3%E4%BA%8E%E9%87%8D%E6%9E%84%E5%92%8C%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</guid>
      <description>&lt;p&gt;之前在工作写了一个数据库查询的工具.大体背景就是这种工具需要跨不同环境的数据库,开发,测试,性能等.最早简单写了一个版本,在第一次查询时会初始化三个库的连接,保存在map中,然后后续查询直接根据使用者选择的环境类型取出对应的连接构造sql即可.&lt;/p&gt;
&lt;p&gt;随着各个不同系统接入的越来越多,各个平台都保存了自己的连接,导致代码冗余度急剧上升,上周,利用晚上的一点时间读了一下&amp;laquo;重构&amp;raquo;,这本书,深受启发,一个是重构就是要采用小步快走的方式,在测试用例的覆盖下,快速改动,去掉代码中不合理的地方.另一个就是重构需要对业务的当下和未来的变化有一个比较深刻的理解,知道这个系统能做什么,不能做什么.才能更好地做重构.&lt;/p&gt;
&lt;p&gt;于是,根据这个工具的特点,感觉抽象工厂模式比较合适,于是在抽象工厂模式的指导下,对关键部分进行了重构,在增加了几个类之后,代码复杂度开始下降.各个接入系统的代码基本上保持在了几十行内,之前都是几百行,大量冗余代码,只能说自己之前眼光太短浅了.并且,采用了类似单例模式的操作.当查询的时候,先根据当前环境作为key取连接,如果连接被关闭,或者不存在,则初始化,然后放到map中,返回.如果有的话,直接用.这样改动后,第一次查询的时候只需要初始化一个连接,速度极快.也算个好处..&lt;/p&gt;
&lt;p&gt;由此,反思了一下,设计模式之前也看过.但是总觉得各种书上讲的都比较浅显,给出的例子也似乎如作者所说,很符合那个模式,但实际上,在工作中如何识别当下的业务应该是比较难的,需要在业务变动中,不断地重构自己的代码,才能发现,某一种模式似乎特别适合解决这种问题,反之,重构也需要一定的设计模式作为基础,否则对代码的重构会只停留在抽取公共方法.重命名.大类变小类的阶段..&lt;/p&gt;
&lt;p&gt;希望接下来能够抽空把&amp;laquo;敏捷软件开发：原则、模式与实践&amp;raquo;这本书看完.同时能够真的理解这些模式的场合,想起一句话,知道一个技术方案的好,说明你还没有理解这种方法,只有你知道了这个方案的不足,你才真正理解了他,相信很多技术我都没有理解.设计模式也是,希望之后能够理解每种模式的不足,重构这本书也要经常翻翻,能加深对代码的理解.&lt;/p&gt;</description>
    </item>
    <item>
      <title>《Spring揭秘》读书笔记-第一章Spring框架的由来</title>
      <link>http://blog.leaver.me/2014/06/30/spring%E6%8F%AD%E7%A7%98%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%80%E7%AB%A0spring%E6%A1%86%E6%9E%B6%E7%9A%84%E7%94%B1%E6%9D%A5/</link>
      <pubDate>Mon, 30 Jun 2014 20:40:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/06/30/spring%E6%8F%AD%E7%A7%98%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%80%E7%AB%A0spring%E6%A1%86%E6%9E%B6%E7%9A%84%E7%94%B1%E6%9D%A5/</guid>
      <description>&lt;p&gt;1.框架的由来&lt;/p&gt;
&lt;p&gt;倡导J2EE轻量级应用解决方案&lt;/p&gt;
&lt;p&gt;框架总结结构&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/06/Spring-Framework.jpg&#34;&gt;&lt;img alt=&#34;Spring Framework&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8775d9e40dbc29240061edd2b9b6f76990f39cad.jpg&#34;&gt;&lt;/a&gt;
整个Spring架构建立在Core核心模块上，是基础，该模块中，有一个IoC容器的实现，用来以依赖注入的方式管理对象之间的依赖关系。Core中还有一些气筒工具类，比如IO工具类&lt;/p&gt;
&lt;p&gt;从图中看到，AOP模块，提供了轻便二强大的AOP框架，一AOP的形式增强POJO的能力，弥补OOP/OOSD的不足，采用Proxy模式，与IoC容器相结合&lt;/p&gt;
&lt;p&gt;继续向上看，在Core和AOP之上，提供了完毕的数据访问和事务管理的抽象，其中，对JDBC API的最佳实践简化了API的使用，还未ORM产品提供了统一的支持，&lt;/p&gt;
&lt;p&gt;为了简化Java EE的服务，比如JNDI，JMS等等，Spring还提供了这些的集成服务，&lt;/p&gt;
&lt;p&gt;最后就是Web模块，提供了一套自己的Web MVC框架，上层模块依赖于下层模块，水平之间的模块彼此基本可以认为独立。&lt;/p&gt;
&lt;p&gt;Spring不仅仅是容器，更是开发任何Java应用的框架，&lt;/p&gt;
&lt;p&gt;Spring 框架之上衍生的产品包括不限于Spring Web Flow,Spring Web Services,Spring Security,Spring Integration，Spring Rich Client 等等等等&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]运用 BoxLayout 进行 Swing 控件布局</title>
      <link>http://blog.leaver.me/2014/03/03/%E8%97%8F%E8%BF%90%E7%94%A8-boxlayout-%E8%BF%9B%E8%A1%8C-swing-%E6%8E%A7%E4%BB%B6%E5%B8%83%E5%B1%80/</link>
      <pubDate>Mon, 03 Mar 2014 21:17:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/03/%E8%97%8F%E8%BF%90%E7%94%A8-boxlayout-%E8%BF%9B%E8%A1%8C-swing-%E6%8E%A7%E4%BB%B6%E5%B8%83%E5%B1%80/</guid>
      <description>&lt;p&gt;写的非常非常好的一个教程，感谢&lt;a href=&#34;http://www.ibm.com/developerworks/cn/java/j-lo-boxlayout/&#34;&gt;陈 怡平&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;引言&#34;&gt;引言&lt;/h2&gt;
&lt;p&gt;在用户使用 Java Swing 进行用户界面开发过程中，会碰到如何对 Java Swing 的控件进行布局的问题。Swing 的控件放置在容器 (Container) 中，容器就是能够容纳控件或者其它容器的类，容器的具体例子有 Frame、Panel 等等。容器需要定义一个布局管理器来对控件进行布局管理，Swing 当中提供的主要的布局管理器有 FlowLayout、BorderLayout、BoxLayout、GridLayout 和 GridBaglayout, 它们的主要特点如表 1 所示：&lt;/p&gt;
&lt;h5 id=&#34;表-1-swing-中的一些主要布局管理器的比较&#34;&gt;表 1. Swing 中的一些主要布局管理器的比较&lt;/h5&gt;
&lt;table summary=&#34;Swing 中的一些主要布局管理器的比较&#34; border=&#34;0&#34; cellspacing=&#34;0&#34; cellpadding=&#34;0&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;**布局管理器**&lt;/th&gt;
&lt;th&gt;**特点**&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FlowLayout&lt;/td&gt;
&lt;td&gt;把控件按照顺序一个接一个由左向右的水平放置在容器中，一行放不下，就放到下一行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BorderLayout&lt;/td&gt;
&lt;td&gt;将整个容器划分成东南西北中五个方位来放置控件，放置控件时需要指定控件放置的方位&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BoxLayout&lt;/td&gt;
&lt;td&gt;可以指定在容器中是否对控件进行水平或者垂直放置，比 FlowLayout 要更为灵活&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GridLayout&lt;/td&gt;
&lt;td&gt;将整个容器划分成一定的行和一定的列，可以指定控件放在某行某列上&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GridBagLayout&lt;/td&gt;
&lt;td&gt;是 Swing 当中最灵活也是最复杂的布局管理器，可对控件在容器中的位置进行比较灵活的调整&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
本文主要关注在 BoxLayout 布局管理器的使用上。我们首先对 BoxLayout 作一下介绍。
&lt;h2 id=&#34;boxlayout-介绍&#34;&gt;BoxLayout 介绍&lt;/h2&gt;
&lt;p&gt;如前所述，BoxLayout 可以把控件依次进行水平或者垂直排列布局，这是通过参数 X_AXIS、Y_AXIS 来决定的。X_AXIS 表示水平排列，而 Y_AXIS 表示垂直排列。BoxLayout 的构造函数有两个参数，一个参数定义使用该 BoxLayout 的容器，另一个参数是指定 BoxLayout 是采用水平还是垂直排列。下面是一个创建 BoxLayout 实例的例子：&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt; JPanel panel=new JPanel(); 
 BoxLayout layout=new BoxLayout(panel, BoxLayout.X_AXIS); 
 panel.setLayout(layoout);&lt;/pre&gt;
&lt;/div&gt;
在这个例子中，一个 BoxLayout 布局管理器的实例 layout 被创建，这个实例被设置为 panel 的布局管理器，该布局管理器采用了水平排列来排列控件。
&lt;p&gt;当 BoxLayout 进行布局时，它将所有控件依次按照控件的优先尺寸按照顺序的进行水平或者垂直放置，假如布局的整个水平或者垂直空间的尺寸不能放下所有控件，那么 BoxLayout 会试图调整各个控件的大小来填充整个布局的水平或者垂直空间。&lt;/p&gt;
&lt;p&gt;BoxLayout 往往和 Box 这个容器结合在一起使用，这么做的理由是，BoxLayout 是把控件以水平或者垂直的方向一个接一个的放置，如果要调整这些控件之间的空间，就会需要使用 Box 容器提供的透明的组件作为填充来填充控件之间的空间，从而达到调整控件之间的间隔空间的目的。Box 容器提供了 4 种透明的组件，分别是 rigid area、strut、glue、filler。Box 容器分别提供了不同的方法来创建这些组件。这四个组件的特点如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rigid area 是一种用户可以定义水平和垂直尺寸的透明组件；&lt;/li&gt;
&lt;li&gt;strut 与 rigid area 类似，但是用户只能定义一个方向的尺寸，即水平方向或者垂直方向，不能同时定义水平和垂直尺寸；&lt;/li&gt;
&lt;li&gt;当用户将 glue 放在两个控件之间时，它会尽可能的占据两个控件之间的多余空间，从而将两个控件挤到两边；&lt;/li&gt;
&lt;li&gt;Filler 是 Box 的内部类，它与 rigid area 相似，都可以指定水平或者垂直的尺寸，但是它可以设置最小，最大和优先尺寸。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;用-boxlayout-进行布局&#34;&gt;用 BoxLayout 进行布局&lt;/h2&gt;
&lt;p&gt;在了解了 BoxLayout 和 Box 容器的基本特点后，我们来看一下 BoxLayout 的优点，首先 BoxLayout 可以进行对控件进行垂直或者水平布局，同时 BoxLayout 使用起来较为简单，然而把它和 Box 容器相结合，就可以进行较为复杂的布局，达到同使用 GridBagLayout 的一样的效果，但是使用起来要简单方便多了。我们用按钮的布局作为例子来看怎样运用 BoxLayout 和 Box 容器进行布局：&lt;/p&gt;
&lt;h5 id=&#34;图-1-应用-boxlayout-进行按钮布局例子-1&#34;&gt;图 1. 应用 BoxLayout 进行按钮布局例子 1&lt;/h5&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/03/image003.jpg&#34;&gt;&lt;img alt=&#34;image003&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3f7f662b57a56e94f2e43da95973ee61d0735286.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>[译]使用Mockito简单mock入门</title>
      <link>http://blog.leaver.me/2014/03/01/%E8%AF%91%E4%BD%BF%E7%94%A8mockito%E7%AE%80%E5%8D%95mock%E5%85%A5%E9%97%A8/</link>
      <pubDate>Sat, 01 Mar 2014 10:57:33 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/01/%E8%AF%91%E4%BD%BF%E7%94%A8mockito%E7%AE%80%E5%8D%95mock%E5%85%A5%E9%97%A8/</guid>
      <description>&lt;p&gt;我们在写单元测试的时候，面临的一个挑战就是要测试的内容总是依赖于其他组件，要是我们还得先配置好其他组件，未免有点不如意，那么我们可以使用Mocks来代替那些依赖的组件&lt;/p&gt;
&lt;p&gt;本文问了展示这个过程，我会创建一个DAL，数据访问层，这是一个类，提供了一个通用的api来访问和修改数据仓库的数据，然后，我们要测试这个api，而不用配置连接某个本地的数据库，，或者一个远程的数据库，或者是一个文件系统，反正就是任何放数据的东西，DAL层的好处就是隔离开了数据访问和应用程序代码&lt;/p&gt;
&lt;p&gt;首先使用maven来创建一个工程&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;mvn archetype:generate -DgroupId=info.sanaulla -DartifactId=MockitoDemo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false&lt;/pre&gt;
&lt;p&gt;执行之后，本地生成MockitoDemo 文件夹，然后整个工程的目录结构与生成好了。&lt;/p&gt;
&lt;p&gt;然后，我们写这样一个model类，表示book类型&lt;/p&gt;
&lt;pre class=&#34;lang:java decode:true&#34;&gt;package info.sanaulla.models;

import java.util.List;

/**
* Model class for the book details.
*/
public class Book {

  private String isbn;
  private String title;
  private List&amp;lt;String&amp;gt; authors;
  private String publication;
  private Integer yearOfPublication;
  private Integer numberOfPages;
  private String image;

  public Book(String isbn,
              String title,
              List&amp;lt;String&amp;gt; authors,
              String publication,
              Integer yearOfPublication,
              Integer numberOfPages,
              String image){

    this.isbn = isbn;
    this.title: = title;
    this.authors = authors;
    this.publication = publication;
    this.yearOfPublication = yearOfPublication;
    this.numberOfPages = numberOfPages;
    this.image = image;

  }

  public String getIsbn() {
    return isbn;
  }

  public String getTitle() {
    return title;
  }

  public List&amp;lt;String&amp;gt; getAuthors() {
    return authors;
  }

  public String getPublication() {
    return publication;
  }

  public Integer getYearOfPublication() {
    return yearOfPublication;
  }

  public Integer getNumberOfPages() {
    return numberOfPages;
  }

  public String getImage() {
    return image;
  }
}&lt;/pre&gt;
&lt;p&gt;然后，我们访问Book model的DAL类会如下&lt;/p&gt;
&lt;pre class=&#34;lang:java decode:true&#34;&gt;package info.sanaulla.dal;

import info.sanaulla.models.Book;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* API layer for persisting and retrieving the Book objects.
*/
public class BookDAL {

  private static BookDAL bookDAL = new BookDAL();

  public List&amp;lt;Book&amp;gt; getAllBooks(){
      return Collections.EMPTY_LIST;
  }

  public Book getBook(String isbn){
      return null;
  }

  public String addBook(Book book){
      return book.getIsbn();
  }

  public String updateBook(Book book){
      return book.getIsbn();
  }

  public static BookDAL getInstance(){
      return bookDAL;
  }
}&lt;/pre&gt;
&lt;p&gt;DAL层现在还没啥功能，我们要通过TDD来测试，实际中，DAL可能和ORM来交互，也可能和数据库API交互，但是我们设计DAL的时候，不用关心&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用CSS3的自定义字体美化文字</title>
      <link>http://blog.leaver.me/2013/07/17/%E4%BD%BF%E7%94%A8css3%E7%9A%84%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AD%97%E4%BD%93%E7%BE%8E%E5%8C%96%E6%96%87%E5%AD%97/</link>
      <pubDate>Wed, 17 Jul 2013 14:45:45 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/07/17/%E4%BD%BF%E7%94%A8css3%E7%9A%84%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AD%97%E4%BD%93%E7%BE%8E%E5%8C%96%E6%96%87%E5%AD%97/</guid>
      <description>&lt;p&gt;之前看到一些设计师的主题的字体很美，下载下来发现使用了css3的自定义字体，可以用来显示服务器上的字体，非常方便，学习了一下&lt;/p&gt;
&lt;p&gt;1.首先得到字体&lt;/p&gt;
&lt;p&gt;这个方法很多，本机的字体，一些国外的免费网站，比如这个：&lt;a href=&#34;http://www.dafont.com/&#34;&gt;http://www.dafont.com&lt;/a&gt;，下载后的字体一般为ttf格式，ttf字体被很多浏览器支持，但是，IE不支持，为了兼容性，需要为IE单独设置字体文件，格式必须为eot，所以我们需要转换字体，使用在线工具，比如&lt;a href=&#34;http://www.kirsle.net/wizards/ttf2eot.cgi&#34;&gt;http://www.kirsle.net/wizards/ttf2eot.cgi&lt;/a&gt;，当然类似的网站有很多，根据个人爱好，随意。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;2.添加内容&lt;/p&gt;
&lt;p&gt;这里，我写一个简单的html文件，内容为&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;body&amp;gt;
&amp;lt;p class=&#34;test&#34;&amp;gt;bystander&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;&lt;/pre&gt;
&lt;p&gt;在没有设置customFont这个类的css之前，字体就是默认的字体了。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;3.设置css样式&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;@font-face
{
font-family:myFont;/*主流浏览器可用*/
src:url(&#34;PONCTUATION.ttf&#34;);
}
@font-face
{
font-family:myFont;/*兼容IE*/
src:url(&#34;PONCTUATION.eot&#34;);
}
.test
{
font-family:myFont;
font-size:40px;
}&lt;/pre&gt;
&lt;p&gt;显示效果就是这样的了&amp;hellip;只是用来演示的一个字体。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/38421_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/0aa0db5ed4bc986d61cfbb9e1e421a2226c94f9b.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;因为浏览器是要自动下载这个字体文件的，所以对于英文字体没啥问题，英文字体一般这个字体文件在100k左右，和一张图片比起来，基本算不是问题，但是对于中文字体，包一般在10M-20M左右，这样是不现实的，我的想法是，可以自己制作字体包，这样只需要满足常用的一些汉字就行了，大大减少包的大小，然后去找了一下，发现了&lt;a href=&#34;http://www.high-logic.com/font-editor/fontcreator.html&#34;&gt;http://www.high-logic.com/font-editor/fontcreator.html&lt;/a&gt;这个软件，是可以直接编辑字体包的，也可以创建字体包，有空了用来试试.&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#反射实现简单的插件系统</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>利用反射转换对象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/23/%E4%B8%8D%E8%A6%81%E5%8F%98%E6%88%90%E4%BD%A0%E8%AE%A8%E5%8E%8C%E7%9A%84%E4%BA%BA%E9%9D%A2%E7%9B%AE%E5%8F%AF%E6%86%8E/</link>
      <pubDate>Wed, 23 Jan 2013 16:37:54 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/23/%E4%B8%8D%E8%A6%81%E5%8F%98%E6%88%90%E4%BD%A0%E8%AE%A8%E5%8E%8C%E7%9A%84%E4%BA%BA%E9%9D%A2%E7%9B%AE%E5%8F%AF%E6%86%8E/</guid>
      <description>&lt;p&gt;本文来自&lt;a href=&#34;http://www.xjp.cc/2013-log/01/5379.html&#34;&gt;xjp的碎碎念&lt;/a&gt;，我很喜欢的一个博主。博客已被伟大的GFW屏蔽。和文章的主题类似，我有时候会在G+上会纠正一些人的谣言，并且给出澄清，可是，往往效果不大。我的态度很简单，你要反对一样东西，请你不要是那样的东西。或用那样的东西去反对。不要为任何主义所迷惑，你要做好一个人。&lt;/p&gt;
&lt;p&gt;今天看到一篇来自《新京报》的报道，称时事评论员&lt;a href=&#34;http://weiba.weibo.com/10015/t/zfCUGgdhj&#34;&gt;@周筱赟爆料&lt;/a&gt;称，根据铁道部的两份采购合同显示，推测铁道部12306订票网站实际投入已经超过5亿元，而不是之前曾披露的3.2亿元。&lt;/p&gt;
&lt;p&gt;首先我很赞同周筱赟所做的事情，在国内目前民众获取信息渠道有限的情况下，有这样的热心人士去披露政府部门行政行为中值得讨论的部分，对于整个社会的公正与透明都有极大的推动作用。&lt;/p&gt;
&lt;p&gt;但我注意的是另一群人，他们典型的回复是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1、花5个多亿做成这么垃圾的网站，铁道部公然贪污多少钱？臭不要脸的！二逼的网站和系统归功于傻逼造就！&lt;/p&gt;
&lt;p&gt;2、卧槽，里面有4.5亿是贪污款吧&lt;/p&gt;
&lt;p&gt;3、习总说反腐，最大的蛀虫在这里，敢反否？&lt;/p&gt;
&lt;p&gt;4、3亿建站为什么这些年一直没有工商部去追查12306的贪污问题。你懂我懂大家懂。&lt;/p&gt;
&lt;p&gt;5、中央纪委、监察部和各级纪检监察机关要加大检查监督力度，执好纪、问好责、把好关。&lt;/p&gt;
&lt;p&gt;6、太极集团是做医药的呀，怎么也搞起软件来了。我想说，有没经验都不要紧，要紧的是有钱。咱就撒都能做！&lt;/p&gt;
&lt;p&gt;7、五亿······· 用了个500的模版 月薪5000水平的制作团队&lt;/p&gt;
&lt;p&gt;8、三億各單位部門宣傳費，一億三公支出，五千萬采購合同草擬費用，四千萬給媒體掩口費, 九百九十萬信息產業部備案費用，最後十萬才是網站制作費用… 這五億基本上都使對了地方，沒有錯啊!
其它的评论都是诸如此类，某一些理性的评论都被深埋其中。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我不是铁道部、太极的任何一方，我不能拍着胸脯说这些问题一定不存在，但真正让我恐惧的是，有大量网友没有认真去研究文章的内容与事实，只是单纯下意识地做出了判断，然后开喷。&lt;/p&gt;
&lt;p&gt;我们仔细去看我们讨厌的那些五毛与政府宣传部门，他们的日常做法都是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1、戴帽子&lt;/p&gt;
&lt;p&gt;2、站在道德高度，说正确的废话&lt;/p&gt;
&lt;p&gt;3、自说自话，完全不管别人在说什么&lt;/p&gt;
&lt;p&gt;4、预设立场&lt;/p&gt;
&lt;p&gt;5、我永远是对的，反对我的都是错的&lt;/p&gt;
&lt;p&gt;6、你们站在人民的对立面
然后有一个微博网友在评论里跟我说，他只需要一万元就能够搞定12306的网站外包开发。听到这样的话，我不由地一阵颤抖，如果这话来自一名所谓的业内人士，那我真的不知道应该怎么说了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;引用某网友的评论：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;从专业角度来说，投入不算多，只是透明度不够，民众才疑惑！全国各地还需要再多些大型机房，才能满足高峰期分流排队和并发操作！
我的看法是，不否认铁道部的开发、架构设计存在一定问题，如果没有实际的大型系统设计经验的团队，可能会造成很多理论与实际脱节问题，事实上今年的12306已经比去年好太多了，他们也在吸取教训。当然，我也赞成他们向互联网公司取经，吸收现有经验。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;建议大家不要单纯喷，5亿这个数字可能略高，但比起数千万的静态网站好多了，至于具体审计是国家审计局的事情，我支持惩处贪腐。做一个覆盖数千万用户，承受刷票插件5秒一次的并发，服务器、带宽、配套都是成本。而售票数字化几乎是必经之路，铁道部走出这一步是好的，买不到票有基础运力的问题，跟网络售票无关。&lt;/p&gt;
&lt;p&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#)</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>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>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>获取操作系统版本信息</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>依赖倒置原则和依赖注入模式</title>
      <link>http://blog.leaver.me/2012/11/21/%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99%E5%92%8C%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%A8%A1%E5%BC%8F/</link>
      <pubDate>Wed, 21 Nov 2012 13:46:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/11/21/%E4%BE%9D%E8%B5%96%E5%80%92%E7%BD%AE%E5%8E%9F%E5%88%99%E5%92%8C%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%A8%A1%E5%BC%8F/</guid>
      <description>&lt;p&gt;昨天读完了程杰的《大话设计模式》。。收获颇丰。深刻感到了设计模式的伟大。。对面向接口的编程也理解了不少。刚好看到codeproject上一篇将依赖倒置的。讲到了依赖注入的方式。仔细读了一下。翻译一遍加深认识。&lt;/p&gt;
&lt;p&gt;高耦合的代码随着项目复杂性的不断增加，最终会变成一碗碗的意大利面条啦。。二者通常是软件设计上的问题，如果一个类对另一个类的实现了解太多。当该类改变的时候会引起更多的改变。这违反了依赖倒置原则&lt;/p&gt;
&lt;p&gt;而松耦合的代码设计优良。随着时间流逝，代码复杂两增大，松耦合的好处会变得更加清晰，依赖注入模式是实现松耦合的一个好的办法，本文介绍在没有依赖注入容器的情况下实现依赖注入&lt;/p&gt;
&lt;p&gt;GoF说了，依赖倒置的原则：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;高层模块不应依赖于低层模块，他们都应该依赖于抽象
抽象不依赖细节，细节依赖抽象&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;刚开始写依赖倒置比较难，随着经验增长会有所改善，通过使高层模块依赖于抽象，依赖倒置成功解耦，依赖注入模式是该原则的一个实现。&lt;/p&gt;
&lt;p&gt;通常我们写出如下的代码：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;public class Email
{
    public void SendEmail()
    {
        // code
    }
}

public class Notification
{
    private Email _email;
    public Notification()
    {
        _email = new Email();
    }

    public void PromotionalNotification()
    {
        _email.SendEmail();
    }
}
&lt;/pre&gt; 
&lt;p&gt;Notification类依赖Email类，这违反了DIP，而且当我们要发送短信/保存到数据库的时候，我们还要改变Notification类。
我们使用抽象类/接口解耦&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;public interface IMessageService
{
    void SendMessage();
}
public class Email : IMessageService
{
    public void SendMessage()
    {
        // code
    }
}
public class Notification
{
    private IMessageService _iMessageService;

    public Notification()
    {
        _iMessageService = new Email();
    }
    public void PromotionalNotification()
    {
        _iMessageService.SendMessage();
    }
}
&lt;/pre&gt; 
&lt;p&gt;IMessageService 是一个接口，而Notification 类只要调用接口的方法/属性就可以了
同时，我们把Email对象的构造移到Notification 类外面去。&lt;/p&gt;
&lt;p&gt;依赖注入模式可以实现。通常有三种方式&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;strong&gt;构造器注入&lt;/strong&gt;
最普遍的方式，当一个类需要另一个类的依赖的时候，我们通过构造函数来提供，现在我们这样写&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;public class Notification
{
    private IMessageService _iMessageService;

    public Notification(IMessageService _messageService)
    {
        this._iMessageService = _messageService;
    }
    public void PromotionalNotification()
    {
        _iMessageService.SendMessage();
    }
}&lt;/pre&gt; 
&lt;p&gt;有几个好处：1.构造函数实现很简单，Notification类需要知道的很少。想要创建Notification实例的时候看构造函数就可以知道需要什么信息了。因此实现了松耦合。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;属性注入&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;属性注入/setter注入比较不常见，当依赖可有可无的时候很有用。我们暴露一个可写的属性，允许客户提供不同的依赖实现，比如这样。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;public class Notification
{
    public IMessageService MessageService
    {
        get;
        set;
    }
    public void PromotionalNotification()
    {

        if (MessageService == null)
        {
            // some error message
        }
        else
        {
            MessageService.SendMessage();

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

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

//...

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

worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new System.ComponentModel.DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(
worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
worker_RunWorkerCompleted);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
BackgroundWorker worker;
}&lt;/pre&gt;
&lt;p&gt;我们必须把DoWork事件暴露给用户。我添加了一个委托。这样。我可以很容易的访问窗体成员&lt;/p&gt;</description>
    </item>
    <item>
      <title>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>《商务智能与数据挖掘-谢邦昌》第三章读书笔记</title>
      <link>http://blog.leaver.me/2012/09/21/%E5%95%86%E5%8A%A1%E6%99%BA%E8%83%BD%E4%B8%8E%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98-%E8%B0%A2%E9%82%A6%E6%98%8C%E7%AC%AC%E4%B8%89%E7%AB%A0%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 21 Sep 2012 08:16:06 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/21/%E5%95%86%E5%8A%A1%E6%99%BA%E8%83%BD%E4%B8%8E%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98-%E8%B0%A2%E9%82%A6%E6%98%8C%E7%AC%AC%E4%B8%89%E7%AB%A0%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;&lt;strong&gt;3.数据挖掘&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.1定义&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　数据挖掘是指找寻隐藏在数据中的信息，如趋势。特征及相关性的过程。也就是从数据中发掘信息或知识（Knowledge Discovery in Database）。也有人称之为数据考古学。。记住，它不是一个无所不能的软件或是一种技术，他是一种结合数种专业技术的应用。数据挖掘工具从数据中发掘出个各种假设。但是并不帮你查证。确认这些假设。也不帮你判断这些假设是否有价值。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.2数据挖掘的功能&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　1.分类（Classification），按照分析对象的属性进行分门别类加以定义。建立类组（Class）。例如划分银行信用申请者的风险属性，使用的技术有决策树（Decision Tree），记忆基础推理（memory-based reasoning）&lt;/p&gt;
&lt;p&gt;　　2.估计（Estimation），根据既有连续性数值的相关属性数据。以获知某一属性未知值。。例如按照信用申请者的教育程度，行为估计其的信用卡缴费量。使用的技术包括相关分析，回归分析及神经网络算法。&lt;/p&gt;
&lt;p&gt;　　3.预测（Prediction）根据对象属性的过去观察值来估计该属性未来值。比如根据顾客过去刷卡消费量来预测其未来刷卡消费量。使用的技术包括回归分析，时间序列分析，神经网络。&lt;/p&gt;
&lt;p&gt;　　4.关联分组（Affinity Grouping）从所有对象决定哪些相关对象放在一起销售。比如那个啤酒和尿不湿。。在客户营销系统上，此功能用来确定交叉销售。。&lt;/p&gt;
&lt;p&gt;　　5.聚类（Clustering)，将异质总体中区分为特征相近的同质类组。目的是将组和组之间的差异辨识出来。并对个别组内相似样本进行挑选。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.3数据挖掘的步骤&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　1.理解数据和数据所代表的含义（Data Understanding）&lt;/p&gt;
&lt;p&gt;　　2.获取相关知识和技术（Domain Knowledge Acquisition）&lt;/p&gt;
&lt;p&gt;　　3.整合和检查数据（Integration and Checking）&lt;/p&gt;
&lt;p&gt;　　4.去除错误或不一致的数据（Data Cleaning)&lt;/p&gt;
&lt;p&gt;　　5.建模与假设（Model and Hypothesis Development）&lt;/p&gt;
&lt;p&gt;　　6.数据挖掘运行（Running)&lt;/p&gt;
&lt;p&gt;　　7.测试与验证所挖掘的数据（Testing and Verification）&lt;/p&gt;
&lt;p&gt;　　8.解释与使用数据（Interpretation and Use）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.4数据挖掘建模的标准CRISP-DM&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　CRISP-DM模型强调完整的数据挖掘过程，不能只针对数据整理、数据呈现、数据分析以及构建模型，还需要对企业的需求问题进行了解，同时，后期对模型进行评价和模型的延伸应用，也是一个完整的数据挖掘过程不可或缺的要素。&lt;/p&gt;
&lt;p&gt;　　CRISP-DM分为六个阶段（phase）和四个层次（level），分别简介如下：&lt;/p&gt;
&lt;p&gt;　　1. 商业理解（Business Understanding）&lt;/p&gt;
&lt;p&gt;　　本阶段主要的工作是要针对企业问题以及企业需求进行了解确认，针对不同的需求做深入的了解，将其转换成数据挖掘的问题，并拟定初步构想。在此阶段中，需要与企业进行讨论，以确定分析者可以对于问题有非常清楚的了解，只有这样才可以正确地针对问题拟定分析过程。&lt;/p&gt;
&lt;p&gt;　　2. 数据理解（Data Understanding）&lt;/p&gt;
&lt;p&gt;　　这部分包含建立数据库与分析数据。在此阶段必须收集初步数据，然后了解数据的内涵与特性，选择要进行数据挖掘所必须的数据，然后进行数据整理及评估数据的质量，必要时再将分属不同数据库的数据加以合并及整合。数据库建立完成后再进行数据分析，找出影响预测最大的数据。&lt;/p&gt;
&lt;p&gt;　　3. 数据预处理（Data Preparation）&lt;/p&gt;
&lt;p&gt;　　此步骤和第二步数据理解是数据处理的核心，这是建立模型之前的最后一步数据准备工作。数据预处理任务很可能要执行多次，并且没有任何规定的顺序。&lt;/p&gt;
&lt;p&gt;　　4. 建立模型（Modeling）&lt;/p&gt;
&lt;p&gt;　　针对已预处理过的数据加以分析，配合各种技术方法加以应用，针对既有数据建构出模型，替企业解决问题；面对同一种问题，会有多种可以使用的分析技术，但是每一种分析技术却对数据有些限制及要求，因此需要回到数据前置处理的阶段，来重新转换需要的变量数据加以分析。&lt;/p&gt;
&lt;p&gt;　　5. 评价和解释（Evaluation）&lt;/p&gt;
&lt;p&gt;　　从数据分析的观点看，在开始进入这个阶段时已经建立了看似是高质量的模型，但在实际应用中，随着应用数据的不同，模型的准确率肯定会变化。这里，一个关键的目的是确定是否有某些重要的商业问题还没有充分地考虑。在这个阶段的结尾，应该获得对数据挖掘结果的判定。&lt;/p&gt;
&lt;p&gt;　　6. 实施（Deployment）&lt;/p&gt;
&lt;p&gt;　　一般而言，创建模型完成并不意味着项目结束。模型建立并经验证之后，可以有两种主要的使用方法。一种是提供给决策人员做参考，由他察看和分析这个模型之后提出行动方案建议；另一种是把此模型应用到不同的数据集上。此外，在应用了模型之后，当然还要不断监控它的效果。&lt;/p&gt;
&lt;p&gt;　　四个层次分别为阶段（phase）、一般任务（generic task）、专项任务（specialized task）、流程实例（process instance）。每个阶段由若干一般任务组成，每个一般任务又实施若干专项任务，每个专项任务由若干流程实例来完成。其中，上两层独立于具体数据挖掘方法，即是一般数据挖掘项目均需实施的步骤（What to do？），这两层的任务将结合具体数据挖掘项目的“上下文”（context）映像到下两层的具体任务和过程。所谓项目的“上下文”是指项目开发中密切相关、需要综合考虑的一些关键问题，如应用领域、数据挖掘问题类型、技术难点、工具及其提供的技术等。&lt;/p&gt;</description>
    </item>
    <item>
      <title>《商务智能与数据挖掘-谢邦昌》第二章读书笔记</title>
      <link>http://blog.leaver.me/2012/09/20/%E5%95%86%E5%8A%A1%E6%99%BA%E8%83%BD%E4%B8%8E%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98-%E8%B0%A2%E9%82%A6%E6%98%8C%E7%AC%AC%E4%BA%8C%E7%AB%A0%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Thu, 20 Sep 2012 08:47:36 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/20/%E5%95%86%E5%8A%A1%E6%99%BA%E8%83%BD%E4%B8%8E%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98-%E8%B0%A2%E9%82%A6%E6%98%8C%E7%AC%AC%E4%BA%8C%E7%AB%A0%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;&lt;strong&gt;2.数据仓库&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　数据仓库名字上来看是很好理解的。他与传统的数据库的不同在于。传统的数据库是未经整理后的一大堆数据集。而数据仓库是从数据库中萃取出来。经过整理，规划，建构而成的一个有系统的数据库的子集合。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.1数据仓库特点：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　数据仓库的四个特点。&lt;/p&gt;
&lt;p&gt;　　1.面向主题（Subject Orient）。数据建立的着重点就是在于以重要的主题组件作为核心。作为建构的方向。数据需求者只要把谣言觉得相关主题数据，从数据库中攫取，整合之后就可以做研究之用。&lt;/p&gt;
&lt;p&gt;　　2.整合性（Integrated）各应用系统的数据需经过整合。以便利执行相关分析操作&lt;/p&gt;
&lt;p&gt;　　3.长期性（Time Variance） 为了执行趋势的分析。数据仓库系统需保留1-10年的历史数据。这与数据库为日常性的数据有所不同。&lt;/p&gt;
&lt;p&gt;　　4.稳定性（Non-Volatile）数据库可以被随时修改，但数据仓库基本上不会大动。只有内部人员会定期修改。但频率不会太多。也不允许用户做更新的动作。&lt;/p&gt;
&lt;p&gt;　　由于以上的几个特点。数据仓库必须通过一连串的程序才可建立。而不是说即买即用。。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.2数据仓库架构&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　数据源-&amp;gt;整体数据仓库-&amp;gt;部门性数据仓库-&amp;gt;查询工具-&amp;gt;终端用户&lt;/p&gt;
&lt;p&gt;　　数据仓库的建设过程：&lt;/p&gt;
&lt;p&gt;　　专业顾问通过与企业进行需求访谈，建立数据仓库的model，然后将企业内各种数据整合到数据库中，并建立前端分析数据的工具以及管理工具，这样的过程即为建立数据仓库的基本过程。&lt;/p&gt;
&lt;p&gt;　　1.设计（Design） 即数据仓库的数据Model设计，这部分是最重要的，若Model设计的不够周全或布里希那个，不管之后的报表设计如何精美，也可能跑出错误的信息。这也是需要有经验的专业顾问建立数据仓库的一个重要原因。&lt;/p&gt;
&lt;p&gt;　　2.整合（Integrate）即数据的整合转换过程，包含数据解释（Data Extraction） ，数据转换（Data Transformation）数据清理（Data Cleaning），数据加载（Data Loading）将各种来源的数据整理，转换并加载数据仓库中，程序编写较为繁杂，自动化处理困难，经常需要人工参与操作，大约占掉该项目60-70%的时间和人力。&lt;/p&gt;
&lt;p&gt;　　3.可视化（Visualize）即前端呈现给用户看的形式，例如数据挖掘（Data Mining） 即OLAP工具，用以呈现分析过的数据形式。&lt;/p&gt;
&lt;p&gt;　　4.调度（Administration）为管理的工具。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.3建立数据仓库的原因和目的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　提高企业的竞争能力，降低成本，提高客户满意度。创造利润。&lt;/p&gt;</description>
    </item>
    <item>
      <title>面试体验：Google 篇</title>
      <link>http://blog.leaver.me/2012/08/11/%E9%9D%A2%E8%AF%95%E4%BD%93%E9%AA%8Cgoogle-%E7%AF%87/</link>
      <pubDate>Sat, 11 Aug 2012 14:30:10 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/08/11/%E9%9D%A2%E8%AF%95%E4%BD%93%E9%AA%8Cgoogle-%E7%AF%87/</guid>
      <description>&lt;p&gt;　　尝试在&lt;a href=&#34;http://www.cnblogs.com/cathsfz/archive/2012/08/08/google-interview-experience.html&#34;&gt;自己的博客&lt;/a&gt;上搜索点东西，结果发现 4 年多以前还在博客上写过一系列的 recruiting events，把大四时候参加过的各种笔试面试都记录下来了。我从去年准备离开百度开始，到现在总过面试过 4 家公司：Google、Microsoft、Yahoo、Facebook，原本去年也想把面试经验写一写的，结果一拖就拖到现在。我不想写面试经验，因为我个人不喜欢漏题和背题的做法。我自己作为面试官，知道要设计出来一道好用的题目有多难，所以我希望面试者都是如实表现自己解题能力的。我更喜欢写面试体验，就是在整个面试过程中一家公司给人的印象是怎样的，HR 和面试官是否专业，能否让人信服这是一家值得长期工作的公司。&lt;/p&gt;
&lt;p&gt;　　我想写的第一家公司是 Google，因为它是我在想要离开百度时第一家联系到我的公司。2010 年 12 月底的某一天早上，我突然感觉到我应该离开百度，因为如果这个时候已经没有勇气离开这家公司了，很可能就不会再想要离开了。当天中午在百度大厦西餐厅吃午饭，接到一个 Google 上海 HR 的电话，问我有没有兴趣去面试，我想既然你打电话来的时机那么好，我就答应你去面试吧。（在那一天之前，我对猎头的标准回复是「有美国或者香港的职位吗？」）她问我将来希望在北京还是上海工作，当时我对北京的厌恶程度还没有现在那么高，同时觉得搬家到上海又比较麻烦，于是就说在北京，接着我就变成跟北京 HR 沟通了。&lt;/p&gt;
&lt;p&gt;　　Google 的 HR 会负责做两件简单得不需要面试官做的事情，这能够很好的提高招聘流程的效率。第一件是确认你能够适应工作环境中的英语，为此 HR 要我用英语跟她对话两三分钟，主要就是让我说说工作经验和其中的亮点。习惯在私企工作的人不要以为外企对英语的要求很高，其实大多数长期在中国工作的人说话或者发邮件都会很 Chinglish 啦，所以关键是要敢于用英语进行沟通。&lt;/p&gt;
&lt;p&gt;　　然后 HR 发了一个 Codility 的地址给我，让我有空抽时间去做题。一个小时 3 道难度相当于 OI 基础题的题目，平均 20 分钟一道。最简单的题目一看就知道是 O(n) 能解决的，最复杂的题目看上去是 O(n^2) 但想一下就能优化为 O(n log n)。对于有算法训练背景的人来说，这样的题目会让人感觉到很有把握。对于没有经受过算法训练的人来说，掉进陷阱里是很容易的。很可能没有把 O(n^2) 优化为 O(n log n)，结果超时；可能没仔细看题目说明的数值取值范围，某些变量选错了数值类型，结果溢出。考虑到 Google 重视算法的程度，再加上 Google 中国面试的额外难度，算法训练还是很必要的。&lt;/p&gt;
&lt;p&gt;　　在我通过 Codility 测试后，HR 问我了对题目难度的反馈，然后约了一轮电话面试，并且告知面试主要围绕算法、数据结构、系统设计、编码来进行。Google 面试的格式都很固定，45 分钟内期望你能做出 3 道题来。这 3 道题最起码要能把人人都能想出来的「笨办法」用代码写出来，否则会让面试官感到不满意。如果有些题目能够比较快地做出来，面试官就会让你优化。就算你第一次给出的答案已经是业界已知最优解，面试官都还是会让你优化，因为谁也不知道有没有人能在面试过程中突然爆发，想出一些过去没人想到过的解法。如果面试官心中已有优化的方案，在你想不出优化方案时他可能会给你提供一些提示。&lt;/p&gt;
&lt;p&gt;　　一轮电话面试后，HR 就开始约到 Google 办公室的面试了。第一次约了下午 3 轮面试，还是那个很固定的格式：每轮面试 45 分钟，两轮间隔 15 分钟。整个面试流程让人感觉到很人性化：在 Google 签到后，HR 会先带你去 kitchen 拿点吃的喝的，然后把你带到面试所用的会议室。多轮面试的话，HR 中间还会来问一下你要不要去洗手间，或者多拿两瓶水。面试完毕后 HR 会来问你感觉如何，同时也会让你知道面试官的初步反馈是否跟你的感觉一致。我在 3 轮面试中有一轮感觉不太好，因为面试官只给了 2 道题，并且我最终都没办法解出来，HR 也确认了就是这一轮的反馈不好。&lt;/p&gt;
&lt;p&gt;　　此外，Google 的招聘流程还让人感觉到很有效率。作为面试官，我也知道自己写面试反馈有多喜欢拖延，而且公司填写面试反馈的系统越不人性化我就越想要拖延，然而公司内部系统做得人性化的又实在罕见。Google 的面试基本上隔天就有结果，然后 HR 就会约下一轮的面试。因为我在百度的时候每周哪个时间没有会议是很确定的，所以我总是选择下周同一个时间段来面试。在经过总共 4 轮面试后，HR 说因为前面有一轮的面试官反馈不好，所以希望再加一轮面试。因为前面反馈不好的面试官比较 senior，所以这次找了一位同样 senior 的面试官来面试，于是我又去了一次 Google 办公室。&lt;/p&gt;
&lt;p&gt;　　完成 5 轮面试后，HR 把材料提交给 Google 的北京招聘委员会，结果没有通过。HR 说，因为 Google 都是按照后端工程师的标准来招聘，看重算法和数据结构，前端工程师要通过不容易。因为 Google 没有专门的前端工程师，只有一个软件工程师职位，所以所有人还是必须按照一个标准来衡量。她问我如果找到专门需要前端工程师的团队，并且需要额外再面试的话，我是否感兴趣。当时 Google 是我的第一选择，我当然说感兴趣啦。&lt;/p&gt;
&lt;p&gt;　　后来 HR 跟我说，她帮忙问过 Google Maps，可惜对方说不要专才只要通才。又过了几个星期，HR 发现 IME 需要专门做前端的人，于是帮我再约了一轮面试。这轮面试是在 Google 办公室做的，但实际上是视频会议，因为面试官在美国。（不确定面试官是在美国出差，还是美籍华人。）面试过程跟电话面试类似，用 Google Docs 写代码，比电话面试要好的是说话时能够见到人。&lt;/p&gt;
&lt;p&gt;　　这一轮面试结束后，我的材料再次进入 Google 的北京招聘委员会。HR 说这次专门找了对前端有经验的人来审阅我的材料，结果顺利通过了。接着 HR 问我要了一大堆的补充材料，包括高考成绩和 GPA（连同成绩单），还包括当前薪酬和竞争对手的 offer（我当时有 Yahoo 的 offer），甚至包括过去的获奖和晋升经历。所有这些材料都会发往 Google 美国总部审阅，具体流程 HR 没有细说，但看 Don Dodge 的文章可以了解一些。最后我被 Google 美国总部给拒绝了，然后 HR 还是一如既往地及时沟通，并且安慰了我几句。&lt;/p&gt;</description>
    </item>
    <item>
      <title>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>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/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>移动设备电池白皮书</title>
      <link>http://blog.leaver.me/2012/07/07/%E7%A7%BB%E5%8A%A8%E8%AE%BE%E5%A4%87%E7%94%B5%E6%B1%A0%E7%99%BD%E7%9A%AE%E4%B9%A6/</link>
      <pubDate>Sat, 07 Jul 2012 18:47:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/07/%E7%A7%BB%E5%8A%A8%E8%AE%BE%E5%A4%87%E7%94%B5%E6%B1%A0%E7%99%BD%E7%9A%AE%E4%B9%A6/</guid>
      <description>&lt;p&gt;资源来自：&lt;a href=&#34;http://www.ijinshan.com/dcys/baipishu/&#34;&gt;金山网络&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　　我比较认真的读完了这本小册子，确实收获还是蛮大的。前几天有个朋友问我电池的事情，我以前看过电池的一些保养的。当时就知道锂电池是首次使用是不需要进行12小时充电的。。看到这本小册子的时候，证实了我没乱讲哈。。&lt;/p&gt;
&lt;p&gt;　　　然后里面还说道一个就是很多人不相信软件能够保养电池。其实真的是可以的。。理由不赘述。你可以自己读一读。。我自己感觉对普通用户很有用的是30页的那一节。讲到的问题有；&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;li&gt;不管怎么用待机时间都一样？&lt;/li&gt;
&lt;li&gt;手机还有一半电量的时候不必担心？&lt;/li&gt;
&lt;li&gt;新电池前3次需充满12小时？&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;充电不饱和会伤害电池吗？&lt;/li&gt;
&lt;li&gt;iPhone和iPad的充电器可以混用吗？&lt;/li&gt;
&lt;li&gt;经常把电用光再充对电池好不好？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;书籍下载：[移动设备电池使用白皮书](&lt;a href=&#34;http://115.com/file/ancame68#&#34;&gt;http://115.com/file/ancame68#&lt;/a&gt; 移动设备电池白皮书.pdf)&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>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>SASS用法指南</title>
      <link>http://blog.leaver.me/2012/06/19/sass%E7%94%A8%E6%B3%95%E6%8C%87%E5%8D%97/</link>
      <pubDate>Tue, 19 Jun 2012 17:03:49 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/19/sass%E7%94%A8%E6%B3%95%E6%8C%87%E5%8D%97/</guid>
      <description>&lt;div&gt;
&lt;p&gt;作者： &lt;a href=&#34;http://www.ruanyifeng.com/&#34;&gt;阮一峰&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;日期： &lt;a href=&#34;http://www.ruanyifeng.com/blog/2012/06/&#34;&gt;2012年6月19日&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;main-content&#34;&gt;
&lt;div&gt;
&lt;p&gt;学过&lt;a href=&#34;http://zh.wikipedia.org/wiki/%E5%B1%82%E5%8F%A0%E6%A0%B7%E5%BC%8F%E8%A1%A8&#34;&gt;CSS&lt;/a&gt;的人都知道，它不是一种编程语言。&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;more&#34;&gt;
&lt;p&gt;你可以用它开发网页样式，但是没法用它编程。也就是说，CSS基本上是设计师的工具，不是程序员的工具。在程序员眼里，CSS是一件很麻烦的东西。它没有变量，也没有条件语句，只是一行行单纯的描述，写起来相当费事。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/24063303e3abc5d5089bc58bdba65c550be0f8cb.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;很自然地，有人就开始为CSS加入编程元素，这被叫做&lt;a href=&#34;http://www.catswhocode.com/blog/8-css-preprocessors-to-speed-up-development-time&#34;&gt;&amp;ldquo;CSS预处理器&amp;rdquo;&lt;/a&gt;（css preprocessor）。它的基本思想是，用一种专门的编程语言，进行网页样式设计，然后再编译成正常的CSS文件。&lt;/p&gt;
&lt;p&gt;各种&amp;quot;CSS预处理器&amp;quot;之中，我自己最喜欢&lt;a href=&#34;http://sass-lang.com/&#34;&gt;SASS&lt;/a&gt;，觉得它有很多优点，打算以后都用它来写CSS。下面是我整理的用法总结，供自己开发时参考，相信对其他人也有用。&lt;/p&gt;
&lt;p&gt;============================================&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SASS用法指南&lt;/strong&gt;&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/c00b9e9a6c97811cb70a4f18ec85976f493eb3e7.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、什么是SASS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://sass-lang.com/&#34;&gt;SASS&lt;/a&gt;是一种CSS的开发工具，提供了许多便利的写法，大大节省了设计者的时间，使得CSS的开发，变得简单和可维护。&lt;/p&gt;
&lt;p&gt;本文总结了SASS的主要用法。我的目标是，有了这篇文章，日常的一般使用就不需要去看&lt;a href=&#34;http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html&#34;&gt;官方文档&lt;/a&gt;了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二、安装和使用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.1 安装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS是Ruby语言写的，但是两者的语法没有关系。不懂Ruby，照样使用。只是必须先&lt;a href=&#34;http://www.ruby-lang.org/zh_cn/downloads/&#34;&gt;安装Ruby&lt;/a&gt;，然后再安装SASS。&lt;/p&gt;
&lt;p&gt;假定你已经安装好了Ruby，接着在命令行输入下面的命令：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;gem install sass
然后，就可以使用了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;2.2 使用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS文件就是普通的文本文件，里面可以直接使用CSS语法。文件后缀名是.scss，意思为Sassy CSS。&lt;/p&gt;
&lt;p&gt;下面的命令，可以在屏幕上显示.scss文件转化的css代码。（假设文件名为test。）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;sass test.scss
如果要将显示结果保存成文件，后面再跟一个.css文件名。
sass test.scss test.css
SASS提供四个编译风格的选项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;nested：嵌套缩进的css代码，它是默认值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;expanded：没有缩进的、扩展的css代码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compact：简洁格式的css代码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compressed：压缩后的css代码。
生产环境当中，一般使用最后一个选项。
sass &amp;ndash;style compressed test.sass test.css
SASS的官方网站，提供了一个&lt;a href=&#34;http://sass-lang.com/try.html&#34;&gt;在线转换器&lt;/a&gt;。你可以在那里，试运行下面的各种例子。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;三、基本用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.1 变量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS允许使用变量，所有变量以$开头。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$blue : #1875e7;&lt;/p&gt;
&lt;p&gt;div {
color : $blue;
}
如果变量需要镶嵌在字符串之中，就必须需要写在#{}之中。
$side : left;&lt;/p&gt;
&lt;p&gt;.rounded {
border-#{$side}-radius: 5px;
}
&lt;strong&gt;3.2 计算功能&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SASS允许在代码中使用算式：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;body {
margin: (14px/2);
top: 50px + 100px;
right: $var * 10%;
}
&lt;strong&gt;3.3 嵌套&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SASS允许选择器嵌套。比如，下面的CSS代码：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;div h1 {
color : red;
}
可以写成：
div {
hi {
color:red;
}
}
属性也可以嵌套：
p {
border-color: red;
}
可以写成：
p {
border: {
color: red;
}
}
注意，border后面必须加上冒号。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;3.4 注释&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS共有两种注释风格。&lt;/p&gt;
&lt;p&gt;标准的CSS注释 /* comment */ ，会保留到编译后的文件。&lt;/p&gt;
&lt;p&gt;单行注释 // comment，只保留在SASS源文件中，编译后被省略。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;四、代码的重用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.1 继承&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS允许一个选择器，继承另一个选择器。比如，现有class1：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;.class1 {
border: 1px solid #ddd;
}
class2要继承class1，就要使用@extend命令：
.class2 {
@extend .class1;
font-size:120%;
}
&lt;strong&gt;4.2 Mixin&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
