<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_imfunny</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/85566/rss</id><updated>2012-05-14T13:22:56Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/85566/rss"/><entry><id>http://www.cnblogs.com/imfunny/archive/2012/05/14/2500431.html</id><title type="text">博问本周活跃用户第一了</title><summary type="text">赢得博问本周活跃用户第一了。留图纪念一下下。。</summary><published>2012-05-14T13:10:00Z</published><updated>2012-05-14T13:10:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2012/05/14/2500431.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2012/05/14/2500431.html"/><content type="html">&lt;p&gt;经过一天时间锲而不舍的回答问题，终于赢得了博问本周活跃用户第一。特留图纪念啊。&lt;/p&gt;&lt;p&gt;开心的泪奔啊。哈哈。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/187666/2012051421060394.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/187666/2012051421072698.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/187666/2012051421081234.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;真Happy啊。&lt;/p&gt;&lt;p&gt;现在宁可回答问题，都不愿意写无聊的博客了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2500431.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2012/05/14/2500431.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2012/03/28/2420800.html</id><title type="text">.NET内存管理、垃圾回收(转载)</title><summary type="text">关于GC的一些难得资料</summary><published>2012-03-28T02:33:00Z</published><updated>2012-03-28T02:33:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2012/03/28/2420800.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2012/03/28/2420800.html"/><content type="html">&lt;p&gt;原文的地址在&lt;a href="http://www.cnblogs.com/riccc/archive/2009/09/01/dotnet-memory-management-and-garbage-collection.html" target="_blank"&gt;这里&lt;/a&gt;。备份下已备丢失用。&lt;/p&gt;&lt;p&gt;&lt;strong style="font-size: 18pt;"&gt;1. Stack和Heap&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp; 每个线程对应一个stack，线程创建的时候CLR为其创建这个stack，stack主要作用是记录函数的执行情况。值类型变量（函数的参数、局部变量 等非成员变量）都分配在stack中，引用类型的对象分配在heap中，在stack中保存heap对象的引用指针。GC只负责heap对象的释 放，heap内存空间管理&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;strong&gt;Heap内存分配&lt;/strong&gt; &amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-01-heap-allocation.png" alt="" width="452" height="120" /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;除去pinned object等影响，heap中的内存分配很简单，一个指针记录heap中分配的起始地址，根据对象大小连续的分配内存&lt;br /&gt;&lt;strong&gt;Stack结构&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 每个函数调用时，逻辑上在thread stack中会产生一个帧（stack frame），函数返回时对应的stack frame被释放掉 &amp;nbsp;&amp;nbsp;&amp;nbsp; 用个简单的函数查看执行时CLR对栈的处理情况：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; JIT编译后主要汇编代码如下（其他的情况下汇编代码可能有所差别，但用这个简单函数大致看下栈的管理已经足够）：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: 宋体; font-size: 11pt;"&gt;执行时刻的&lt;/span&gt;&lt;span style="font-size: 11pt;" lang="EN-US"&gt;stack&lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 11pt;"&gt;状态如下（栈基地址为高端地址，栈顶为低端地址）：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-03-stack-struct.png" alt="" width="258" height="183" /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Stack状态变化过程： &amp;nbsp;&amp;nbsp;&amp;nbsp; a). 调用者将第3、第4、第5个参数压栈，第1、第2个参数分别放入ecx、edx寄存器 &amp;nbsp;&amp;nbsp;&amp;nbsp; b). call指令调用函数Sum，并自动将函数返回地址压栈，代码跳转到函数Sum开始执行 &amp;nbsp;&amp;nbsp;&amp;nbsp; c). 函数Sum先将寄存器ebp压栈保存，并将esp放入ebp，用于后面对参数和局部变量寻址 &amp;nbsp;&amp;nbsp;&amp;nbsp; d). 定义局部变量以及省略掉的是额外代码，跟Sum函数业务无关 &amp;nbsp;&amp;nbsp;&amp;nbsp; e). 执行加法操作，结果保存在eax寄存器中 &amp;nbsp;&amp;nbsp;&amp;nbsp; f). 恢复esp寄存器，这样函数Sum中所有的局部变量以及其他压栈操作全部释放出来 &amp;nbsp;&amp;nbsp;&amp;nbsp; g). 原始ebp的值出栈，恢复ebp，这样栈完全恢复到进入Sum函数调用时的状态 &amp;nbsp;&amp;nbsp; h). ret指令执行函数返回，返回值在eax寄存器中，返回地址为call指令压栈的地址，返回地址自动出栈。0Ch指示处理器在函数返回时释放栈中12个字 节，即由被调用者清除压栈的参数。函数返回之后，本次Sum调用的栈分配全部释放 &amp;nbsp;&amp;nbsp;&amp;nbsp; 这种调用约定类似__fastcall&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 结合引用类型变量、值类型的ref参数，下面代码简化的stack状态如下： &amp;nbsp;&amp;nbsp;&amp;nbsp; 代码：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stack状态： &amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-04-stack-struct.png" alt="" width="475" height="244" /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;任何时候引用类型都分配在heap中，在stack中只是保存对象的引用地址。Run函数执行完毕之后，heap中的MyClass1对象c成为可回收的垃圾对象，在GC时进行回收&lt;br /&gt;&lt;strong style="font-size: 18pt;"&gt;2. Mark-Compact 标记压缩算法&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 简单把.NET的GC算法看作Mark-Compact算法 &amp;nbsp;&amp;nbsp;&amp;nbsp; 阶段1: Mark-Sweep 标记清除阶段 &amp;nbsp;&amp;nbsp;&amp;nbsp; 先假设heap中所有对象都可以回收，然后找出不能回收的对象，给这些对象打上标记，最后heap中没有打标记的对象都是可以被回收的 &amp;nbsp;&amp;nbsp;&amp;nbsp; 阶段2: Compact 压缩阶段 &amp;nbsp;&amp;nbsp;&amp;nbsp; 对象回收之后heap内存空间变得不连续，在heap中移动这些对象，使他们重新从heap基地址开始连续排列，类似于磁盘空间的碎片整理 &amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-02-mark-compact.png" alt="" width="493" height="149" /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; Heap内存经过回收、压缩之后，可以继续采用前面的heap内存分配方法，即仅用一个指针记录heap分配的起始地址就可以&lt;br /&gt;&amp;nbsp;&amp;nbsp; 主要处理步骤：将线程挂起=&amp;gt;确定roots=&amp;gt;创建reachable objects graph=&amp;gt;对象回收=&amp;gt;heap压缩=&amp;gt;指针修复 &amp;nbsp;&amp;nbsp; 可以这样理解roots：heap中对象的引用关系错综复杂（交叉引用、循环引用），形成复杂的graph，roots是CLR在heap之外可以找到的 各种入口点。GC搜索roots的地方包括全局对象、静态变量、局部对象、函数调用参数、当前CPU寄存器中的对象指针（还有finalization queue）等。主要可以归为2种类型：已经初始化了的静态变量、线程仍在使用的对象（stack+CPU register） &amp;nbsp;&amp;nbsp; Reachable objects：指根据对象引用关系，从roots出发可以到达的对象。例如当前执行函数的局部变量对象A是一个root object，他的成员变量引用了对象B，则B是一个reachable object。从roots出发可以创建reachable objects graph，剩余对象即为unreachable，可以被回收 &amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-05-reachable-graph.png" alt="" width="347" height="298" /&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;指针修复是因为compact过程移动了heap对象，对象地址发生变化，需要修复所有引用指针，包括stack、CPU register中的指针以及heap中其他对象的引用指针 &amp;nbsp;&amp;nbsp; Debug和release执行模式之间稍有区别，release模式下后续代码没有引用的对象是unreachable的，而debug模式下需要等到 当前函数执行完毕，这些对象才会成为unreachable，目的是为了调试时跟踪局部对象的内容 &amp;nbsp;&amp;nbsp;&amp;nbsp; 传给了COM+的托管对象也会成为root，并且具有一个引用计数器以兼容COM+的内存管理机制，引用计数器为0时这些对象才可能成为被回收对象 &amp;nbsp;&amp;nbsp; Pinned objects指分配之后不能移动位置的对象，例如传递给非托管代码的对象（或者使用了fixed关键字），GC在指针修复时无法修改非托管代码中的引用 指针，因此将这些对象移动将发生异常。pinned objects会导致heap出现碎片，但大部分情况来说传给非托管代码的对象应当在GC时能够被回收掉&lt;br /&gt;&lt;strong style="font-size: 18pt;"&gt;3. Generational 分代算法&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 程序可能使用几百M、几G的内存，对这样的内存区域进行GC操作成本很高，分代算法具备一定统计学基础，对GC的性能改善效果比较明显 &amp;nbsp;&amp;nbsp; 将对象按照生命周期分成新的、老的，根据统计分布规律所反映的结果，可以对新、老区域采用不同的回收策略和算法，加强对新区域的回收处理力度，争取在较短 时间间隔、较小的内存区域内，以较低成本将执行路径上大量新近抛弃不再使用的局部对象及时回收掉 &amp;nbsp;&amp;nbsp;&amp;nbsp; 分代算法的假设前提条件： &amp;nbsp;&amp;nbsp;&amp;nbsp; a). 大量新创建的对象生命周期都比较短，而较老的对象生命周期会更长 &amp;nbsp;&amp;nbsp;&amp;nbsp; b). 对部分内存进行回收比基于全部内存的回收操作要快 &amp;nbsp;&amp;nbsp;&amp;nbsp; c). 新创建的对象之间关联程度通常较强。heap分配的对象是连续的，关联度较强有利于提高CPU cache的命中率&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .NET将heap分成3个代龄区域: Gen 0、Gen 1、Gen 2 &amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-06-generation.png" alt="" width="624" height="167" /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; Heap分为3个代龄区域，相应的GC有3种方式: # Gen 0 collections, # Gen 1 collections, # Gen 2 collections。如果Gen 0 heap内存达到阀值，则触发0代GC，0代GC后Gen 0中幸存的对象进入Gen 1。如果Gen 1的内存达到阀值，则进行1代GC，1代GC将Gen 0 heap和Gen 1 heap一起进行回收，幸存的对象进入Gen 2。2代GC将Gen 0 heap、Gen 1 heap和Gen 2 heap一起回收 &amp;nbsp;&amp;nbsp; Gen 0和Gen 1比较小，这两个代龄加起来总是保持在16M左右；Gen 2的大小由应用程序确定，可能达到几G，因此0代和1代GC的成本非常低，2代GC称为full GC，通常成本很高。粗略的计算0代和1代GC应当能在几毫秒到几十毫秒之间完成，Gen 2 heap比较大时full GC可能需要花费几秒时间。大致上来讲.NET应用运行期间2代、1代和0代GC的频率应当大致为1:10:100&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-07-heap-gen-size-mon.png" alt="" width="560" height="359" /&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;图为一个ASP.NET程序运行的Performance Moniter，Gen 0 heap size(红色)平均6M，Gen 1(蓝色)平均5M，Gen 2(黄色)达到620M，Gen 0+Gen 1平均13.2M，最大19.8M&lt;br /&gt;&amp;nbsp;&amp;nbsp; 直观上来看，程序的运行由一系列函数调用组成，函数运行期间会创建很多局部对象，函数结束之后也就产生大量待回收的对象。采用分代算法加强较新代龄的垃圾 回收力度，通常能够极大的提高垃圾回收效率，否则就是极特殊的程序，或者是不合理的对象关联设计。例如ASP.NET程序，应当确保绝大部分用于HTTP请求处理的对象在0代和1代垃圾回收中被释放掉&lt;br /&gt;&amp;nbsp;&amp;nbsp; 为heap记录几个指针可以确定代龄区域范围，创建reachable objects graph时根据对象的地址可以确定对象位于哪个代龄区域，0代GC在创建graph时如果遇到1代、2代heap对象，可以直接越过不用继续遍历下去， 较老代龄的对象如果引用了较新代龄的对象，可以通过Win32 API GetWriteWatch订阅内存更新通知，记录在"card table"中，辅助较低代龄的GC正确构造graph&lt;br /&gt;&lt;strong style="font-size: 18pt;"&gt;4. LOH&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .NET 1.1和2.0中，85000字节以下的对象称为小对象，分配在Gen 0 heap中，85000字节以上的对象称为大对象，分配在Large Object Heap中，这是因为GC在heap压缩时移动大的内存块需要消耗大量CPU时间，通过性能调优实践确定了85000字节这样一个阀值 &amp;nbsp;&amp;nbsp; LOH只在2代GC时进行回收，采用Mark-Sweep算法，没有压缩处理，因此LOH中的内存分配是不连续的，使用一个空闲列表free list记录LOH中的空闲空间，对释放出来的空间进行管理 &amp;nbsp;&amp;nbsp; &lt;img src="http://images.cnblogs.com/cnblogs_com/riccc/dotnet/net-mem-08-loh.png" alt="" width="385" height="229" /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;上图中obj1、obj2释放之后，其空间合并起来成为free list的一个节点，随后被分配给obj4&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;什么时候触发垃圾回收？&lt;/strong&gt; &amp;nbsp;&amp;nbsp; 前面已经提到，0代和1代垃圾回收主要由阀值控制。初始时Gen 0 heap大小与CPU缓存的大小相关，运行时CLR根据内存请求状态动态调整Gen 0 heap大小，但Gen 0和Gen 1总大小保持在16M左右 Gen 2 heap和LOH都在full GC时进行回收，full GC主要由2类事件触发： &amp;nbsp;&amp;nbsp; a). 进入Gen 2 heap和LOH的对象很多，超过了一定比例。RegisterForFullGCNotification的参数maxGenerationThreshold、largeObjectHeapThreshold可以分别为Gen 2 heap和LOH设定这个值 &amp;nbsp;&amp;nbsp;&amp;nbsp; b). 操作系统内存吃紧的时候。CLR会接收到操作系统内存紧张的通知消息，触发full GC&lt;br /&gt;&lt;strong style="font-size: 18pt;"&gt;5. Heap细节、扩容与收缩&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp; Heap的代龄是逻辑上的结构，heap实际内存申请和分配以及释放以segment（段）为单位，workstation GC模式segment大小为16M，server GC模式segment大小为64M。Gen 0和Gen 1 heap总是位于同一个段中，叫做ephemeral segment（新生段），因此max(Gen 0 heap size+Gen 1 heap size)&amp;asymp;16M || 64M，Gen 2 heap由0个或多个segments组成，LOH由1个或多个segments组成 &amp;nbsp;&amp;nbsp;&amp;nbsp; .NET程序启动时CLR为heap创建2个segment，一个作为ephemeral segment，另一个用于LOH。.NET使用VirtualAlloc申请和分配heap内存，在LOH中分配新对象时没有足够的空间，或者1代GC时进入Gen 2的对象过多空间不够，.NET将为LOH或者小对象heap分配新的segment。申请新的segment失败将由EE抛出OutOfMemory异 常 &amp;nbsp;&amp;nbsp;&amp;nbsp; Full GC后完全空闲的segments将被释放掉，内存返回给操作系统&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .NET 2.0对GC的一个重要改进是尽量改善heap碎片处理。heap碎片主要由pinned objects引起，改善措施主要有2个方面。首先是延迟升级，如果ephemeral segment存在pinned objects，则尽可能的延迟他们升级到Gen 2的时间点，考虑pinned objects的同时尽量充分利用当前ephemeral segment的空间；其次是重复利用Gen 2的空间，如果Gen 2中存在pinned objects的segments释放出了足够空间，该segments可能重新作为ephemeral segment使用&lt;br /&gt;&lt;strong style="font-size: 18pt;"&gt;6. GC方式&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp; 有Workstation GC with Concurrent GC off、 Workstation GC with Concurrent GC on、Server GC 3种 &amp;nbsp;&amp;nbsp; Workstation GC with Concurrent GC off:用于单CPU机器实现高吞吐量，采用一系列策略观察内存分配以及每次GC的状况，动态调整GC策略，尽可能使程序随着运行时状态的变化实现高效的GC操 作，但进行GC时会冻结所有线程 &amp;nbsp;&amp;nbsp; Workstation GC with Concurrent GC on:用于响应时间非常重要的交互式程序，例如流媒体的播放等（如果一次full GC导致应用程序中断几秒、十几秒时间，用户将无法忍受）。这种方式利用多CPU对full GC进行并行处理，不是整个full GC期间冻结所有线程，而是将full GC切分成多次很短的时间对线程进行冻结，在线程冻结时间之外，应用程序仍然可以正常运行，进行内存分配，这主要通过将Gen 0 heap size设置的比non-concurrent GC大很多而实现，使得GC操作时线程仍然能够在Gen 0 heap中进行内存分配，但如果Gen 0 heap用完后GC仍然没有结束，线程仍然会出现阻塞。这种方式付出的代价是working set和GC所需时间比non-concurrent GC要大一些 &amp;nbsp;&amp;nbsp;&amp;nbsp; Server GC:用于多CPU机器的服务器应用程序实现高吞吐量和伸缩性，充分利用服务器的大内存。.NET为每个CPU创建一组heap（包括Gen 0, 1, 2和LOH）和一个GC线程，每个CPU可以独立的为相应的heap执行GC操作，而其他CPU则正常执行处理。最佳的应用场景是多线程之间内存结构基本 相同，执行的工作相同或类似&lt;br /&gt;&amp;nbsp;&amp;nbsp; 单CPU机器上只能使用workstation GC，默认情况下为Workstation GC with Concurrent GC on方式，单CPU机器上配置为Server GC无效，仍然使用workstation GC；多CPU服务器上的ASP.NET默认使用Server GC方式，Server GC时不能使用concurrent方式 &amp;nbsp;&amp;nbsp;&amp;nbsp; concurrent GC可以用于单CPU机器，它与CPU数量无关 &amp;nbsp;&amp;nbsp; 对于ASP.NET程序应当尽量保证一个CPU仅对应一个GC线程，防止同一个CPU上面多个GC线程之间的冲突造成性能问题。如果使用了Web Garden则应当使用Workstation GC with Concurrent GC off。Web Garden为了提高吞吐量会导致多出几倍的内存使用，每个work process的内存有很多重复部分，Web Garden的最佳应用场景是多个进程之间使用一个共享的resource pool，避免内存的重复并尽可能的提高吞吐量。在这一点上Server GC应当与Web Garden类似，但Web Garden在多个进程中，而Server GC是在同一个进程中通过多线程实现，目前没有发现Server GC方面深入一些的资料，很多东西只能根据现有资料做一些猜想 &amp;nbsp;&amp;nbsp;&amp;nbsp; 为workstation GC禁用concurrent GC:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;p&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;runtime&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;gcConcurrent &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;enabled&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="false"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;runtime&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 启用Server GC:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;p&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;runtime&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;gcServer &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;enabled&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=&amp;ldquo;true"/&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;&amp;lt;/runtime&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;configuration&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;strong style="font-size: 18pt;"&gt;7. Finalization&lt;/strong&gt;&lt;br style="font-size: 18pt;" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 具有finalize method的对象在垃圾回收时，.NET先调用finalize method，然后再进行回收，具体处理如下： &amp;nbsp;&amp;nbsp;&amp;nbsp; a). 在heap创建具有finalize method的对象时，对象指针会放入finalization queue； &amp;nbsp;&amp;nbsp;&amp;nbsp; b). 垃圾回收时，具有finalize method的对象如果成为unreachable，则将其指针从finalization queue中移除，放入freachable queue，在本次垃圾回收处理中并不对这些对象进行回收；其它没有finalize method的unreachable对象正常回收。freachable queue中的对象是reachable的（它引用到的其他对象也都是reachable的） &amp;nbsp;&amp;nbsp;&amp;nbsp; c). 垃圾回收结束后，如果freachable queue非空，则一个专门的运行时线程finalizer thread被唤醒，它逐个调用freachable queue中对象的finalize method，然后将其指针从freachable queue中移除 &amp;nbsp;&amp;nbsp;&amp;nbsp; d). 经过步骤c的处理之后，第二次垃圾回收时这些对象就成为unreachable，被正常回收 &amp;nbsp;&amp;nbsp;&amp;nbsp; 因为finalize method被设计用于非托管资源的释放，对这些资源的释放可能需要较长的时间，为了优化垃圾回收处理的性能，因此将调用finalize method专门交给一个独立的线程finalizer thread异步进行处理，这样也造成finalize method的对象需要经过2次垃圾回收处理&lt;br /&gt;参考： &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Patrick-Dussud-Garbage-Collection-Past-Present-and-Future/" target="_blank"&gt;Garbage Collection - Past, Present and Future&lt;/a&gt;,&lt;/p&gt;&lt;p&gt;Patrick Dussud, 中文翻译: &lt;a href="http://blog.csdn.net/hellothere/archive/2008/02/23/2115422.aspx" target="_blank"&gt;.NET垃圾收集器的过去现在和未来（一）&lt;/a&gt;, &lt;a href="http://blog.csdn.net/hellothere/archive/2008/04/02/2245734.aspx" target="_blank"&gt;（二）&lt;/a&gt; &lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx" target="_blank"&gt;C# Heap(ing) Vs Stack(ing) in .NET Part I&lt;/a&gt;,&lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx" target="_blank"&gt;Part II&lt;/a&gt;, &lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx" target="_blank"&gt;Part III&lt;/a&gt;, &lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory_401282006141834PM/csharp_memory_4.aspx" target="_blank"&gt;Part IV&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Matthew Cochran &lt;a href="http://msdn.microsoft.com/en-us/magazine/bb985010.aspx" target="_blank"&gt;Garbage Collection: Automatic &lt;/a&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/bb985010.aspx" target="_blank"&gt;Memory Management in the Microsoft .NET Framework&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Jeffrey Richter &lt;a href="http://msdn.microsoft.com/en-us/magazine/bb985011.aspx" target="_blank"&gt;Garbage Collection Part 2: Automatic Memory Management in the Microsoft .NET Framework&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Jeffrey Richter &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc534993.aspx" target="_blank"&gt;CLR Inside Out: Large Object Heap Uncovered&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Maoni Stephens &lt;a href="http://msdn.microsoft.com/en-us/library/ms810466.aspx" target="_blank"&gt;Heap: Pleasures and Pains&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Murali R. Krishnan &lt;a href="http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/" target="_blank"&gt;The Dangers of the Large Object Heap&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Andrew Hunter &lt;a href="http://msdn.microsoft.com/en-us/library/cc713687.aspx" target="_blank"&gt;Garbage Collection Notifications&lt;/a&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/ms973837.aspx" target="_blank"&gt;Garbage Collector Basics and Performance Hints&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Rico Mariani &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163528.aspx" target="_blank"&gt;CLR Inside Out: Investigating Memory Issues&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Claudio Caldato and Maoni Stephens &lt;a href="http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/" target="_blank"&gt;Understanding Garbage Collection in .NET&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Andrew Hunter &lt;a href="http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx" target="_blank"&gt;Using GC Efficiently Part 1&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx" target="_blank"&gt;Part 2&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maoni/archive/2004/12/19/327149.aspx" target="_blank"&gt;Part 3&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/maoni/archive/2005/05/06/415296.aspx" target="_blank"&gt;Part 4&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Maoni Stephens &lt;a href="http://vineetgupta.spaces.live.com/blog/cns%218DE4BDC896BEE1AD%211104.entry" target="_blank"&gt;Notes on the CLR Garbage Collector&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Vineet Gupta &lt;a href="http://www.julmar.com/blog/mark/PermaLink,guid,3670d081-0276-48e6-b97d-1b644093b52e.aspx" target="_blank"&gt;The Mystery of Concurrent GC&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Mark Smith &lt;a href="http://www.facultyresourcecenter.com/curriculum/pfv.aspx?ID=6182" target="_blank"&gt;Garbage Collection Curriculum&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ferreira Paulo, Veiga Lu&amp;iacute;s &lt;a href="http://www.ibm.com/developerworks/library/j-jtp10283/" target="_blank"&gt;Java theory and practice: A brief history of garbage collection&lt;/a&gt; Brian Goetz&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2420800.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2012/03/28/2420800.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2012/02/06/mvc.html</id><title type="text">体验不一样的MVC,让开发更加迅捷</title><summary type="text">mvc其实也可以很疯狂.....</summary><published>2012-02-06T07:17:00Z</published><updated>2012-02-06T07:17:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2012/02/06/mvc.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2012/02/06/mvc.html"/><content type="html">&lt;p&gt;去年说了要做一些开源项目，一直都忙着玩，也没发布。今年借此机会先尝鲜体现下犀利的C#吧。&lt;/p&gt;&lt;p&gt;在上上一篇的时候介绍了MVC,这一篇就来分享下自己的mvc项目。虽然就一百多行代码。不过小即使美。废话不多说，看代码。&lt;/p&gt;&lt;p&gt;首先MvcHttpHandler&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Web;&lt;br/&gt;using System.Linq;&lt;br/&gt;using System.Web.SessionState;&lt;br/&gt;using System.Text;&lt;br/&gt;using System.Text.RegularExpressions;&lt;br/&gt;using System.Collections;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;using System.Collections.Specialized;&lt;br/&gt;using StructureMap;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;    /// &amp;lt;summary&amp;gt;&lt;br/&gt;    /// 拦截请求，并对请求进行处理&lt;br/&gt;    /// &amp;lt;/summary&amp;gt;&lt;br/&gt;    public class MvcHttpHandler : IHttpHandler, IRequiresSessionState&lt;br/&gt;    {&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 此部分请求不共享，并不保证绝对的线程安全。如果设置true,测需要对控制器设置HybridHttpOrThreadLocalScoped或者HttpContextScoped&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public bool IsReusable&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return false;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 隐示实现IHttpHandler接口&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;remarks&amp;gt;&lt;br/&gt;        /// 此部分为了兼容与IHttpHandler接口，以及MoqHttpContextBase对象&lt;br/&gt;        /// &amp;lt;/remarks&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="httpContext"&amp;gt;HttpContext请求对象&amp;lt;/param&amp;gt;&lt;br/&gt;        public virtual void ProcessRequest(HttpContext httpContext)&lt;br/&gt;        {&lt;br/&gt;            this.HttpContext = new HttpContextWrapper(httpContext);&lt;br/&gt;            this.ProcessRequest();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 执行请求&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public virtual void ProcessRequest()&lt;br/&gt;        {&lt;br/&gt;            var request = new RequestContext(this.HttpContext);&lt;br/&gt;            IController controller = null;&lt;br/&gt;            try&lt;br/&gt;            {&lt;br/&gt;                controller = ObjectFactory.GetNamedInstance&amp;lt;IController&amp;gt;(request.ControllerName);&lt;br/&gt;            }&lt;br/&gt;            catch&lt;br/&gt;            {&lt;br/&gt;                throw new NullReferenceException(string.Format("未查询到{0}的实例", request.ControllerName));&lt;br/&gt;            }&lt;br/&gt;            finally&lt;br/&gt;            {&lt;br/&gt;                controller.Execute(request);&lt;br/&gt;            }&lt;br/&gt;            return;&lt;br/&gt;         &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// HttpContext的抽象&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public HttpContextBase HttpContext&lt;br/&gt;        {&lt;br/&gt;            get;&lt;br/&gt;            set;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #region IHttpHandler&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 显示实现IHttpHandler接口,对方法进行指定。&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        bool IHttpHandler.IsReusable&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.IsReusable;&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 显示实现IHttpHandler接口,对方法进行指定。&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="context"&amp;gt;HttpContext请求对象&amp;lt;/param&amp;gt;&lt;br/&gt;        void IHttpHandler.ProcessRequest(HttpContext context)&lt;br/&gt;        {&lt;br/&gt;            this.ProcessRequest(context);&lt;br/&gt;            return;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;再次RequestContext&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;using System.Text;&lt;br/&gt;using System.Web;&lt;br/&gt;using System.Text.RegularExpressions;&lt;br/&gt;using System.IO;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;    /// &amp;lt;summary&amp;gt;&lt;br/&gt;    /// RequestContext对象&lt;br/&gt;    /// &amp;lt;/summary&amp;gt;&lt;br/&gt;    public class RequestContext&lt;br/&gt;    {&lt;br/&gt;&lt;br/&gt;        private string m_path;&lt;br/&gt;        private string m_baseuri;&lt;br/&gt;        private Uri m_uri;&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// RequestContext对象&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="httpcontent"&amp;gt;HttpContextBase对象&amp;lt;/param&amp;gt;&lt;br/&gt;        public RequestContext(HttpContextBase httpcontent)&lt;br/&gt;        {&lt;br/&gt;            this.HttpContext = httpcontent;&lt;br/&gt;            this.m_uri = httpcontent.Request.Url;&lt;br/&gt;            var regx = new Regex(@"(\D+/)([0-9a-zA-Z][-\w]*[0-9a-zA-Z])+(\.aspx)", RegexOptions.IgnoreCase).Match(this.m_uri.ToString());&lt;br/&gt;            this.m_path = regx.Success ? regx.Groups[1].Value : "/Index/";&lt;br/&gt;            this.m_baseuri = regx.Success ? regx.Groups[1].Value : "/";&lt;br/&gt;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// HttpContext请求&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public HttpContextBase HttpContext&lt;br/&gt;        {&lt;br/&gt;            get;&lt;br/&gt;            set;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 返回当前的请求路径&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public Uri Url&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.m_uri;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 返回Url的基址&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public Uri BaseUri&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                var uri = string.Format("http://{0}{1}", this.HttpContext.Request.UserHostName, this.m_baseuri);&lt;br/&gt;                return new Uri(uri);&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 请求中的谓词&lt;br/&gt;        /// &amp;lt;remarks&amp;gt;&lt;br/&gt;        /// 如需要扩展谓词，侧需要服务器的支持。&lt;br/&gt;        /// &amp;lt;/remarks&amp;gt;&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public string HttpMethod&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.HttpContext.Request.HttpMethod.ToUpper();&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 返回渲染视图的模板地址&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public string TemplatePath&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                string path = string.Format("{0}{1}", this.m_path, Path.GetFileNameWithoutExtension(this.HttpContext.Request.PhysicalPath));&lt;br/&gt;                return path;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 返回控制器的名称&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public string ControllerName&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return string.Format("{0}Controller", this.m_path.Replace("/", string.Empty)).ToUpper();&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;Route路由器&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Web;&lt;br/&gt;using System.Collections.Specialized;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;&lt;br/&gt;    /// &amp;lt;summary&amp;gt;&lt;br/&gt;    /// 路由器&lt;br/&gt;    /// &amp;lt;/summary&amp;gt;&lt;br/&gt;    class Route&lt;br/&gt;    {&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// UriTemplate对象&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public UriTemplate PathPattern&lt;br/&gt;        {&lt;br/&gt;            get;&lt;br/&gt;            private set;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// Http谓词&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public string HttpMethod&lt;br/&gt;        {&lt;br/&gt;            get;&lt;br/&gt;            private set;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 返回代码处理方法&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public Func&amp;lt;ResponseContent, ActionResult&amp;gt; Action&lt;br/&gt;        {&lt;br/&gt;            get;&lt;br/&gt;            private set;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 路由器构造实例&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="httpmethod"&amp;gt;Http谓词&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="PathPattern"&amp;gt;UriTemplate对象&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="action"&amp;gt;返回代码处理方法&amp;lt;/param&amp;gt;&lt;br/&gt;        public Route(string httpmethod, UriTemplate PathPattern, Func&amp;lt;ResponseContent, ActionResult&amp;gt; action)&lt;br/&gt;        {&lt;br/&gt;            this.HttpMethod = httpmethod;&lt;br/&gt;            this.PathPattern = PathPattern;&lt;br/&gt;            this.Action = action;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;IController接口&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Data;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;    /// &amp;lt;summary&amp;gt;&lt;br/&gt;    /// IController&lt;br/&gt;    /// &amp;lt;/summary&amp;gt;&lt;br/&gt;    public interface IController&lt;br/&gt;    {&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 执行IController方法&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="requestContext"&amp;gt;RequestContext&amp;lt;/param&amp;gt;&lt;br/&gt;        void Execute(RequestContext requestContext);&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;控制器接口实现&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Collections.Specialized;&lt;br/&gt;using System.IO;&lt;br/&gt;using System.Web;&lt;br/&gt;using System.Text;&lt;br/&gt;using System.Text.RegularExpressions;&lt;br/&gt;using System.Linq;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;    public abstract class Controller : IController&lt;br/&gt;    {&lt;br/&gt;        private readonly IList&amp;lt;Route&amp;gt; routes = new List&amp;lt;Route&amp;gt;(25);&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 添加路由请求到注册容器中。&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public abstract void  MapRoutes();&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 返回匹配的ActionResult&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;returns&amp;gt;ActionResult&amp;lt;/returns&amp;gt;&lt;br/&gt;        private ActionResult GetActionResult()&lt;br/&gt;        {&lt;br/&gt;            ActionResult result = null;&lt;br/&gt;            var routetable = from c in this.routes where c.HttpMethod == this.RequestContext.HttpMethod select c;&lt;br/&gt;            UriTemplateMatch results;&lt;br/&gt;            foreach (var st in routetable)&lt;br/&gt;            {&lt;br/&gt;                results = st.PathPattern.Match(this.RequestContext.BaseUri, this.RequestContext.Url);&lt;br/&gt;                if (results != null)&lt;br/&gt;                {&lt;br/&gt;                    result = st.Action(new ResponseContent() { HttpContent = this.RequestContext.HttpContext, Parameter = results.BoundVariables });&lt;br/&gt;                    return result;&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;            return NotFound();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// RequestContext对象&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        protected internal RequestContext RequestContext&lt;br/&gt;        {&lt;br/&gt;            get;&lt;br/&gt;            set;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;       &lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// IController的接口实现&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="context"&amp;gt;RequestContext对象&amp;lt;/param&amp;gt;&lt;br/&gt;        public virtual void Execute(RequestContext context)&lt;br/&gt;        {&lt;br/&gt;            this.RequestContext = context;&lt;br/&gt;            var result = this.GetActionResult();&lt;br/&gt;            if (context.HttpContext.Response.SuppressContent)&lt;br/&gt;            {&lt;br/&gt;                context.HttpContext.Response.Write("SuppressContent被设置请求忽略");&lt;br/&gt;            }&lt;br/&gt;            else&lt;br/&gt;            {&lt;br/&gt;                result.Execute(context.HttpContext);&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// &lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="route"&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="block"&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        protected internal void Get(string route, Func&amp;lt;ResponseContent, ActionResult&amp;gt; block)&lt;br/&gt;        {&lt;br/&gt;            this.routes.Add(new Route("GET", new UriTemplate(route), block));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected internal void Post(string route, Func&amp;lt;ResponseContent, ActionResult&amp;gt; block)&lt;br/&gt;        {&lt;br/&gt;            this.routes.Add(new Route("POST", new UriTemplate(route), block));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected internal void Delete(string route, Func&amp;lt;ResponseContent, ActionResult&amp;gt; block)&lt;br/&gt;        {&lt;br/&gt;            this.routes.Add(new Route("DELETE", new UriTemplate(route), block));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected internal void Put(string route, Func&amp;lt;ResponseContent, ActionResult&amp;gt; block)&lt;br/&gt;        {&lt;br/&gt;            this.routes.Add(new Route("PUT", new UriTemplate(route), block));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected ActionResult Text(string text)&lt;br/&gt;        {&lt;br/&gt;            return new TextResult(text);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected ActionResult NotFound()&lt;br/&gt;        {&lt;br/&gt;            return new StatusResult(404, "dd");&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected ActionResult Error()&lt;br/&gt;        {&lt;br/&gt;            return new StatusResult(501, "dd");&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        protected ActionResult View&amp;lt;T&amp;gt;(T value)&lt;br/&gt;        {&lt;br/&gt;            return new ViewResult&amp;lt;T&amp;gt;(this.RequestContext.TemplatePath, value);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected ActionResult View&amp;lt;T&amp;gt;(string templatename,T value)&lt;br/&gt;        {&lt;br/&gt;            return new ViewResult&amp;lt;T&amp;gt;(templatename, value);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #region IController&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 显示实现IController接口&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="requestContext"&amp;gt;RequestContext对象&amp;lt;/param&amp;gt;&lt;br/&gt;        void IController.Execute(RequestContext requestContext)&lt;br/&gt;        {&lt;br/&gt;            this.Execute(requestContext);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;视图ActionResult&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Collections.Specialized;&lt;br/&gt;using System.IO;&lt;br/&gt;using System.Web;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;    public abstract class ActionResult&lt;br/&gt;    {&lt;br/&gt;        public abstract void Execute(HttpContextBase context);&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;系统初始化&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System.Collections;&lt;br/&gt;using System;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;using System.Reflection;&lt;br/&gt;using System.Linq;&lt;br/&gt;using StructureMap;&lt;br/&gt;&lt;br/&gt;namespace Dapper.Web.Mvc&lt;br/&gt;{&lt;br/&gt;    /// &amp;lt;summary&amp;gt;&lt;br/&gt;    /// 初始化MVC框架&lt;br/&gt;    /// &amp;lt;/summary&amp;gt;&lt;br/&gt;    public static class Initialise&lt;br/&gt;    {&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 注册系统内部的控制器集合。此部分使用时候要注意，要适当的考虑派生的方法也会在某些时候直接注册在容器中。&lt;br/&gt;        /// &amp;lt;remarks&amp;gt;&lt;br/&gt;        /// 如果此部分在扩展的时候，可以直接使用Activator.CreateInstance。参考RegionController("IndexController");提示的方法进行操作。&lt;br/&gt;        /// &amp;lt;/remarks&amp;gt;&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        public static void RegionController()&lt;br/&gt;        {&lt;br/&gt;            var classes = Assembly.GetCallingAssembly().GetTypes().Where(t =&amp;gt; t.BaseType == typeof(Controller));&lt;br/&gt;            ObjectFactory.Initialize(r =&amp;gt;&lt;br/&gt;            {&lt;br/&gt;                foreach (var c in classes)&lt;br/&gt;                {&lt;br/&gt;                    var controller = (Controller)Activator.CreateInstance(c);&lt;br/&gt;                    controller.MapRoutes();&lt;br/&gt;                    r.For&amp;lt;IController&amp;gt;().HybridHttpOrThreadLocalScoped().AddInstances(m =&amp;gt; m.IsThis(controller).Named(c.Name.ToUpper()));&lt;br/&gt;                   &lt;br/&gt;                }&lt;br/&gt;            });&lt;br/&gt;            return;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        //private static void GetControllerByName(string controllername, out IController controller)&lt;br/&gt;        //{&lt;br/&gt;        //    try&lt;br/&gt;        //    {&lt;br/&gt;        //        controller = (IController)Activator.CreateInstance(Type.GetType(string.Format("Dapper.Web.Controllers.{0},Web", controllername), false, true));&lt;br/&gt;        //    }&lt;br/&gt;        //    catch&lt;br/&gt;        //    {&lt;br/&gt;        //        throw new Exception("控制器实例化错误");&lt;br/&gt;        //    }&lt;br/&gt;           &lt;br/&gt;        //    return;&lt;br/&gt;        //}&lt;br/&gt;&lt;br/&gt;        //public static void RegionController(string controllername)&lt;br/&gt;        //{&lt;br/&gt;        //    IController controller;&lt;br/&gt;        //    GetControllerByName(controllername, out controller);&lt;br/&gt;        //    ObjectFactory.Initialize(r =&amp;gt;&lt;br/&gt;        //        {&lt;br/&gt;        //            r.ForSingletonOf&amp;lt;IController&amp;gt;().HybridHttpOrThreadLocalScoped().Use(controller).Named(controllername);&lt;br/&gt;        //        });&lt;br/&gt;        //    return;&lt;br/&gt;        //}&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;OK,有了这些，代码就可以这样写了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    public class AdminController : Controller&lt;br/&gt;    {&lt;br/&gt;        private readonly IData data;&lt;br/&gt;&lt;br/&gt;        #region 构造参数&lt;br/&gt;&lt;br/&gt;        public AdminController()&lt;br/&gt;        {&lt;br/&gt;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public AdminController(IData data)&lt;br/&gt;        {&lt;br/&gt;            this.data = data;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;&lt;br/&gt;        public ActionResult Index()&lt;br/&gt;        {&lt;br/&gt;            return Text("Login");&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public ActionResult Index(string text)&lt;br/&gt;        {&lt;br/&gt;            return Text(text);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public override void MapRoutes()&lt;br/&gt;        {&lt;br/&gt;            Get("Login.aspx", view =&amp;gt; Index());&lt;br/&gt;            Get("Login.aspx/{language}/", view =&amp;gt; Index(view.Parameter["language"]));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public class UserController : Controller&lt;br/&gt;    {&lt;br/&gt;        public ActionResult Login()&lt;br/&gt;        {&lt;br/&gt;            return Text("UserController");&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public ActionResult LoginUser()&lt;br/&gt;        {&lt;br/&gt;            return Text("UserController");&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public ActionResult RegionUser()&lt;br/&gt;        {&lt;br/&gt;            return Text("UserController");&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public override void MapRoutes()&lt;br/&gt;        {&lt;br/&gt;            Get("Login.aspx", view =&amp;gt; Login());&lt;br/&gt;            Post("Login.aspx", view =&amp;gt; LoginUser());&lt;br/&gt;            Get("Region.aspx", view =&amp;gt; RegionUser());&lt;br/&gt;            Get("Login.aspx", view =&amp;gt; new Simple ().OneActionResult(view));&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public class UserContentController : Controller&lt;br/&gt;    {&lt;br/&gt;        public override void MapRoutes()&lt;br/&gt;        {&lt;br/&gt;            Get("ViewContent.aspx/{id}", view =&amp;gt;&lt;br/&gt;            {&lt;br/&gt;                int id = int.Parse(view.Parameter["id"]);&lt;br/&gt;                return Text(id.ToString());&lt;br/&gt;            });&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这样的代码好处是什么呢。看代码也许就能够明白了。&lt;/p&gt;&lt;p&gt;对于UserController。可以分别通过来获得对应的视图。&lt;/p&gt;&lt;p&gt;/User/Login.aspx&lt;br /&gt;/User/Region.aspx&lt;/p&gt;&lt;p&gt;&lt;br /&gt;对于UserContentController这样的视图，可以通过&lt;br /&gt;/User/Content/ViewContent.aspx/1&lt;br /&gt;/UserContent/ViewContent.aspx/1&lt;/p&gt;&lt;p&gt;通过这样的结构，就不需要面对大量的aspx文件了，一个方法对应一个路由url。而超过mvc的优点就是不需要去配置路由表。&lt;/p&gt;&lt;p&gt;那么如果要是多语言该如何实现呢。一些依然很简单。&lt;/p&gt;&lt;p&gt;使用&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Get("Test.aspx/{language}/", view =&amp;gt; Index(view.Parameter["language"]));&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;来装载不同的语言包。&lt;/p&gt;&lt;p&gt;我们就可以使用Test.aspx/zh-cn/这样的url来改变语言。&lt;/p&gt;&lt;p&gt;如果要分布式的去处理web中产生的逻辑呢？其实在这种情况下已经变得很简单了。&lt;/p&gt;&lt;p&gt;比如举例子用xml_rpc来实现验证服务器分布。如果在商业用中推荐NServiceBus&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    public interface IXmlRpc : IXmlRpcProxy&lt;br/&gt;    {&lt;br/&gt;        [XmlRpcMethod("hello word")]&lt;br/&gt;        ActionResult OneActionResult(ResponseContent content);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public class Simple : IXmlRpc&lt;br/&gt;    {&lt;br/&gt;        public ActionResult OneActionResult(ResponseContent content)&lt;br/&gt;        {&lt;br/&gt;            throw new NotImplementedException();&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;关于服务器平台以及兼容性侧直接支持iis5.0之上的所有平台。如果你的并发足够的大，可以运行在nginx之上。为什么，怎么用，有什么好处？下篇解释吧。&lt;/p&gt;&lt;p&gt;有兴趣的去测试下TPS，看看快不快，大体结果是和关闭viewstat的aspx差不多，是微软mvc的一倍以上。&lt;/p&gt;&lt;p&gt;题外话：有上海或者常州要招聘.net 中级开发人员的公司有木有？求知道啊。最近找工作，找不到那些公司需要招聘啊。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2340204.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2012/02/06/mvc.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/12/07/2279355.html</id><title type="text">RazorEngine的一些问题</title><summary type="text">RazorEngine是微软最新的一个视图引擎，借组简单的语法表达能力，以及良好的代码感知，有点要灭掉aspx的样子。这个引擎也有着很高的关注度。</summary><published>2011-12-07T07:25:00Z</published><updated>2011-12-07T07:25:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/12/07/2279355.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/12/07/2279355.html"/><content type="html">&lt;p&gt;RazorEngine是微软最新的一个视图引擎，借组简单的语法表达能力，以及良好的代码感知，有点要灭掉aspx的样子。这个引擎也有着很高的关注度。&lt;/p&gt;&lt;p&gt;最近一直想体验下Razor。这种模板编写实在让人喜欢，再加上有智能感知。可是Razor需要运行在4.0的环境。于是重新的下了一个VS2010。经过了一番折腾，终于搞定，模板也可以智能感知了，JS也智能感知了，一切完美。之后测试的测试才知道有多慢。最开始的时候还在想是不是那个地方做错了。检查了一遍，再测试，依然慢。&lt;/p&gt;&lt;p&gt;&lt;a href="http://pic002.cnblogs.com/images/2011/187666/2011120620063234.jpg" target="_blank"&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011120620063234.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://pic002.cnblogs.com/images/2011/187666/2011120620063952.jpg" target="_blank"&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011120620063952.jpg" alt="" width="500" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;于是就直接拿着asp.net Mvc3的项目测试。一个简单的Rendered视图，比asp.net Mvc2要慢两倍，asp.net Mvc2实际上已经够慢的了，经过包装的asp.net mvc3实际上已经达到了泣鬼神的地步。当然有人会说这个是你写的糟糕，实施上都是初始化的项目，一行代码都木写啊。不知道那个能够解释下这个是为撒。&lt;/p&gt;&lt;p&gt;肯定有人会说Razor使用了新的编译模型，完善了WebForm的编译，让它更适合也更方便，所以速度慢，这点总是无稽之谈。因为Nhaml和Razor都是编译的视图引擎，人家的性能直接秒杀WebForm，一点都不慢。那么该到底做合解释呢？或者真的是Razor有问题吗？&lt;/p&gt;&lt;p&gt;跪求高手解答。找遍整个stackoverflow都木有很好的解释。不知道有木有人用到。有人用到了给点意见啊。如果能够达到WebForm的运行效率，一切就完美了。&lt;/p&gt;&lt;p&gt;不是刻意的拿着速度来说事，就是拿个布加迪威龙，最高时速100KM，也还不如个QQ。&lt;/p&gt;&lt;p&gt;用Razor真是伤不起啊。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2279355.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/12/07/2279355.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/12/04/2275474.html</id><title type="text">MVC与轻量化的WEB开发模型（1）</title><summary type="text">需要什么样的web开发模型呢？mvc,webform,or 其他。</summary><published>2011-12-04T07:21:00Z</published><updated>2011-12-04T07:21:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/12/04/2275474.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/12/04/2275474.html"/><content type="html">&lt;p&gt;提到MVC的时候总会有人想到ASP.NET MVC。其实倒不是，MVC更多的是一种思想。而ASP.NET MVC只是把这些给具体的实现了而已。MVC模式的缺点是由于它没有明确的定义，所以完全理解MVC模式并不是很容易。如果想看下MVC的一些理论知识，可以看下这篇。&lt;a href="http://zh.wikipedia.org/wiki/MVC"&gt;http://zh.wikipedia.org/wiki/MVC&lt;/a&gt;&lt;/p&gt;&lt;p&gt;而流程侧如下。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011120414455474.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;OK,举例说明什么是MVC.&lt;/p&gt;&lt;p&gt;1：去商店买东西，付款拿到东西走人。&lt;/p&gt;&lt;p&gt;2：在有的地方可以付款，然后拿小票，然后再去买东西走人。&lt;/p&gt;&lt;p&gt;付款到取货的流程就是控制器。这两种形式其实很贴近与WebForm和Mvc的现实模型。第一种任何地方都可以付然后直接取货，第二种统一到一起进行支付然后有小票发货。&lt;/p&gt;&lt;p&gt;尽管有许多人都捍卫着WebForm或者ASP.NET MVC，争辩到底那种方式好或者不好，都是以偏概全，因为条条大路通罗马。选择你自己的支付方式就行了。求同存异。现实中也没见的上面的两种支付方法灭绝。&lt;/p&gt;&lt;p&gt;网上说的很多WebForm的缺点，比如依赖HttpContent,难以单元测试，ViewState。现在这些早就被人解决了，webform依然可以进行mock，ViewState也可以关闭。而个人认为WebForm的缺点就是曾经看过了一个系统，后台aspx文件800多个，于是打开后台目录哥头晕了。&lt;/p&gt;&lt;p&gt;首先看下其他的语言对于mvc的web开发模型是如何设计的。为什么不使用ASP.NET MVC，可以看下本文最下边。&lt;/p&gt;&lt;p&gt;ROR（Ruby on Rails）的。这个几乎是所有mvc的鼻祖。ASP.NET MVC就是这个的C#版。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class IndexController &amp;lt; ApplicationController&lt;br/&gt;       def Index&lt;br/&gt;       end&lt;br/&gt;end&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;然后在 app\Views\Index\Index.rhtml 建立 Hello, world!&lt;/p&gt;&lt;p&gt;Ruby Sinatra的编码结构&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;get '/Index' { "Hello, world!" }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;Python django的编码结构&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;from django.http import HttpResponse&lt;br/&gt; def index(request):&lt;br/&gt;    return HttpResponse("Hello, world!")&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;Python bottle的编码结构&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;import bottle &lt;br/&gt;app = bottle.Bottle() &lt;br/&gt;&lt;br/&gt;@app.route('/index') &lt;br/&gt;def index(): &lt;br/&gt;    return "Hello, world!" &lt;br/&gt;&lt;br/&gt;if __name__ == "__main__":    &lt;br/&gt;    app.run()&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 看了那么多语言的表达。其实还是Sinatra和bottle表达的清晰点。相信很容易选择那种模型来做开发，直观的代码表达其实是件很重要的事情。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; net其实有一个框架，叫做Nancy。地址在这里。&lt;a href="https://github.com/NancyFx/Nancy"&gt;https://github.com/NancyFx/Nancy&lt;/a&gt;。很多大牛在开发维护。也是个不错的项目。可以比拟与spring.net.&lt;/p&gt;&lt;p&gt;它的编码结构是这样的。想玩下的自己去下吧。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class Module : NancyModule&lt;br/&gt;{&lt;br/&gt;    public Module()&lt;br/&gt;    {&lt;br/&gt;        Get["/greet/{name}"] = x =&amp;gt; {&lt;br/&gt;            return string.Concat("Hello ", x.name);&lt;br/&gt;        };&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;于是需求已经很明确了。&lt;br /&gt;&amp;nbsp;1.非常的高效。具备很好的可开发性。&lt;br /&gt;&amp;nbsp;2.方便测试代码。可以自由的Mock测试代码，最好能够自动单元测试。&lt;br /&gt;&amp;nbsp;3.代码表达很清晰。最好是Python bottle或者Sinatra那种，不需要动脑筋就知道代码在表达什么。&lt;br /&gt;&amp;nbsp;4.无需配置RouteMap，简单的路由表达。&lt;br /&gt;&amp;nbsp;5.支持IIS6,7,7.5，无需改动支持经典模式和集成模式，方便简单。（比如凡客怪异的url，可以用google搜索下&amp;ldquo;凡客 .mvc&amp;rdquo;就知道了。）&lt;br /&gt;&amp;nbsp;6.良好的插件机制。&lt;br /&gt;&amp;nbsp;7.实现上面所有的。&lt;/p&gt;&lt;p&gt;有了需求以及知道想要什么，一切都变得简单了，篇2就开始一点点的从新制造一个轻量化的轮子吧。实施上一个mvc结构的200行代码就over了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;题外话：为什么不使用ASP.NET MVC。。&lt;/p&gt;&lt;p&gt;ASP.NET MVC其实并不完美的原因在于，第一太大了，第二太慢了，特别是第一次打开，简直都无敌了。第三Ruby on Rails的Route都已经很糟糕了，结果ASP.NET MVC很生硬的搬过来了，继续糟糕，RouteMap太生硬了。比如/User/Content/View/1，必须要借助与RouteTable来管理路由请求，囧爆了。而在Python bottle侧就是@app.route('/User/Content/View/:id') ，Nancy就可以/User/Content/View/{id}这些可以直接定义在方法里来表达以及获取值。第四就是兼容性不够好。比如对于iis经典模式的支持。&lt;/p&gt;&lt;p&gt;所以ASP.NET MVC尽管很好，但是有些缺点也很致命。每个人都有每个人的理由，求同存异。但是mvc的思想，却很伟大。如果不正确，请指教。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2275474.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/12/04/2275474.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/11/21/2257159.html</id><title type="text">被娱乐化的博客园</title><summary type="text">最近很囧。以前的时候看园子，可以膜拜一堆大牛，不过最近发现N多大牛已经不再写博客了，像俺这种菜鸟没地学了。囧爆了。</summary><published>2011-11-21T06:15:00Z</published><updated>2011-11-21T06:15:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/11/21/2257159.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/11/21/2257159.html"/><content type="html">&lt;p&gt;最近很囧。以前的时候看园子，可以膜拜一堆大牛，不过最近发现N多大牛已经不再写博客了，像俺这种菜鸟没地学了。囧爆了。&lt;/p&gt;&lt;p&gt;做技术的时候就严谨的做技术，分享娱乐不反对，但是好歹写博客的时候专业点吧，实在有点太NG了。&lt;/p&gt;&lt;p&gt;然后总结结论:博文要牛B,博文Title名字就要更牛B,然后什么多线程，什么设计模式，什么异步操作，什么框架，什么某某架构，反正让人感觉很牛B就行了。&lt;/p&gt;&lt;p&gt;留个图纪念下吧。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011112114134890.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011112114141020.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011112114142411.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011112114143874.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;特地的纪念下娱乐化的园子主页。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2257159.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/11/21/2257159.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/11/15/2250032.html</id><title type="text">OCR识别图片的一些实例</title><summary type="text">试用OCR引擎识别58同城电话号码和京东商城商品价格的实现。</summary><published>2011-11-15T10:29:00Z</published><updated>2011-11-15T10:29:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/11/15/2250032.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/11/15/2250032.html"/><content type="html">&lt;p&gt;之前一直想做一个人脸识别的项目，结果最后被调离那个项目组，最后不了了之。最近在家休息，一哥们就让帮忙采集一些数据，因为有效的数据被图片化了，就需要一些简单的数字识别，然后决定用tesseract-ocr来实现。&lt;/p&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/tesseract-ocr/downloads/list"&gt;tesseract-ocr&lt;/a&gt;是一 个OCR引擎，在1985年到1995年由HP实验室开发，现在在Google。tesseract-ocr 3.0发布，支持中文。开源协议Apache License 2.0，在商业项目中还是可以值得一用的。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pixel-technology.com/freeware/tessnet2/"&gt;C#项目地址&lt;/a&gt;&lt;/p&gt;&lt;p&gt;OK.废话少说。代码贴上了。简单的测试了下，生产环境下自己封装下。OCR这些对资源的消耗特别严重，并且在现实情况下图片有噪点扭曲，失败的概率有点大,所以穷举的时候要注意对象代的管理。不过京东没有扭曲什么的，识别就简单多了。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;using System.Text;&lt;br/&gt;using System.Drawing;&lt;br/&gt;using System.IO;&lt;br/&gt;using System.Linq;&lt;br/&gt;using System.Net;&lt;br/&gt;using System.Threading;&lt;br/&gt;&lt;br/&gt;using tessnet2;&lt;br/&gt;namespace OCR&lt;br/&gt;{&lt;br/&gt;    class Program&lt;br/&gt;    {&lt;br/&gt;&lt;br/&gt;        static void Main(string[] args)&lt;br/&gt;        {&lt;br/&gt;            var imgpath = "http://image.58.com/showphone.aspx?t=v55&amp;amp;v=D438D3A47DA8384485F9AB46324E7BDB0";&lt;br/&gt;            var ocr = new Tesseract();&lt;br/&gt;            var result = new List&amp;lt;Word&amp;gt;(13);&lt;br/&gt;            var sb = new StringBuilder(20);&lt;br/&gt;            var ocrlength = 0;&lt;br/&gt;            var ocrcount = 0;&lt;br/&gt;            ocr.SetVariable("tessedit_char_whitelist", "￥-0123456789.");&lt;br/&gt;            ocr.Init(Path.Combine(Directory.GetCurrentDirectory(), @"Language"), "eng", false);&lt;br/&gt;&lt;br/&gt;            /*识别58并验证是否电话号码*/&lt;br/&gt;            Spot.Test(imgpath, ocr, out result);&lt;br/&gt;            ocrlength = result.Single&amp;lt;Word&amp;gt;().Text.Length;&lt;br/&gt;            while (ocrlength != 11) /// 检查是否匹配,实际环境中用正则&lt;br/&gt;            {&lt;br/&gt;                ocrcount++;&lt;br/&gt;                if (ocrcount % 5 != 0)&lt;br/&gt;                {&lt;br/&gt;                    Spot.Test(imgpath, ocr, out result);&lt;br/&gt;                    ocrlength = result.Single&amp;lt;Word&amp;gt;().Text.Length;&lt;br/&gt;                    while (ocrlength == 11)&lt;br/&gt;                    {&lt;br/&gt;                        Console.WriteLine("识别成功");&lt;br/&gt;                        result.Each&amp;lt;Word&amp;gt;(r =&amp;gt; Console.WriteLine(r.Text));&lt;br/&gt;                        Console.ReadLine();&lt;br/&gt;                        return;&lt;br/&gt;                    }&lt;br/&gt;                }&lt;br/&gt;                else&lt;br/&gt;                {&lt;br/&gt;                    Console.WriteLine("为了缓解服务器的压力,稍微休息5秒之后继续识别");&lt;br/&gt;                    Thread.Sleep(5000);//任务休息5秒&lt;br/&gt;                    GC.Collect();&lt;br/&gt;                    GC.Collect(2);&lt;br/&gt;                }&lt;br/&gt;                sb.Remove(0, sb.Length);&lt;br/&gt;                result.Each&amp;lt;Word&amp;gt;(r =&amp;gt; sb.Append(r.Text));&lt;br/&gt;                Console.WriteLine("第{0}次错误识别结果是{1}", ocrcount, sb.ToString());&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;            /* 识别京东价格&lt;br/&gt;            Spot.Test(imgpath,ocr,out result);&lt;br/&gt;            result.Each&amp;lt;Word&amp;gt;(r =&amp;gt; sb.Append(r.Text));&lt;br/&gt;            Console.WriteLine(sb.Replace('S', '5').Replace('s', '5'));&lt;br/&gt;            Console.ReadLine();&lt;br/&gt;             */&lt;br/&gt;        }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;    &lt;br/&gt;    public static class Spot&lt;br/&gt;    {&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 测试方法，实际环境中注意对象的回收。&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;remarks&amp;gt;&lt;br/&gt;        /// Spot.Test("","","");&lt;br/&gt;        /// &amp;lt;/remarks&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="url"&amp;gt;图片Url&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="ocr"&amp;gt;ocr的全局对象&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="result"&amp;gt;返回识别的结果&amp;lt;/param&amp;gt;&lt;br/&gt;        public static void Test(string url,Tesseract ocr,out List&amp;lt;Word&amp;gt; result)&lt;br/&gt;        {&lt;br/&gt;            using (var wc = new WebClient())&lt;br/&gt;            {&lt;br/&gt;                var img = wc.DownloadData(url);&lt;br/&gt;                using (var bitimage = new Bitmap(new MemoryStream(img), true))&lt;br/&gt;                {&lt;br/&gt;                    result = ocr.DoOCR(bitimage, Rectangle.Empty);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;br/&gt;    /// &amp;lt;summary&amp;gt;&lt;br/&gt;    /// &lt;br/&gt;    /// &amp;lt;/summary&amp;gt;&lt;br/&gt;    public static class Linq&lt;br/&gt;    {&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 扩展&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="col"&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name="handler"&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        public static void Each&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; col, Action&amp;lt;T&amp;gt; handler)&lt;br/&gt;        {&lt;br/&gt;            foreach (var item in col)&lt;br/&gt;                handler(item);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;运行的结果：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011111519283258.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011111518232419.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;需要玩下的点这里&lt;a href="http://files.cnblogs.com/imfunny/OCR.rar"&gt;下载&lt;/a&gt;项目吧。&lt;/p&gt;&lt;p&gt;&lt;br /&gt;OCR小贴士：&lt;/p&gt;&lt;p&gt;&lt;br /&gt;什么是OCR,点击这里查看。&lt;a href="http://files.cnblogs.com/imfunny/OCR.rar"&gt;&lt;span style="color: #800080;"&gt;点击下载&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;还存在那些OCR引擎？&lt;/p&gt;&lt;p&gt;答：&lt;/p&gt;&lt;p&gt;主要几个OCR还有Asprise-OCR，不过个人感觉这个识别不大准确，错误率太高。所以放弃了。&lt;/p&gt;&lt;p&gt;微软也有OCR，不过下次再介绍基于微软的Document组件的中文识别吧。&lt;a href="http://code.google.com/p/tesseract-ocr/downloads/list"&gt;tesseract-ocr&lt;/a&gt;实际上也是支持中文的。可以自己去看下了解下。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2250032.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/11/15/2250032.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/11/14/2248009.html</id><title type="text">UML和代码生成的一些思想和一些工具的分享</title><summary type="text">设计完善一些小工具来完善基础代码的开发，同时提高代码的规范。</summary><published>2011-11-14T02:29:00Z</published><updated>2011-11-14T02:29:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/11/14/2248009.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/11/14/2248009.html"/><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;UML是什么。实在不解释了。&lt;/p&gt;&lt;p&gt;代码生成是个不错的主意。根据设计好的数据库来让一些代码堆起来也更方便。&lt;/p&gt;&lt;p&gt;那么这个部分其实有点不合理的部分。&lt;/p&gt;&lt;p&gt;方式一：我们使用powerdesigner来设计数据库或者类图，然后生成出一个关系型数据库，然后再生成代码？&lt;/p&gt;&lt;p&gt;方式二：使用诸如Subsonic,EF这样具有Code Frist的库，写好类，然后生成出数据库？&lt;/p&gt;&lt;p&gt;这个过程就比如是鸡生蛋和蛋生鸡的过程，先有数据库再有代码，还是现有代码再有数据库？&lt;/p&gt;&lt;p&gt;Code First让一些代码完全变得是浪费力气，打了许多代码，手也不知道累不累，同时也更缺少一个整体的数据模型，也很难确定好一个完整的业务模型视图。这个其实我个人感觉是万丈高楼不打地基。&lt;/p&gt;&lt;p&gt;传统的手写代码其实还是很有自己的道理，有良好的关系视图，有好的设计，类图之间的关系清晰而明快，一眼就知道要干什么。但是依然UML图到数据库过程中，有些数据库自己的特性，而这部分又是代码不需要更改的。&lt;/p&gt;&lt;p&gt;OK.那就到了问题的重点了。UML包含了一个系统的基础对象片段，而特别是在关系型数据库开发中，类又被演变成了许多小的字段。那么为什么我们在设计UML的时候直接可以进行代码的转化。这样事实上编码的感觉更好。为什么？因为更加简单。&lt;/p&gt;&lt;p&gt;上面扯了半天淡，下面就分享工具吧。再之前发过没更改。如果使用Dapper的可以直接进行编码。&lt;/p&gt;&lt;p&gt;工具名称：EZDML。作者官网：&lt;a href="http://www.ezdml.com/"&gt;http://www.ezdml.com&lt;/a&gt;。用途设计类图，生成数据库，生成代码。&lt;/p&gt;&lt;p&gt;俺的作用呢，只是捋顺一些思想，简化的使用工具，然后写了点模板。让开发数据库来的更方便以及规范点。&lt;/p&gt;&lt;p&gt;模板是Delphi写的，贴下Model代码。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;(*[SettingsPanel]&lt;br/&gt;Control="Edit";Name="NameSpace";Caption="命名空间:";Value="Doodle.DataAccess.Entity"&lt;br/&gt;Control="Edit";Name="Table_Pix";Caption="表前缀:";Value="ex_"&lt;br/&gt;[/SettingsPanel]*)&lt;br/&gt;var&lt;br/&gt;  I: Integer;&lt;br/&gt;  clsName,info,sqlquery,sqlqueryParmar,StrTableName,strtemp,strparmartemp: string;&lt;br/&gt;  f: TCtMetaField;&lt;br/&gt;&lt;br/&gt;function getPublicName(N: string): string;&lt;br/&gt;begin&lt;br/&gt;  Result := N;&lt;br/&gt;  if (Result &amp;lt;&amp;gt; '') then&lt;br/&gt;    if Result[1] &amp;gt;= 'a' then&lt;br/&gt;      if Result[1] &amp;lt;= 'z' then&lt;br/&gt;        Result[1] := Chr(Ord(Result[1]) - (Ord('a') - Ord('A')));&lt;br/&gt;end;&lt;br/&gt;function GetDesName(p, n: string): string;&lt;br/&gt;begin&lt;br/&gt;  if p = '' then&lt;br/&gt;    Result := n&lt;br/&gt;  else&lt;br/&gt;    Result := p;&lt;br/&gt;end;&lt;br/&gt;function GFieldName(Fld: TCtMetaField): string;&lt;br/&gt;begin&lt;br/&gt;  Result := GetDesName(f.Name, f.DisplayName);&lt;br/&gt;end;&lt;br/&gt;function CaseToValue(idx: TCtFieldDataType): string;&lt;br/&gt;begin&lt;br/&gt;  case Integer(idx) of&lt;br/&gt;    0: Result := 'unknown';&lt;br/&gt;    1: Result := 'string';&lt;br/&gt;    2: Result := 'int';&lt;br/&gt;    3: Result := 'double';&lt;br/&gt;    4: Result := 'DateTime';&lt;br/&gt;    5: Result := 'bool';&lt;br/&gt;    6: Result := 'enum';&lt;br/&gt;    7: Result := 'var';&lt;br/&gt;    8: Result := 'object';&lt;br/&gt;    9: Result := 'List';&lt;br/&gt;    10: Result := 'function';&lt;br/&gt;    11: Result := 'EventHnadler';&lt;br/&gt;    12: Result := 'type';&lt;br/&gt;  else&lt;br/&gt;    Result := 'unknown';&lt;br/&gt;  end;&lt;br/&gt;end;&lt;br/&gt;function GFieldType(Fld: TCtMetaField): string;&lt;br/&gt;begin&lt;br/&gt;  if f.DataType = cfdtOther then&lt;br/&gt;    Result := f.DataTypeName&lt;br/&gt;  else if f.DataType = cfdtEnum then&lt;br/&gt;    Result := getPublicName(GFieldName(f)) + 'Enum'&lt;br/&gt;  else&lt;br/&gt;    Result := CaseToValue(f.DataType);&lt;br/&gt;end;&lt;br/&gt;procedure PrintContent;&lt;br/&gt;begin&lt;br/&gt;CurOut.Add('');&lt;br/&gt;CurOut.Add('    /// &amp;lt;summary&amp;gt;');&lt;br/&gt;CurOut.Add('    /// ' + F.GetFieldComments);&lt;br/&gt;CurOut.Add('    /// &amp;lt;/summary&amp;gt;');&lt;br/&gt;CurOut.Add('    public ' + GFieldType(F) + ' '+ getPublicName(F.Name) +'');&lt;br/&gt;CurOut.Add('    {');&lt;br/&gt;CurOut.Add('       get;');&lt;br/&gt;CurOut.Add('       set;');&lt;br/&gt;CurOut.Add('    }');&lt;br/&gt;end;&lt;br/&gt;begin&lt;br/&gt;  with CurTable do&lt;br/&gt;  begin&lt;br/&gt;    StrTableName := Name;&lt;br/&gt;    clsName := Name;        ///表名称&lt;br/&gt;    info := GetTableComments; ///表简介&lt;br/&gt;    clsName := StringReplace(clsName,'ex_','',[rfReplaceAll])&lt;br/&gt;    clsName  := getPublicName(clsName);&lt;br/&gt;&lt;br/&gt;    CurOut.Add('using System;');&lt;br/&gt;    CurOut.Add('');&lt;br/&gt;    CurOut.Add('namespace ' + GetParamValueDef('NameSpace','User'));&lt;br/&gt;    CurOut.Add('{');&lt;br/&gt;    CurOut.Add('');&lt;br/&gt;    clsName := Name;&lt;br/&gt;    CurOut.Add('  /// &amp;lt;summary&amp;gt;');&lt;br/&gt;    CurOut.Add('  /// ' + Info + '对象描述');&lt;br/&gt;    CurOut.Add('  /// &amp;lt;/summary&amp;gt;');&lt;br/&gt;    clsName := StringReplace(clsName,'ex_','',[rfReplaceAll])&lt;br/&gt;    clsName  := getPublicName(clsName);&lt;br/&gt;    CurOut.Add('  public class ' + clsName + 'Info');&lt;br/&gt;    CurOut.Add('  {');&lt;br/&gt;    CurOut.Add('');&lt;br/&gt;    CurOut.Add('    /// &amp;lt;summary&amp;gt;');&lt;br/&gt;    CurOut.Add('    /// ' + Info + '构造函数');&lt;br/&gt;    CurOut.Add('    /// &amp;lt;/summary&amp;gt;');&lt;br/&gt;    CurOut.Add('    public ' + clsName + 'Info()');&lt;br/&gt;    CurOut.Add('    {');&lt;br/&gt;    CurOut.Add('        ///');&lt;br/&gt;    CurOut.Add('    }');&lt;br/&gt;    for I := 0 to MetaFields.Count - 1 do&lt;br/&gt;    begin&lt;br/&gt;      f := MetaFields[I];&lt;br/&gt;      PrintContent;&lt;br/&gt;    end;&lt;br/&gt;    CurOut.Add('');&lt;br/&gt;    CurOut.Add('  }');&lt;br/&gt;    CurOut.Add('}');&lt;br/&gt;    CurOut.Add('');&lt;br/&gt;end;&lt;br/&gt;end.&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;如图下面的代码就生成了。具体的代码，数据库都伴随着类图设计完毕之后直接出来。这个时候数据库以及脱离和代码的关系。唯一的连接也就是类图了。这样的结构其实更很清晰。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011111410353279.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011111410313793.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011111410315350.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/imfunny/Templates.rar"&gt;点击模板下载&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/imfunny/DBA.rar"&gt;点击下载工具&lt;/a&gt;&lt;/p&gt;&lt;p&gt;工具下载好之后把里面的Template文件给替换成上面的模版文件就一切OK了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2248009.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/11/14/2248009.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/11/01/2232120.html</id><title type="text">再谈创业话题（1）</title><summary type="text">创业和工作完全不是一个概念。创业在乎的是您的付出，工作在乎的是您的收入。</summary><published>2011-11-01T11:15:00Z</published><updated>2011-11-01T11:15:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/11/01/2232120.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/11/01/2232120.html"/><content type="html">&lt;p&gt;创业是个很神圣的词。其实一直都不想懈怠这个词。不过这个词现在很流行。&lt;/p&gt;&lt;p&gt;可是很多的创业真的是伪创业。他们总是很意淫与创业的成功，他们根本就不知道创业是什么，在他们眼里的创业成功之后随之而来的富有，让别人瞩目，荣光，有一天衣锦还乡像别人证明自己，让别人仰视自己。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011110119110038.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;真正的创业是付出的过程。您付出了许多的努力，终于有天实现了梦想，或许赚到了足够的多的钱，没有穷奢极欲，依然用心的去经营，创业只是为了一些梦想得以实现的过程或者实现自己的过程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;几年前的时候开始接到好友的邀请，然后开始创业之旅。当时的团队薪资水平是M型的，中层较高，底层和高层最低，公司的总经理大概一个月就不到4K，月薪总额不得超过10W，平均低于外面的公司百分之三十以上，资源也少的可怜，却有无偿加班通宵加班的员工。公司消耗掉183W的时候，一年后的盈利却达到50W，之后投资者大爆发之后，公司再也不缺钱，团度的成员都积极踊跃的薪水破万，一年时间花掉了几千万，却发现部分部门连盈利50W都很困难，团队迅速的变成了养老的团队，没有了一点朝气，几层的办公楼上下几乎从来都不来往，结构复杂而臃肿。项目批量化的流产。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;创业，就倾尽所有。一边拿着高的工资一边去创业，这种团队能够成事的概率几乎小于千分之一。团队的成功需要保持团队整体的饥饿感，这些饥饿不是对于金钱与物质资源的饥饿，而是对于未来的渴望，十五个人以上的团队，如果信仰一致，产品优秀，有着很强的毅力，几乎没有失败的可能。一群饥饿狼才会有着充分的战斗力。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;不要太在乎别人的看法，您可以拿着2K的薪水来保持1W薪水的范儿。什么理想很丰满，现实很骨感，不过是人的借口。现实就是毛毛菜一块五一斤，橘子两块五，800公里以上燃油附加税130，食品之类越长越高，即使房价再高也不是说没住的，依然每天生活工作而已，也没见得有多少人露宿街头。所以现实很美好，只是人贪图安逸，找点借口，来拟补对于未来的恐惧。人其实怕的不是现实，而是未来。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;创业和工作完全不是一个概念。创业在乎的是您的付出，工作在乎的是您的收入。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;创业，请勇敢。别担心以后的身家性命养老小孩的问题，一切总会好起来的，社会的资源总在承上启下的过度，年轻的时候您总是最糟糕的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;推荐一本书，小时候读的。《谁动了我的奶酪》&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;推荐一句话，有志者 事竟成 破釜沉舟 百二秦关终属楚 苦心人 天不负 卧薪尝胆 三千越甲可吞吴。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;总之：看过后忘记。别听我的瞎扯淡。做您该做的事情。切忌。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;关于技术人员为什么不适合创建可以看看这篇。&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/07/11/2103063.html"&gt;http://www.cnblogs.com/imfunny/archive/2011/07/11/2103063.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/187666/2011110119122316.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2232120.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/11/01/2232120.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/imfunny/archive/2011/10/15/2212998.html</id><title type="text">从MVC的MapRoute扩展到Sinatra的编码结构</title><summary type="text">ASP.NET MVC 引发出更加前卫的Sinatra式编码。很值得Web开发人员和架构师阅读。</summary><published>2011-10-15T06:19:00Z</published><updated>2011-10-15T06:19:00Z</updated><author><name>imfunny</name><uri>http://www.cnblogs.com/imfunny/</uri></author><link rel="alternate" href="http://www.cnblogs.com/imfunny/archive/2011/10/15/2212998.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/imfunny/archive/2011/10/15/2212998.html"/><content type="html">&lt;p&gt;ASP.NET MVC 真的很不错。很适合开发和测试。太犀利了，用着很容易入迷。但是实在不习惯里面的MapRoute和RegisterRoutes。配置来配置去，一出错就要拿RouteDebug去兢兢业业的测试，如果短路参数短还好，如果参数多MapRoute到方法真要人老命。&lt;/p&gt;&lt;p&gt;为了改善这个问题，有了什么TypeRoute还有什么SCanRoute之类的注册方法。不过觉得实在不大好用。果断放弃。然后就看到一个扩展这快的方法，用的很爽。前段时间在github上看到这样一个扩展。大家遇到这些问题的时候直接贴代码解决之。&lt;/p&gt;&lt;p&gt;首先&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Web;&lt;br/&gt;&lt;br/&gt;namespace Oxite.Web.Routing&lt;br/&gt;{&lt;br/&gt;    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]&lt;br/&gt;    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]&lt;br/&gt;    public class RouteOrderAttribute : Attribute&lt;br/&gt;    {&lt;br/&gt;        public RouteOrderAttribute(int order)&lt;br/&gt;        {&lt;br/&gt;            Order = order;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public int Order { get; set; }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;然后&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Linq;&lt;br/&gt;using System.Linq.Expressions;&lt;br/&gt;using System.Reflection;&lt;br/&gt;using System.Text.RegularExpressions;&lt;br/&gt;using System.Web;&lt;br/&gt;using System.Web.Mvc;&lt;br/&gt;using System.Web.Routing;&lt;br/&gt;&lt;br/&gt;namespace Oxite.Web.Routing&lt;br/&gt;{&lt;br/&gt;    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]&lt;br/&gt;    public class StrongRoute : Route&lt;br/&gt;    {&lt;br/&gt;        public StrongRoute() : base(null, new MvcRouteHandler())&lt;br/&gt;        {&lt;br/&gt;            Constraints = new RouteValueDictionary();&lt;br/&gt;            Defaults = new RouteValueDictionary();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public string Key { get; set; }&lt;br/&gt;&lt;br/&gt;        public void Register(RouteCollection routes)&lt;br/&gt;        {&lt;br/&gt;            routes.Add(this.Key, this);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static StrongRoute MapRegex&amp;lt;TController&amp;gt;(string url, Expression&amp;lt;Func&amp;lt;TController, ActionResult&amp;gt;&amp;gt; action)&lt;br/&gt;            where TController : Controller&lt;br/&gt;        {&lt;br/&gt;            return MapRegex(url, action, false);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static StrongRoute MapRegex&amp;lt;TController&amp;gt;(string url, Expression&amp;lt;Func&amp;lt;TController, ActionResult&amp;gt;&amp;gt; action, bool useDefaults)&lt;br/&gt;            where TController : Controller&lt;br/&gt;        {&lt;br/&gt;            return Map(new Regex(url), action, useDefaults);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static StrongRoute Map&amp;lt;TController&amp;gt;(Regex url, Expression&amp;lt;Func&amp;lt;TController, ActionResult&amp;gt;&amp;gt; action, bool useDefaults)&lt;br/&gt;            where TController : Controller&lt;br/&gt;        {&lt;br/&gt;            throw new NotImplementedException();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static StrongRoute Map&amp;lt;TController&amp;gt;(string url, Expression&amp;lt;Func&amp;lt;TController, ActionResult&amp;gt;&amp;gt; action)&lt;br/&gt;            where TController : Controller&lt;br/&gt;        {&lt;br/&gt;            return Map(url, action, false);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static StrongRoute Map&amp;lt;TController&amp;gt;(string url, Expression&amp;lt;Func&amp;lt;TController, ActionResult&amp;gt;&amp;gt; action, bool useDefaults)&lt;br/&gt;            where TController : Controller&lt;br/&gt;        {&lt;br/&gt;            if (action == null)&lt;br/&gt;                throw new ArgumentException("Action must be a method call");&lt;br/&gt;&lt;br/&gt;            var body = action.Body as MethodCallExpression;&lt;br/&gt;&lt;br/&gt;            if (body == null)&lt;br/&gt;                throw new ArgumentException("Expression must be a method call");&lt;br/&gt;&lt;br/&gt;            if (body.Object != action.Parameters[0])&lt;br/&gt;                throw new ArgumentException("Method call must target lambda argument");&lt;br/&gt;&lt;br/&gt;            var route = new StrongRoute { Constraints = null };&lt;br/&gt;            var actionName = body.Method.Name;&lt;br/&gt;            var attributes = body.Method.GetCustomAttributes(typeof(ActionNameAttribute), false);&lt;br/&gt;            var controllerName = typeof(TController).Name;&lt;br/&gt;&lt;br/&gt;            if (attributes.Length &amp;gt; 0)&lt;br/&gt;                actionName = ((ActionNameAttribute)attributes[0]).Name;&lt;br/&gt;&lt;br/&gt;            if (controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))&lt;br/&gt;                controllerName = controllerName.Remove(controllerName.Length - 10, 10);&lt;br/&gt;&lt;br/&gt;            route.Defaults.Add("controller", controllerName);&lt;br/&gt;            route.Defaults.Add("action", actionName);&lt;br/&gt;            route.Url = url;&lt;br/&gt;            route.Key = controllerName + ":" + actionName;&lt;br/&gt;&lt;br/&gt;            if (!useDefaults) return route;&lt;br/&gt;&lt;br/&gt;            for (int i = 0; i &amp;lt; body.Arguments.Count; i++)&lt;br/&gt;            {&lt;br/&gt;                var name = body.Method.GetParameters()[i].Name;&lt;br/&gt;                var value = ((ConstantExpression)body.Arguments[i]).Value;&lt;br/&gt;                if (value != null)&lt;br/&gt;                    route.Defaults.Add(name, value);&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            return route;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;    }&lt;br/&gt;}&lt;/div&gt;&lt;p&gt;再来一个。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;using System;&lt;br/&gt;using System.Collections.Generic;&lt;br/&gt;using System.Linq;&lt;br/&gt;using System.Reflection;&lt;br/&gt;using System.Web;&lt;br/&gt;using System.Web.Mvc;&lt;br/&gt;using System.Web.Routing;&lt;br/&gt;&lt;br/&gt;namespace Oxite.Web.Routing&lt;br/&gt;{&lt;br/&gt;    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]&lt;br/&gt;    public static class StrongRouteRegistrar&lt;br/&gt;    {&lt;br/&gt;        public static void MapFrom&amp;lt;TContainer&amp;gt;(RouteCollection routes) where TContainer : Controller&lt;br/&gt;        {&lt;br/&gt;            routes.MapFrom(typeof(TContainer));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static void MapFrom(this RouteCollection routes,Type t)&lt;br/&gt;        {&lt;br/&gt;            var discoveredRoutes = new SortedList&amp;lt;int, StrongRoute&amp;gt;();&lt;br/&gt;            var fields = from type in t.GetMembers()&lt;br/&gt;                         where&lt;br/&gt;                             type.MemberType.Equals(MemberTypes.Field) &amp;amp;&amp;amp;&lt;br/&gt;                             typeof(StrongRoute).IsAssignableFrom(((FieldInfo)type).FieldType)&lt;br/&gt;                         select type;&lt;br/&gt;&lt;br/&gt;            foreach (var field in fields)&lt;br/&gt;            {&lt;br/&gt;                var routeOrder = (RouteOrderAttribute)field.GetCustomAttributes(typeof (RouteOrderAttribute), false).FirstOrDefault();&lt;br/&gt;                var sr = ((FieldInfo)field).GetValue(null) as StrongRoute;&lt;br/&gt;                if (sr == null) continue;&lt;br/&gt;                sr.Key = t.Name + ":" + field.Name + "_" + sr.Key;&lt;br/&gt;&lt;br/&gt;                var order = int.MaxValue;&lt;br/&gt;                if (routeOrder != null)&lt;br/&gt;                {&lt;br/&gt;                    order = routeOrder.Order;&lt;br/&gt;                }&lt;br/&gt;                else&lt;br/&gt;                {&lt;br/&gt;                    while (discoveredRoutes.ContainsKey(order))&lt;br/&gt;                        order--;&lt;br/&gt;                }&lt;br/&gt;                discoveredRoutes.Add(order, sr);&lt;br/&gt;            }&lt;br/&gt;            foreach(var route in discoveredRoutes)&lt;br/&gt;                route.Value.Register(routes);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;调用方法&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;        public static class RssRouteConfig&lt;br/&gt;        {&lt;br/&gt;            [RouteOrder(2)]&lt;br/&gt;            public static readonly StrongRoute List = StrongRoute.Map&amp;lt;RssController&amp;gt;("Rss/{id}/{name}", c =&amp;gt; c.List(0,0));&lt;br/&gt;&lt;br/&gt;            [RouteOrder(1)]&lt;br/&gt;            public static readonly StrongRoute Category = StrongRoute.Map&amp;lt;RssController&amp;gt;("Rss/{id}/{name}/{values}", c =&amp;gt; c.Category(0, string.Empty, string.Empty));&lt;br/&gt;        }&lt;br/&gt; &lt;/div&gt;&lt;p&gt;最后直接注册路由&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt; routes.MapFrom(typeof(RssRouteConfig));&lt;br/&gt;&lt;/div&gt;&lt;p&gt;这样的RegisterRoutes就一切搞定。&lt;/p&gt;&lt;p&gt;&amp;nbsp;实在太厌恶配置来配置去的东东了。代码也简化了不少。方法也更加直观。&lt;/p&gt;&lt;p&gt;&amp;nbsp;其实在这里已经产生了更加精致的Web编码结构。&lt;/p&gt;&lt;p&gt;&amp;nbsp;RssRouteConfig方法里提供了一个Url到方法的映射。也实际上做的一件事情就是把UrlTemplate给添加到了路由表中，然后绑定到路由表中的方法。&lt;/p&gt;&lt;p&gt;&amp;nbsp;那么Mounting Point通过安装一个RssRouteConfig里面的配置方法到路由表中，于是直接移交请求到方法中。于是就自然的引出了一种新的思想。Ruby中的Sinatra。想了解的可以看下这篇。&lt;a href="http://www.infoq.com/cn/articles/sinatra-intro"&gt;http://www.infoq.com/cn/articles/sinatra-intro&lt;/a&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;ASP.NET MVC 中 其实就是Rails的NET版本。而现在随着Sinatra的兴起，也有了许多Sinatra结构的编码。比如Nancy。Nancy实在太犀利了。&lt;/p&gt;&lt;p&gt;&lt;span class="p"&gt;&lt;span style="color: #555555;"&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp; Nancy的编码是这样的。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class HelloWorldModule : NancyModule&lt;br/&gt;{ &lt;br/&gt;    private static readonly string DbPath = System.IO.Path.Combine( System.IO.Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory), @"App_Data\HelloNancy.sdf");&lt;br/&gt;    &lt;br/&gt;    public HelloWorldModule()&lt;br/&gt;    {&lt;br/&gt;        Get["/"] = parameters =&amp;gt; &lt;br/&gt;        {&lt;br/&gt;            return "Hello, Nancy!";&lt;br/&gt;        };&lt;br/&gt;        &lt;br/&gt;        Get["/test"] = parameters =&amp;gt;&lt;br/&gt;        {&lt;br/&gt;            return "This is the Test route";&lt;br/&gt;        };&lt;br/&gt;        &lt;br/&gt;        Get["/spark"] = parameters =&amp;gt;&lt;br/&gt;        {&lt;br/&gt;            var db = Database.OpenFile(DbPath);&lt;br/&gt;            Person model = db.Persons.FindById(1);&lt;br/&gt;            if (model == null)&lt;br/&gt;                model = new Person { FirstName = "Jane", LastName = "Doe" };&lt;br/&gt;            return View["spark", model];&lt;br/&gt;        };&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;代码简单。完整的请求驱动。实在很优秀的一个web开发框架。有兴趣的体验下吧。项目地址&lt;a href="https://github.com/NancyFx/Nancy"&gt;https://github.com/NancyFx/Nancy&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/imfunny/aggbug/2212998.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/imfunny/archive/2011/10/15/2212998.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
