<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_喜乐的ASP.NET(Alex Song)</title><subtitle type="text">探索如何在Net平台下健康快乐的成长</subtitle><id>http://feed.cnblogs.com/blog/u/82801/rss</id><updated>2011-12-20T23:22:34Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/82801/rss"/><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/12/21/2295386.html</id><title type="text">非常好玩的C#/.NET 基础 -- 安全有效引发事件</title><summary type="text">最近在网上看到一篇很好的文章, 讨论如何安全有效的引发事件.也许你不一定要用到下面相同的解决方案, 但是至少你应该知道在引发事件时候需要考虑的问题.引发事件的问题引发事件是一个非常容易的事情, 但是的确也有它的误区. 让我们举个例子. 假设我们写个消息接收器, 每当我们收到一个新消息, 我们引发一个包含了新消息的事件 MessageReceived.安装我们通常的方法,就是:public class MessageReceivedEventArgs : EventArgs{ // 接收到的消息 public string Message { get; private set; } ...</summary><published>2011-12-20T23:15:00Z</published><updated>2011-12-20T23:15:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/21/2295386.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/21/2295386.html"/><content type="html">&lt;p&gt;最近在网上看到一篇很好的文章, 讨论如何安全有效的引发事件.&lt;/p&gt;&lt;p&gt;也许你不一定要用到下面相同的解决方案, 但是至少你应该知道在引发事件时候需要考虑的问题.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;引发事件的问题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;引发事件是一个非常容易的事情, 但是的确也有它的误区. 让我们举个例子. 假设我们写个消息接收器, 每当我们收到一个新消息, 我们引发一个包含了新消息的事件 &lt;strong&gt;MessageReceived.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;安装我们通常的方法,就是:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; MessageReceivedEventArgs : EventArgs&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 接收到的消息&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Message { get; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; set; }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 架构 ReceivedEventArgs &lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; MessageReceivedEventArgs(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; message)&lt;br /&gt;    {&lt;br /&gt;        Message = message;&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;接下来, 我们创建一个非线程安全访问的类&lt;strong&gt;UnsafeMessenger&lt;/strong&gt;来实现这个消息同时通知所有的订阅者(subscriber).&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; UnsafeMessenger&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; EventHandler&amp;lt;MessageReceivedEventArgs&amp;gt; MessageReceived;&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 当收到新消息时调用&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; OnNewMessage(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; message)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (MessageReceived != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            MessageReceived(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MessageReceivedEventArgs(message));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;注意, 通常&lt;em&gt;OnNewMessage() &lt;/em&gt;是私有的, 但是在这里为了测试的方便,我们将它设为public.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;大功告成!! 是吗? 事实上, 如果我们是单线程的程序, 这的确已经足够, 但是这是非线程安全访问(thread-safe).&lt;/p&gt;&lt;p&gt;为什么? 想想, 订阅者可以任何时候订阅或者取消订阅. 比如,我们当前有一个订阅者, 那么当接收到一个新消息,执行到这一句时:&lt;/p&gt;if (MessageReceived != null)肯定会通过, 因为有一个订阅者, 如果这个时候, 这名订阅者执行了取消订阅的命令:myMessenger.MessageReceived -= MyMessageHandler;&amp;nbsp;那么&lt;strong&gt;MessageReceived&lt;/strong&gt;委托 就为null 了, &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//已经通过了这个IF语句&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (MessageReceived != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//MessageReceived委托 就为null 了, 但是我们将要执行这句&lt;/span&gt;&lt;br /&gt;    MessageReceived(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MessageReceivedEventArgs(message));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;这个时候, 就会引发&lt;strong&gt;NullReferenceException.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;方案一: 锁住它, 锁机制&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;当允许多线程的时候, 我们可以用锁机制来避免一个用户在我们执行事件时订阅或者取消订阅, 或者在用户执行操作时, 不能引发事件.&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; SyncronizedMessenger : IMessenger&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 委托和锁&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; EventHandler&amp;lt;MessageReceivedEventArgs&amp;gt; _messageReceived;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; _raiseLock = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 订阅/取消订阅的锁机制&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; EventHandler&amp;lt;MessageReceivedEventArgs&amp;gt; MessageReceived&lt;br /&gt;    {&lt;br /&gt;        add { &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (_raiseLock) { _messageReceived += &lt;span style="color: #0000ff;"&gt;value&lt;/span&gt;; } }&lt;br /&gt;        remove { &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (_raiseLock) { _messageReceived -= &lt;span style="color: #0000ff;"&gt;value&lt;/span&gt;; } }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 引发事件的锁机制&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; OnNewMessage(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; message)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (_raiseLock)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (_messageReceived != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                _messageReceived(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MessageReceivedEventArgs(message));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;这样, 如果有人试图订阅或取消订阅时, 必须要等待OnNewMessage事件的完成, 反之亦然.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;方案二: 永不为空, 默认加载一个订阅者&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们面临的主要问题是有可能委托为空. 那么如果事先加载一个委托,会怎么样?&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; EmptySubscriberMessenger : IMessenger&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 立刻给它一个空的订阅者&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; EventHandler&amp;lt;MessageReceivedEventArgs&amp;gt; MessageReceived = (s, e) =&amp;gt; { };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 现在根本无需检查是否为 null!&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; OnNewMessage(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; message)&lt;br /&gt;    {&lt;br /&gt;        MessageReceived(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MessageReceivedEventArgs(message));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;方案三: 创建一个本地的委托副本&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;另外一个简单的方案, 也就是很多人都在使用的, 微软建议的模式: 创建一个本地的委托副本.&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; LocalCopyMessenger : IMessenger&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; EventHandler&amp;lt;MessageReceivedEventArgs&amp;gt; MessageReceived;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;// 当我们引发事件时, 做一个副本&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; OnNewMessage(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; message)&lt;br /&gt;    {&lt;br /&gt;        var target = MessageReceived;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (target != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            target(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MessageReceivedEventArgs(message));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;下面是以上四种方法的效率, 在执行10亿次的重复操作时:&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112210715185900.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot074" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112210715201605.jpg" alt="ScreenShot074" width="824" height="114" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;以上参考翻译自:&amp;nbsp; &lt;a href="http://geekswithblogs.net/BlackRabbitCoder/archive/2011/12/01/c.net-fundamentals-safely-and-efficiently-raising-events.aspx"&gt;C#/.NET Fundamentals: Safely and Efficiently Raising Events&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;小结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;有一种编程方式叫 Cargo Cult Programming, 中文名:&amp;nbsp; 货物崇拜编程. 维基定义为"&lt;/p&gt;&lt;p&gt;其特征为不明就里地仪式性地使用代码或程序架构。货物崇拜编程通常是一个程序员既没理解他要解决的 bug，也没理解表面上的解决方案的典型表现。&lt;/p&gt;&lt;p&gt;这个名词有时也指不熟练的或没经验的程序员从某处拷贝代码到另一处，却不太清楚其代码是如何工作的，或者不清楚在新的地方是否需要这段代码。也可以指不正确或过份的应用设计模式，代码风格或编程方法，却对其原理不明就里。"&lt;/p&gt;&lt;p&gt;我承认在"高举实用主义"(敝人的&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/20/2294125.html"&gt;如何做一个快乐的ASP.NET程序员&lt;/a&gt;) 的年代, 为了效率, 我也经常这样做.--试问谁有时间给第三方控件做测试?&lt;/p&gt;&lt;p&gt;自从这个创建本地委托副本的方案被大牛们推荐后, 大家都在用, 有人也不一定明白它背后的故事.&lt;/p&gt;&lt;p&gt;有时间的朋友们聊聊.net中的野史, 谈笑间扩充一点编程的能力,总比聊哪个明星又被潜规则了要有益处. 哈哈~~~&lt;/p&gt;&lt;p&gt;&lt;strong&gt;本年总结 + 新年祝福&lt;/strong&gt;&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;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/02/09/1950044.html"&gt;有些时候，作为程序员，我们只是需要被重启一下&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/05/19/2050670.html"&gt;码斗士的修炼之路 -- 如何保持并提升战斗力&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/20/2294125.html"&gt;如何做一个快乐的ASP.NET程序员&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;* C# 语言&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/02/12/1951793.html"&gt;写出优雅简明代码的论题集 -- Csharp(C#)篇[1]&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/02/16/1955695.html"&gt;写出优雅简明代码的论题集 -- Csharp(C#)篇[2]&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/03/22/1990916.html"&gt;再说Csharp(C#) &amp;rdquo;整洁代码&amp;rdquo;那些事 -- 变小[1]&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/09/27/2192710.html"&gt;C# 中奇妙的函数&amp;ndash;8. String Remove() 和 Replace()&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/09/17/2179380.html"&gt;C# 中奇妙的函数&amp;ndash;7. String Split 和 Join&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/08/27/2155268.html"&gt;C# 中奇妙的函数&amp;ndash;6. 五个序列聚合运算(Sum, Average, Min, Max,Aggregate)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/08/25/2152743.html"&gt;C# 中奇妙的函数&amp;ndash;5. Nullable 静态类&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/06/04/2072415.html"&gt;C# 中奇妙的函数 -- 4. Empty, DefaultIfEmpty, Count&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/05/17/2048319.html"&gt;C# 中奇妙的函数 -- 3. 联接序列的五种简单方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/05/14/2046029.html"&gt;C# 中奇妙的函数 -- 2. First 和 Single -- 你是她心中的第一还是唯一?&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/03/31/2000528.html"&gt;C# 中奇妙的函数 -- 1. ToLookup&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/24/2261105.html"&gt;不可不知的C#基础 4. 延迟加载 -- 提高性能&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/29/2228317.html"&gt;不可不知的C#基础 3. 线程浅析&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/15/2212780.html"&gt;不可不知的C#基础 2. -&amp;ndash;从 struct 和 class的异同 说开去&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/13/2209603.html"&gt;不可不知的C#基础 1. -- Extension 扩展方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;* 其他&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/30/2268516.html"&gt;从 Comparison/Converter 到Func 的进化&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/13/2285506.html"&gt;从 Linq Queries 快速生成数据 HTML, EXCEL, CSV 报表&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/14/2287061.html"&gt;DynamicXml -- 动态读取操作XML (一个从XML到Object的通用实现)&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2295386.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/21/2295386.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/12/20/2294125.html</id><title type="text">如何做一个快乐的ASP.NET程序员</title><summary type="text">首先我想解释一下标题中两个关键字: "快乐", "ASP.NET程序员".有的人想成为一个"杰出"的程序员, 或者"资深"的程序员, 简单来说就是"大牛"级的人物 -- 但是本文不是针对此种发展方向不是说我不鼓励大家朝这方向走, 而是对我而言我更看重"快乐"的本身. -- 而且除非你是天才导致"杰出"或者"资深"是同时需要正确的态度和漫长的过程.那么为什么单单谈"ASP.NET程序员" -- 这是对我本人的写照, 也</summary><published>2011-12-19T20:37:00Z</published><updated>2011-12-19T20:37:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/20/2294125.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/20/2294125.html"/><content type="html">&lt;p&gt;首先我想解释一下标题中两个关键字: "快乐", "ASP.NET程序员".&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;那么为什么单单谈"ASP.NET程序员" -- 这是对我本人的写照, 也是对一类人的写照 -- 我们跟着微软混, 在微软的平台上面选择不同的地域,建立自己的城池. -- 不管是出于无奈还是值得骄傲的选择. -- 很大的程度上来说, 微软的举动和变革多少会影响我们的发展前途.&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;1. 保持一颗谦卑且自信的心. 这是什么意思?&amp;nbsp; 谦卑意味着, 承认自己的有限, 承认自己的不足. 自信代表, 相信都是人设计的逻辑和框架理论, 只要花时间就可以学得会.&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;2. 与人分享你的"财富". 作为一个程序员, 什么是你的财富? -- "知识", "经验". 在网上社区和同事中分享你的财富, 会让你更富有.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;曾经听过一个讲座. 说贫穷的人关注自己, 中产阶级挤压别人抬高自己, 富有的人影响别人.&amp;nbsp; 请注意, 这里的贫穷和富有不单单是指金钱,内心富有的人不会只关注自己,也不会老想着把别人压下去. 我看到很多喜欢和别人分享自己"财富"的人, 他们一天天的成长, 不断的进步, 也帮助着更多的人.&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;3. 高举实用主义,不追求理论的卓越. 作为一名"ASP.NET"程序员. -- 实用在我看来是很重要的. 从.net1.0 到现在.net本身不断进步完善, 我们用的工具, 设计模式和编码的方式都在变化. 如果你想"了解全盘"或者"追求完美",那么你就完了.&lt;/p&gt;&lt;p&gt;.NET1.0中很多的东西到了现在都不用了, 以前花了很多时间去学这部分的, 如果没有用上的确浪费了.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;满足客户或者老板目前的需求, 学习目前项目需要的知识是"实用主义"的本质. 接受项目中代码的不完善, 接受系统的不完美.&lt;/p&gt;&lt;p&gt;看过很多鼓吹"追求卓越"方面的文章, 对于.NET项目来说, 我认为是一种误区. Google 和 Apple.com 都有无法访问的时候.&lt;/p&gt;&lt;p&gt;我们只能在有限时间和有限资源的情况下, 做到最好. -- 别把自己逼疯了.&lt;/p&gt;&lt;p&gt;对于做管理的或者做老板的读者, 我想说的, 大家都在这潭子上混, 退一步海阔天空. 很多时候辛苦做出的系统, 客户未必用的顺手, 也未必真的可以用很久.&lt;/p&gt;&lt;p&gt;以前在HSBC上班时, 听说有个程序员代码写错了, 导致银行赔了10个亿, 银行都没有解雇这哥们 -- 因为这不是他一个人的错, 还牵涉到测试人员和一层层质量把关的问题.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;说明一下, 我并非说软件质量不重要, 而是说要关注在实际需求上, 而非不切实际的要求.&lt;/p&gt;&lt;p&gt;[特例: 听说有些公司有些老板, 对程序员的要求很苛刻, 我认为可以尝试着跟他们沟通, 往公司里多注入一些"幽默感"]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;4. 关注新事物, 立足不变的基础. 永远不要放弃对新事物的关注. 常常上上cnblogs, 订阅各类你喜欢的feed, 很多时候一个简单的新东西会节省你几天的摸索.&lt;/p&gt;&lt;p&gt;但是光光学新东西是不够的. 很多基础的东西, 象C#语言本身, 设计模式等等, 一定要学. 不知道为什么还有人在评论asp.net程序员是拖控件的....&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;5. 了解自己, 善于使用已有的代码. 有这样一个故事, 客户向程序员说他的需求, 一个大牛立刻飞快的敲着键盘开始架构, 开始以每秒80公里的速度编程; 另外一个大牛说:"等等, 我做过这个东西".&lt;/p&gt;&lt;p&gt;不管是你以前做过, 还是你可以在网上找到代码. 那都是你的资产. 花一点点时间整理你的资产.&lt;/p&gt;&lt;p&gt;[特例: 有人花一个星期到网上找需要的代码, 最后只得自己写. -- 也不要太执着了, 多问问身边的程序员, 说不定他们可以很快告诉你答案]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果你不同意我的观点, 可以讨论; 如果你认同可以推荐一下,让大家都来关注程序员的快乐.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2294125.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/20/2294125.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/12/14/2287061.html</id><title type="text">DynamicXml -- 动态读取操作XML (一个从XML到Object的通用实现)</title><summary type="text">最近的一个项目用到很多不同结构的XML文件. 于是就在网上搜索了一些文章, 结合实际遇到的问题写成自己要的代码.既然已经获取了这方面的知识,不敢独取, 拿出来共享. 这个也还不是很成熟, 希望大家共同完善, 提出宝贵意见, 共同进步.目标基于已经有的XML文件,例如:&lt;root&gt; &lt;books&gt; &lt;book&gt; &lt;author&gt;John Savacki&lt;/author&gt; &lt;title&gt;E.G.Title&lt;/title&gt; &lt;price&gt;20.50&lt;/price&gt; &lt;/book&gt; </summary><published>2011-12-13T20:18:00Z</published><updated>2011-12-13T20:18:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/14/2287061.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/14/2287061.html"/><content type="html">&lt;p&gt;最近的一个项目用到很多不同结构的XML文件. 于是就在网上搜索了一些文章, 结合实际遇到的问题写成自己要的代码.&lt;/p&gt;&lt;p&gt;既然已经获取了这方面的知识,不敢独取, 拿出来共享. 这个也还不是很成熟, 希望大家共同完善, 提出宝贵意见, 共同进步.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;基于已经有的XML文件,例如:&lt;/p&gt;&lt;div&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;books&amp;gt;&lt;br /&gt;         &amp;lt;book&amp;gt;&lt;br /&gt;             &amp;lt;author&amp;gt;John Savacki&amp;lt;/author&amp;gt;&lt;br /&gt;            &amp;lt;title&amp;gt;E.G.Title&amp;lt;/title&amp;gt;&lt;br /&gt;           &amp;lt;price&amp;gt;20.50&amp;lt;/price&amp;gt;&lt;br /&gt;         &amp;lt;/book&amp;gt;&lt;br /&gt;         &amp;lt;book&amp;gt;&lt;br /&gt;             &amp;lt;author&amp;gt;Tom Curly&amp;lt;/author&amp;gt;&lt;br /&gt;            &amp;lt;title&amp;gt;E.G.Title 2&amp;lt;/title&amp;gt;&lt;br /&gt;           &amp;lt;price&amp;gt;26.50&amp;lt;/price&amp;gt;&lt;br /&gt;       &amp;lt;/book&amp;gt;&lt;br /&gt;     &amp;lt;/books&amp;gt;&lt;br /&gt; &amp;lt;/root&amp;gt;&lt;/div&gt;&lt;div&gt;或者是类似任意结构的XML文件, 可以实现初始化&lt;/div&gt;&lt;div&gt;dynamic dx = new DynamicXml(xml);&lt;/div&gt;&lt;p&gt;并且读取属性值:&lt;/p&gt;&lt;p&gt;dx.books.book[0].author, dx.books.book[2].price&lt;/p&gt;&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;自然是选择C# 4.0 中引入的 DynamicObject, 关键是已有的.net框架中不能提供这样的功能.&lt;/p&gt;&lt;p&gt;那么就从这个类中继承生成子类, 同时也需要实现 IEnumerable.&lt;/p&gt;&lt;p&gt;稍微介绍一下:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;DynamicObject 类使您能够定义可以动态对象上执行哪些操作以及如何执行这些操作。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;如果只需要设置和获取属性的操作，您可以只覆盖 TrySetMember 和 TryGetMember 方法。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;IEnumerable 公开枚举器，该枚举器支持在非泛型集合上进行简单迭代。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;应该大家都知道要实现自定义集合的IEnumerable 就要完成&lt;/p&gt;&lt;p&gt;public IEnumerator GetEnumerator()&lt;/p&gt;&lt;p&gt;也就是说, 为了实现需求, 至少我们需要完成三个函数:&lt;/p&gt;&lt;p&gt;TrySetMember, TryGetMember, GetEnumerator&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;通过上面的分析, 我们知道这个类看起来应该是这样:&lt;/p&gt;&lt;p&gt;public class DynamicXml : DynamicObject, IEnumerable &lt;br /&gt;{&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;public DynamicXml(string text) &lt;br /&gt;{ &lt;br /&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp; public override bool TryGetMember(GetMemberBinder binder, out object result) &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp; public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;&amp;nbsp; public IEnumerator GetEnumerator() &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在构造函数里我们希望可以读取XML的内容, 加载所有元素的值.&lt;/p&gt;&lt;p&gt;在TrySetMember中, 我们为设置成员值的操作提供实现, 以便为设置属性值指定动态行为。在本文中, 我们只考虑读取XML内容, 所以不需要重写这个函数.&lt;/p&gt;&lt;p&gt;在TryGetMember中, 我们要为获取成员值的操作提供实现。&lt;/p&gt;&lt;p&gt;在 TryGetIndex中,&amp;nbsp; 我们要为按索引获取值的操作提供实现.&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;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; DynamicXml : DynamicObject, IEnumerable&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;readonly&lt;/span&gt; List&amp;lt;XElement&amp;gt; _elements;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; DynamicXml(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; text)&lt;br /&gt;    {&lt;br /&gt;        var doc = XDocument.Parse(text);&lt;br /&gt;        _elements = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;XElement&amp;gt; { doc.Root };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt; DynamicXml(XElement element)&lt;br /&gt;    {&lt;br /&gt;        _elements = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;XElement&amp;gt; { element };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt; DynamicXml(IEnumerable&amp;lt;XElement&amp;gt; elements)&lt;br /&gt;    {&lt;br /&gt;        _elements = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;XElement&amp;gt;(elements);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; TryGetMember(GetMemberBinder binder, &lt;span style="color: #0000ff;"&gt;out&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; result)&lt;br /&gt;    {&lt;br /&gt;        result = &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (binder.Name == &lt;span style="color: #006080;"&gt;"Value"&lt;/span&gt;)&lt;br /&gt;            result = _elements[0].Value;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (binder.Name == &lt;span style="color: #006080;"&gt;"Count"&lt;/span&gt;)&lt;br /&gt;            result = _elements.Count;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            var attr = _elements[0].Attribute(&lt;br /&gt;                XName.Get(binder.Name));&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (attr != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;br /&gt;                result = attr;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                var items = _elements.Descendants(&lt;br /&gt;                    XName.Get(binder.Name));&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (items == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; || items.Count() == 0)&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;;&lt;br /&gt;                result = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DynamicXml(items);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; TryGetIndex(GetIndexBinder binder, &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;[] indexes, &lt;span style="color: #0000ff;"&gt;out&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; result)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; ndx = (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)indexes[0];&lt;br /&gt;        result = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DynamicXml(_elements[ndx]);&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; IEnumerator GetEnumerator()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (var element &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; _elements)&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DynamicXml(element);&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;运用&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在具体运用中, 有些地方是非常有趣的, 因为我们有了dynamic, 所以你可以用同一个变量去获取不同结构的XML文件. 运用代码如下:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; xml = &lt;span style="color: #006080;"&gt;@"&amp;lt;root&amp;gt;&lt;br /&gt;                     &amp;lt;books&amp;gt;&lt;br /&gt;                        &amp;lt;book&amp;gt;&lt;br /&gt;                            &amp;lt;author&amp;gt;John Savacki&amp;lt;/author&amp;gt;&lt;br /&gt;                           &amp;lt;title&amp;gt;E.G.Title&amp;lt;/title&amp;gt;&lt;br /&gt;                          &amp;lt;price&amp;gt;20.50&amp;lt;/price&amp;gt;&lt;br /&gt;                        &amp;lt;/book&amp;gt;&lt;br /&gt;                        &amp;lt;book&amp;gt;&lt;br /&gt;                            &amp;lt;author&amp;gt;Tom Curly&amp;lt;/author&amp;gt;&lt;br /&gt;                           &amp;lt;title&amp;gt;E.G.Title 2&amp;lt;/title&amp;gt;&lt;br /&gt;                          &amp;lt;price&amp;gt;26.50&amp;lt;/price&amp;gt;&lt;br /&gt;                      &amp;lt;/book&amp;gt;&lt;br /&gt;                    &amp;lt;/books&amp;gt;&lt;br /&gt;                &amp;lt;/root&amp;gt;"&lt;/span&gt;;&lt;br /&gt;    dynamic dx = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DynamicXml(xml);&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"----- Book List -----"&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (dynamic b &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; dx.books.book)&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine(&lt;span style="color: #006080;"&gt;"author='{0}'"&lt;/span&gt;, b.author.Value);&lt;br /&gt;        print(b);&lt;br /&gt;    }&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"------ Book List End ------"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; xml2 = &lt;span style="color: #006080;"&gt;@"&amp;lt;root&amp;gt;&lt;br /&gt;                        &amp;lt;products&amp;gt;&lt;br /&gt;                            &amp;lt;product&amp;gt;&lt;br /&gt;                              &amp;lt;title&amp;gt;iPhone 4&amp;lt;/title&amp;gt;&lt;br /&gt;                              &amp;lt;price&amp;gt;2222.50&amp;lt;/price&amp;gt;&lt;br /&gt;                              &amp;lt;quantity&amp;gt;10&amp;lt;/quantity&amp;gt;&lt;br /&gt;                            &amp;lt;/product&amp;gt;&lt;br /&gt;                            &amp;lt;product&amp;gt;&lt;br /&gt;                              &amp;lt;title&amp;gt;Lenovo IdeaPad&amp;lt;/title&amp;gt;&lt;br /&gt;                              &amp;lt;price&amp;gt;5432.50&amp;lt;/price&amp;gt;&lt;br /&gt;                              &amp;lt;quantity&amp;gt;15&amp;lt;/quantity&amp;gt;&lt;br /&gt;                            &amp;lt;/product&amp;gt;&lt;br /&gt;                        &amp;lt;/products&amp;gt;&lt;br /&gt;                    &amp;lt;/root&amp;gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    dx = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DynamicXml(xml2);&lt;br /&gt;&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"----- Product List -----"&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (dynamic b &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; dx.products.product)&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine(&lt;span style="color: #006080;"&gt;"quantity='{0}'"&lt;/span&gt;, b.quantity.Value);&lt;br /&gt;        print(b);&lt;br /&gt;    }&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"------ Product List End ------"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    Console.Read();&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;我把print函数专门拿出来, 故弄玄虚一下, 因为两个XML的结构有类似的地方, 所以可以同时使用下面的函数. -- 当然对于这样的情况,我们也可以为此定义一个interface.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; print(dynamic b)&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"Title='{0}'"&lt;/span&gt;, b.title.Value);&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"price='{0}'"&lt;/span&gt;, b.price.Value);            &lt;br /&gt;}&lt;/div&gt;&lt;p&gt;不是什么很深奥的东西, 但是希望可以为有同样问题的朋友们节省一些时间.&lt;/p&gt;&lt;p&gt;如果可以较好的掌握Dynamic, 可以节省一些反射方面的代码. 不过这是另外一个话题了.&lt;/p&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;span style="font-size: x-small;"&gt;参考文章:&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://krzysiekfonal.wordpress.com/2011/09/07/dynamic-xml/"&gt;&lt;span style="font-weight: normal; font-size: x-small;"&gt;&lt;em&gt;Dynamic XML&lt;/em&gt;&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.google.ca/url?sa=t&amp;amp;rct=j&amp;amp;q=dynamic%20xml%20csharp&amp;amp;source=web&amp;amp;cd=6&amp;amp;ved=0CEwQFjAF&amp;amp;url=http%3A%2F%2Fblogs.captechconsulting.com%2Fblog%2Fkevin-hazzard%2Ffluent-xml-parsing-using-cs-dynamic-type-part-1&amp;amp;ei=kbLnTsC1A4Ps2QWV3InUCA&amp;amp;usg=AFQjCNFhPKOMrFHAKpRAEg3Q3m1k8xGOCQ&amp;amp;sig2=Overp_AMCl7KBSQYB6iCgw&amp;amp;cad=rja"&gt;&lt;span style="font-weight: normal; font-size: x-small;"&gt;&lt;em&gt;Fluent XML Parsing Using C#'s Dynamic Type Part 1 | CapTech ...&lt;/em&gt;&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2287061.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/14/2287061.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/12/13/2285506.html</id><title type="text">从 Linq Queries 快速生成数据 HTML, EXCEL, CSV 报表</title><summary type="text">在CodePlex 上经常可以发现一些好东西, 关键是有没有时间去淘宝.前几天就发现一个, 并且在实际工作中使用了:* DoddleReport你有没有被要求基于来自数据库的数据,生成一个报表? 我们时不时会有类似的需求.DoddleReport极大的简化了这方面的工作量.首先你需要下载它的Dll 文件, 可以到 codeplex 中得到http://doddlereport.codeplex.com/或者直接从这里下载: cnblogs下载地址得到的是一样的文件, 将它解压到你的一个asp.net 网站的bin目录下. 你就可以引用Doddle的类了.我们来模拟一个场景(本场景是根据Dodd</summary><published>2011-12-12T21:28:00Z</published><updated>2011-12-12T21:28:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/13/2285506.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/13/2285506.html"/><content type="html">&lt;p&gt;在CodePlex 上经常可以发现一些好东西, 关键是有没有时间去淘宝.&lt;/p&gt;&lt;p&gt;前几天就发现一个, 并且在实际工作中使用了:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;* DoddleReport&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;你有没有被要求基于来自数据库的数据,生成一个报表? 我们时不时会有类似的需求.&lt;/p&gt;&lt;p&gt;DoddleReport极大的简化了这方面的工作量.&lt;/p&gt;&lt;p&gt;首先你需要下载它的Dll 文件, 可以到 codeplex 中得到&lt;a title="http://doddlereport.codeplex.com/" href="http://doddlereport.codeplex.com/"&gt;http://doddlereport.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;或者直接从这里下载: &lt;a href="http://files.cnblogs.com/multiplesoftware/DoddleReport.Binaries.zip"&gt;cnblogs下载地址&lt;/a&gt;&lt;/p&gt;&lt;p&gt;得到的是一样的文件, 将它解压到你的一个asp.net 网站的bin目录下. 你就可以引用Doddle的类了.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我们来模拟一个场景(本场景是根据DoddleReport提供的sample 代码改编的):&lt;/p&gt;&lt;p&gt;创建一个aspx页面, 加入下面的代码:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;创建一个Product 类:&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Product&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; Id { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Description { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt; Price { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; OrderCount { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; DateTime LastPurchase { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; UnitsInStock { get; set; }&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;随机生成1000个Product的数据, 方便我们测试结果: &lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; List&amp;lt;Product&amp;gt; GetAll()&lt;br /&gt;{&lt;br /&gt;    var rand = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Random();&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Enumerable.Range(1, 1000)&lt;br /&gt;        .Select(i =&amp;gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Product&lt;br /&gt;        {&lt;br /&gt;            Id = i,&lt;br /&gt;            Name = &lt;span style="color: #006080;"&gt;"产品 "&lt;/span&gt; + i,&lt;br /&gt;            Description =&lt;br /&gt;                &lt;span style="color: #006080;"&gt;"描述..."&lt;/span&gt;,&lt;br /&gt;            Price = rand.NextDouble() * 100,&lt;br /&gt;            OrderCount = rand.Next(1000),&lt;br /&gt;            LastPurchase = DateTime.Now.AddDays(rand.Next(1000)),&lt;br /&gt;            UnitsInStock = rand.Next(0, 2000)&lt;br /&gt;&lt;br /&gt;        })&lt;br /&gt;        .ToList();&lt;br /&gt;}&lt;div id="codeSnippetWrapper"&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;下面我们要用到DoddleReport的类:&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt; &lt;span style="color: #008000;"&gt;// Get the data for the report (any IEnumerable will work)&lt;/span&gt;&lt;br /&gt; var query = GetAll();&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #008000;"&gt;// Create the report and turn our query into a ReportSource&lt;/span&gt;&lt;br /&gt; var report = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Report(query.ToReportSource());&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #008000;"&gt;// Customize the Text Fields&lt;/span&gt;&lt;br /&gt; report.TextFields.Title = &lt;span style="color: #006080;"&gt;"报告的标题"&lt;/span&gt;;&lt;br /&gt; report.TextFields.SubTitle = &lt;span style="color: #006080;"&gt;"副标题"&lt;/span&gt;;&lt;br /&gt; report.TextFields.Footer = &lt;span style="color: #006080;"&gt;"页脚"&lt;/span&gt;;&lt;br /&gt; report.TextFields.Header = &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080;"&gt;@"制作时间: {0}"&lt;/span&gt;, DateTime.Now);&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #008000;"&gt;// Render hints allow you to pass additional hints to the reports as they are being rendered&lt;/span&gt;&lt;br /&gt; report.RenderHints.BooleanCheckboxes = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #008000;"&gt;// Customize the data fields&lt;/span&gt;&lt;br /&gt; report.DataFields[&lt;span style="color: #006080;"&gt;"Id"&lt;/span&gt;].Hidden = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt; report.DataFields[&lt;span style="color: #006080;"&gt;"Price"&lt;/span&gt;].DataFormatString = &lt;span style="color: #006080;"&gt;"{0:c}"&lt;/span&gt;;&lt;br /&gt; report.DataFields[&lt;span style="color: #006080;"&gt;"LastPurchase"&lt;/span&gt;].DataFormatString = &lt;span style="color: #006080;"&gt;"{0:d}"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt; var writer = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; HtmlReportWriter();&lt;br /&gt; writer.WriteReport(report, Response.OutputStream);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;首先用我们的数据生成一个Report的实例; 然后指定Report的一些属性, 例如标题, 页眉, 页脚(很酷,是吗). 再指定一些列的属性, 例如隐藏ID, 和给一些列特殊的格式.&lt;/div&gt;&lt;div&gt;最后调用ReportWriter将数据写出到页面.&lt;/div&gt;&lt;div&gt;下面是生成的截图:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112130527538210.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot070" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112130527548342.jpg" alt="ScreenShot070" width="641" height="237" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果你要生成Excel 或者CSV(以逗号或者tab为分隔符的文件)可以简单的修改ReportWriter后面的代码为:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;string s = Request.PhysicalApplicationPath;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;var exWriter = new ExcelReportWriter(); &lt;br /&gt;exWriter.WriteReport(report, System.IO.File.Create(s + "fil7.xls"));&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;或者&lt;/p&gt;&lt;p&gt;var deWriter = new DelimitedTextReportWriter(); &lt;br /&gt;deWriter.WriteReport(report, System.IO.File.Create(s + "fil7.csv"));&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;可以看看效果:&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112130527567983.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot071" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112130527573688.jpg" alt="ScreenShot071" width="493" height="267" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/201112130527594443.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot072" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201112/20111213052801497.jpg" alt="ScreenShot072" width="514" height="276" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;希望可以帮助到有这方面需要的朋友们.&lt;/p&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2285506.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/12/13/2285506.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/11/30/2268516.html</id><title type="text">从 Comparison/Converter 到Func 的进化</title><summary type="text">本篇文章给大家介绍两个在.net2.0 中就已经出现的, 很"老"的委托方式.通常情况下, 我们在Array 和 List&lt;T&gt; 类中使用这些功能. 明白用法和作用可以帮助你自如的使用它们.但是你也可以使用和它们作用相同的Func 家族的形式 -- 在.NET 2.0 之后引入的新功能.通过了解这些基本信息可以帮助我们看到一部分.net 进化的过程. 我称这种内容为"历史".只是抛砖引玉, 希望大家多多交流Comparison&lt;T&gt;它的出现是为了对Array 和 List&lt;T&gt; 执行type-safe 排序.注意, L</summary><published>2011-11-29T21:32:00Z</published><updated>2011-11-29T21:32:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/30/2268516.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/30/2268516.html"/><content type="html">&lt;p&gt;本篇文章给大家介绍两个在.net2.0 中就已经出现的, 很"老"的委托方式.&lt;/p&gt;&lt;p&gt;通常情况下, 我们在Array 和 List&amp;lt;T&amp;gt; 类中使用这些功能. 明白用法和作用可以帮助你自如的使用它们.&lt;/p&gt;&lt;p&gt;但是你也可以使用和它们作用相同的&lt;strong&gt;Func &lt;/strong&gt;家族的形式 -- 在.NET 2.0 之后引入的新功能.&lt;/p&gt;&lt;p&gt;通过了解这些基本信息可以帮助我们看到一部分.net 进化的过程. 我称这种内容为"历史".&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;只是抛砖引玉, 希望大家多多交流&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Comparison&amp;lt;T&amp;gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;它的出现是为了对Array 和 List&amp;lt;T&amp;gt; 执行type-safe 排序.&lt;/p&gt;&lt;p&gt;注意, Linq函数的 OrderBy(), ThenBy() 是不支持comparison&amp;lt;T&amp;gt;委托的.&lt;/p&gt;&lt;p&gt;看下面的实例:&lt;/p&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Hero&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; Age { get; set; }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt; Power { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;    {&lt;br /&gt;        var heroes = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Hero&amp;gt;&lt;br /&gt;                            {&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Hero {Name = &lt;span style="color: #006080;"&gt;"Goku"&lt;/span&gt;, Age = 60, Power = 1000.00},&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Hero {Name = &lt;span style="color: #006080;"&gt;"Vegeta"&lt;/span&gt;, Age = 65, Power = 800.00},&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Hero {Name = &lt;span style="color: #006080;"&gt;"Ikki"&lt;/span&gt;, Age = 22,Power = 345.30},&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Hero {Name = &lt;span style="color: #006080;"&gt;"Dr. Slump"&lt;/span&gt;, Age = 40, Power = 1.23},&lt;br /&gt;                            };&lt;br /&gt;&lt;br /&gt;        Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** sort by age ****"&lt;/span&gt;);&lt;br /&gt;        heroes.Sort((lhs, rhs) =&amp;gt; Comparer&amp;lt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&amp;gt;.Default.Compare(lhs.Age, rhs.Age));&lt;br /&gt;        Print(heroes);&lt;br /&gt;        Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** sort by name ****"&lt;/span&gt;);&lt;br /&gt;        heroes.Sort((lhs, rhs) =&amp;gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Compare(lhs.Name, rhs.Name));&lt;br /&gt;        Print(heroes);&lt;br /&gt;        Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** sort by power ****"&lt;/span&gt;);&lt;br /&gt;        heroes.Sort((lhs, rhs) =&amp;gt; Comparer&amp;lt;&lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;&amp;gt;.Default.Compare(rhs.Power, lhs.Power));&lt;br /&gt;        Print(heroes);&lt;br /&gt;&lt;br /&gt;        Console.Read();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Print(IEnumerable&amp;lt;Hero&amp;gt; heroes)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (var hero &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; heroes)&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine(hero.Name + &lt;span style="color: #006080;"&gt;"("&lt;/span&gt; + hero.Age + &lt;span style="color: #006080;"&gt;")"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;很容易理解上面几种排序的方法. 那么使用新的Func时, 实现如下:&lt;/div&gt;&lt;div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** sort by name(Func) ****"&lt;/span&gt;);&lt;br /&gt;var heroesOrderByName = heroes.OrderBy(t =&amp;gt; t.Name);&lt;br /&gt;Print(heroesOrderByName);&lt;/p&gt;&lt;/div&gt;在这种情况下Comparison&amp;lt;T&amp;gt; 使用较少的原因, 就是相对代码工作量大, 实现复杂一些. &lt;/div&gt;&lt;p&gt;&lt;strong&gt;Converter&amp;lt;TInput, TOutput&amp;gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Converter的使用是对某种类型的列表或者数组进行操作, 将其转化为另外一个类型的列表或者数组.&lt;/p&gt;&lt;p&gt;继续使用上面的代码, 插入:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** TestFunc ****"&lt;/span&gt;);&lt;br /&gt;TestFunc(heroes);&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** TestConverter ****"&lt;/span&gt;);&lt;br /&gt;TestConverter(heroes);&lt;br /&gt;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #006080;"&gt;"***** TestLinqSelect ****"&lt;/span&gt;);&lt;br /&gt;TestLinqSelect(heroes);&lt;div&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; TestFunc(List&amp;lt;Hero&amp;gt; heroes)&lt;br /&gt;{&lt;br /&gt;    Func&amp;lt;Hero, &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; selector = p =&amp;gt; p.Name;&lt;br /&gt;&lt;br /&gt;    IEnumerable&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; names = heroes.Select(selector);&lt;br /&gt;&lt;br /&gt;    print(names);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; TestLinqSelect(List&amp;lt;Hero&amp;gt; heroes)&lt;br /&gt;{&lt;br /&gt;    var names = heroes.Select(p =&amp;gt; p.Name);&lt;br /&gt;&lt;br /&gt;    print(names);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; TestConverter(List&amp;lt;Hero&amp;gt; heroes)&lt;br /&gt;{&lt;br /&gt;    var names = heroes.ConvertAll(p =&amp;gt; p.Name);&lt;br /&gt;&lt;br /&gt;    print(names);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; print(IEnumerable&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; names)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; names)&lt;br /&gt;        Console.WriteLine(name);&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;其实上面 TestLinqSelect 和 TestFunc 是同一码事, 我只是给大家提供不同的代码方案而已. 一般, 我们不会使用TestFunc 这种形式.&lt;/div&gt;&lt;div&gt;注意, 用 Linq 的Select 和其他一些Linq的函数一样, 是推迟执行, 这意味着, 很多时候, 它们将不执行转换, 直到数值被使用.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;这事实上是双刃剑, 有时候它可以获取更好的效率, 但是如果你马上就想要结果就会导致额外的后台工作开销 -- 支持延迟执行的功能本身需要使用到yield return /yield break 来维持当前状态的信息迭代器. &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;小结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本质上来讲, Comparison/Converter 和与之相对应的Func没有太多区别, 但是为什么.net 让它们同时存在, 或者换句话讲在有了实现方案后, 为什么要"多余"引入后者?&lt;/p&gt;&lt;p&gt;这是因为之后被引入的委托Func&amp;lt;&amp;gt;是一个多功能兵种, 但是在执行具体任务的时候效果稍有区别.&lt;/p&gt;&lt;p&gt;在新项目中, 我们也更倾向于使用新的方法.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;参考文章:&lt;/em&gt;&lt;/span&gt;&lt;a href="http://blackrabbitcoder.net/archive/2011/11/24/c.net-little-wonders-the-predicate-comparison-and-converter-generic-delegates.aspx"&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;C#/.NET Little Wonders: The Predicate, Comparison, and Converter Generic Delegates&lt;/em&gt;&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2268516.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/30/2268516.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/11/24/2261105.html</id><title type="text">不可不知的C#基础 4. 延迟加载 -- 提高性能</title><summary type="text">延迟加载(lazy loading) 设计模式是为了避免一些无谓的性能开销而提出来的，所谓延迟加载就是当在真正需要数据(读取属性值)的时候，才真正执行数据加载操作. 有效使用它可以大大提高系统性能. 为了便于理解, 我们来建立一个场景, 假设我们要构造一个Hero(英雄) 类, 每个Hero 有自己的名字和(SpecialSkill)特殊技能. 建模 这是一种建立的方法: 运行程序后输出如下, ...</summary><published>2011-11-23T20:41:00Z</published><updated>2011-11-23T20:41:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/24/2261105.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/24/2261105.html"/><content type="html">&lt;p&gt;延迟加载(lazy loading) 设计模式是为了避免一些无谓的性能开销而提出来的，所谓延迟加载就是当在真正需要数据(读取属性值)的时候，才真正执行数据加载操作.&lt;/p&gt; &lt;p&gt;有效使用它可以大大提高系统性能.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;为了便于理解, 我们来建立一个场景, 假设我们要构造一个Hero(英雄) 类, 每个Hero 有自己的名字和(SpecialSkill)特殊技能.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;建模&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;这是一种建立的方法:&lt;/p&gt; &lt;div&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Hero&lt;br&gt;{&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FullName { get; set; }&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SpecialSkill Skill{ get; set; }&lt;br&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Hero(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name)&lt;br&gt;    {&lt;br&gt;        Name = name;&lt;br&gt;        FullName = &lt;span style="color: #006080"&gt;"Super "&lt;/span&gt; + name;&lt;br&gt;        Skill = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SpecialSkill(name);&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SpecialSkill&lt;br&gt;{&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Power { get; set; }&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; SkillName { get; set; }&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; StrengthSpent { get; set; }&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SpecialSkill(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name)&lt;br&gt;    {&lt;br&gt;        Console.WriteLine(&lt;span style="color: #006080"&gt;"loading special skill ....."&lt;/span&gt;);&lt;br&gt;        Power = name.Length;&lt;br&gt;        StrengthSpent = name.Length * 3;&lt;br&gt;        SkillName = name + &lt;span style="color: #006080"&gt;" Blazing"&lt;/span&gt;;&lt;br&gt;        Console.WriteLine(SkillName + &lt;span style="color: #006080"&gt;",... this's what makes a legend!"&lt;/span&gt;);&lt;br&gt;    }&lt;br&gt;} &lt;br&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Program&lt;br&gt;{&lt;br&gt;    &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[] args)&lt;br&gt;    {&lt;br&gt;        Hero hero = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Hero(&lt;span style="color: #006080"&gt;"wukong"&lt;/span&gt;);            &lt;br&gt;        Console.WriteLine(&lt;span style="color: #006080"&gt;"\n\n.......................Press Enter to continue.......................\n\n"&lt;/span&gt;);&lt;br&gt;        Console.Read();&lt;br&gt;        Console.WriteLine(&lt;span style="color: #006080"&gt;"Hero's special skill: "&lt;/span&gt; + hero.Skill.SkillName);&lt;br&gt;        Console.Read();&lt;br&gt;        Console.Read();&lt;br&gt;    }&lt;br&gt;}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;运行程序后输出如下, 这个例子非常的容易理解, 结果也是显然的. &lt;/div&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201111/20111124044039277.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ScreenShot066" border="0" alt="ScreenShot066" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201111/201111240440406557.jpg" width="507" height="164"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;它的缺点是, 当运行Hero 构造函数的时候, SpecialSkill 的所有属性都已经加载了. 如果我们只想获取这个Hero 的FullName, 我们也加载了SpecialSkill 所有值.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;属性的加载延迟&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在没有Lazy&amp;lt;T&amp;gt; 以前我们可以这样做:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&amp;nbsp;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Hero&lt;br&gt; {&lt;br&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FullName { get; set; }&lt;br&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; SpecialSkill skill;&lt;br&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SpecialSkill Skill&lt;br&gt;     { &lt;br&gt;         get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; skill ?? (skill = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SpecialSkill(Name)); }&lt;br&gt;     }&lt;br&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Hero(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name)&lt;br&gt;     {&lt;br&gt;         Name = name;&lt;br&gt;         FullName = &lt;span style="color: #006080"&gt;"Super "&lt;/span&gt; + name;&lt;br&gt;         &lt;br&gt;&lt;br&gt;     }&lt;br&gt; }&lt;br&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;即: 修改属性SpecialSkill的加载方法. 那么当我们再运行程序时, 得到的输出就是:&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201111/201111240440414473.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ScreenShot067" border="0" alt="ScreenShot067" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201111/201111240440432389.jpg" width="573" height="144"&gt;&lt;/a&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;strong&gt;Lazy&amp;lt;T&amp;gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;当net framework 引入了Lazy&amp;lt;T&amp;gt; 类后, 我们也可以使用它来实现:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Hero&lt;br&gt;{&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FullName { get; set; }&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;br&gt;    &lt;br&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; Lazy&amp;lt;SpecialSkill&amp;gt; skill;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SpecialSkill Skill&lt;br&gt;    {&lt;br&gt;        get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; skill.Value; }&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Hero(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name)&lt;br&gt;    {&lt;br&gt;        Name = name;&lt;br&gt;        FullName = &lt;span style="color: #006080"&gt;"Super "&lt;/span&gt; + name;&lt;br&gt;        &lt;br&gt;        skill = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Lazy&amp;lt;SpecialSkill&amp;gt;(() =&amp;gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SpecialSkill(name));&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lazy&amp;lt;T&amp;gt;提供对延迟初始化的支持。而 Lazy&amp;lt;T&amp;gt; 中的一个属性 Value, 则是获取当前 Lazy&amp;lt;T&amp;gt; 实例的延迟初始化值。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Lazy&amp;lt;T&amp;gt;的优势&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;那么既然我们已经可以用属性缓存的方法实现, 为什么还要引入Lazy&amp;lt;T&amp;gt; ?&lt;/p&gt;&lt;p&gt;至少Lazy&amp;lt;T&amp;gt; 有以下几点优势:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;它具有 LazyThreadSafetyMode, 但是我们一般不使用它, 除非是很关键的情况下(在此略去181个字) &lt;li&gt;它使属性的定义行更加简单 &lt;li&gt;从语义上来讲, 它更加明确, 更加具有可读性 &lt;li&gt;它允许null为有效值 &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;p&gt;一些相关文章:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/13/2209603.html"&gt;不可不知的C#基础 1. -- Extension 扩展方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/15/2212780.html"&gt;不可不知的C#基础 2. -–从 struct 和 class的异同 说开去&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/29/2228317.html"&gt;不可不知的C#基础 3. 线程浅析&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2261105.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/11/24/2261105.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/10/29/2228317.html</id><title type="text">不可不知的C#基础 3. 线程浅析</title><summary type="text">线程可以使你的项目运行得更加的流畅.什么是线程呢?线程(thread)是程序执行流的最小单元, 是程序中一个单一的顺序控制流程. 每个程序最少有一个线程, 那就是程序本身.在C#中, 你可以使用 System.Threading 提供的类,接口和方法实现线程的所有操作.单线程操作想象着你走进快餐店, 大叫一声"来碗兰州拉面", 然后就坐在饭桌上等. 当厨师听到你的要求时,他就开始做兰州拉面了. 理论上讲, 当你叫了以后, 厨师就已经收到了命令.用代码可以这样表达:static void Main(string[] args){ string name = "兰州拉</summary><published>2011-10-28T22:08:00Z</published><updated>2011-10-28T22:08:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/29/2228317.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/29/2228317.html"/><content type="html">&lt;p&gt;线程可以使你的项目运行得更加的流畅.&lt;/p&gt;&lt;p&gt;什么是线程呢?&lt;/p&gt;&lt;p&gt;线程(thread)是程序执行流的最小单元, 是程序中一个单一的顺序控制流程. 每个程序最少有一个线程, 那就是程序本身.&lt;/p&gt;&lt;p&gt;在C#中, 你可以使用 System.Threading 提供的类,接口和方法实现线程的所有操作.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;单线程操作&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;想象着你走进快餐店, 大叫一声"来碗兰州拉面", 然后就坐在饭桌上等. 当厨师听到你的要求时,他就开始做兰州拉面了. 理论上讲, 当你叫了以后, 厨师就已经收到了命令.&lt;/p&gt;&lt;p&gt;用代码可以这样表达:&lt;/p&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name = &lt;span style="color: #006080;"&gt;"兰州拉面"&lt;/span&gt;;&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"来碗"&lt;/span&gt; + name);&lt;br /&gt;    PlaceOrder(name);&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"坐在饭桌上...."&lt;/span&gt;);&lt;br /&gt;    Console.Read();&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name)&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"开始制作"&lt;/span&gt; + name);&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;运行程序, 你会发现输出结果是:&lt;/div&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607379664.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot056" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607391225.jpg" alt="ScreenShot056" width="174" height="78" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;从显示的结果来看, 这个厨师的动作非常的快, 他一听到命令, 马上就开始了. 为了让这个程序的模拟比较真实, 我们可以想象"我的动作"是一个线程, 而"厨师做拉面"是一个线程.&lt;/div&gt;&lt;div&gt;如果我们运用线程来实现就有点意思了:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name)&lt;br /&gt;  {&lt;br /&gt;      Thread thread1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Thread(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ThreadStart(Cooking));&lt;br /&gt;      thread1.Start();&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Cooking()&lt;br /&gt;  {&lt;br /&gt;      Console.Write(&lt;span style="color: #006080;"&gt;"开始制作"&lt;/span&gt;);&lt;br /&gt;  }&lt;/div&gt;&lt;p&gt;运行程序, 你会发现输出结果是:&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607404455.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot055" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/2011102906074194.jpg" alt="ScreenShot055" width="165" height="78" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这是表示虽然厨师听到你的声音了,但是你坐在饭桌上的动作是在他开始做拉面之前. -- 更加的合情合理, 是吗?&lt;/p&gt;&lt;p&gt;我们还可以引入参数:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name)&lt;br /&gt;{&lt;br /&gt;    Thread thread1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Thread(t =&amp;gt; Cooking(name));&lt;br /&gt;    thread1.Start();&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Cooking(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name)&lt;br /&gt;{&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"开始制作"&lt;/span&gt; + name);&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注意上面的参数的传递方法只用于.net 3.5/4&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;多线程&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果一个饭店有多个厨师, 并且同时有多个人点餐, 我们可以像这样模拟实现:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt; {&lt;br /&gt;     &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name = &lt;span style="color: #006080;"&gt;"兰州拉面"&lt;/span&gt;;&lt;br /&gt;     &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; number = 5;&lt;br /&gt;     Console.WriteLine(&lt;span style="color: #006080;"&gt;"来"&lt;/span&gt; + number + &lt;span style="color: #006080;"&gt;"碗"&lt;/span&gt; + name);&lt;br /&gt;     PlaceOrder(name, 5);&lt;br /&gt;     Console.WriteLine(&lt;span style="color: #006080;"&gt;"坐在饭桌上...."&lt;/span&gt;);&lt;br /&gt;     Console.Read();&lt;br /&gt; }&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; number)&lt;br /&gt; {&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; number; i++)&lt;br /&gt;     {&lt;br /&gt;         Thread thread1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Thread(t =&amp;gt; Cooking(name));&lt;br /&gt;         thread1.Start();&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Cooking(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name)&lt;br /&gt; {&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"开始制作"&lt;/span&gt; + name);&lt;br /&gt; }&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;运行后, 结果显示:&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607434686.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot057" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/20111029060744391.jpg" alt="ScreenShot057" width="205" height="148" border="0" /&gt;&lt;/a&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;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Cooking(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name)&lt;br /&gt;{&lt;br /&gt;    Thread.Sleep(10);&lt;br /&gt;    Console.WriteLine(&lt;span style="color: #006080;"&gt;"开始制作"&lt;/span&gt; + name);&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;再次运行程序, 结果是:&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607461079.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot058" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607474243.jpg" alt="ScreenShot058" width="183" height="131" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;线程的关联性和独立性&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;线程的运作是相对独立的, 完成不同的工作. 但是它们却是共享进程内的资源.&lt;/p&gt;&lt;p&gt;做个实验:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; number)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;[] array = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;[] {1000,500,300,500,1};&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; number; i++)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; time = array[i];&lt;br /&gt;        Thread thread1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Thread(t =&amp;gt; Cooking(name, i,time));&lt;br /&gt;        thread1.Start();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Cooking(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; id, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; time)&lt;br /&gt;{            &lt;br /&gt;    Thread.Sleep(10);&lt;br /&gt;    Console.WriteLine(id + &lt;span style="color: #006080;"&gt;"号开始制作"&lt;/span&gt; + name);&lt;br /&gt;}&lt;/div&gt;&lt;/div&gt;&lt;p&gt;这里我们想给每一个厨师一个编号, 但是当把i 当中参数传递的时候, visual studio 会发出警告:&lt;/p&gt;&lt;p&gt;" Access To Modified Closure &amp;ldquo;.&lt;/p&gt;&lt;p&gt;这个是什么意思呢? 运行一下程序, 输出是:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/20111029060748787.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot059" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/20111029060750985.jpg" alt="ScreenShot059" width="186" height="124" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;发现在运行程序的时候, 错误的读取了厨师的编号, 这就是那个警告发出的原因: 因为线程们共享的名字 i 在不停的变化中, 我们没有办法控制一个特定线程运行时i 的值, -- 它们是相对独立的.&lt;/p&gt;&lt;p&gt;解决方案就是增加一个变量名存放值作为传递:&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; number)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;[] array = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;[] {1000,500,300,500,1};&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; number; i++)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; j = i;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; time = array[i];&lt;br /&gt;        Thread thread1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Thread(t =&amp;gt; Cooking(name, j,time));&lt;br /&gt;        thread1.Start();&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;最后我们来看看, 线程中独立运行的实验:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; PlaceOrder(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; number)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;[] array = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;[] {1000,500,300,500,1};&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; number; i++)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; j = i;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; time = array[i];&lt;br /&gt;        Thread thread1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Thread(t =&amp;gt; Cooking(name, j,time));&lt;br /&gt;        thread1.Start();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Cooking(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; id, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; time)&lt;br /&gt;{            &lt;br /&gt;    Thread.Sleep(10);&lt;br /&gt;    Console.WriteLine(id + &lt;span style="color: #006080;"&gt;"号开始制作"&lt;/span&gt; + name);&lt;br /&gt;    Thread.Sleep(time);&lt;br /&gt;    Console.WriteLine(id + &lt;span style="color: #006080;"&gt;"号准备完毕,花费时间:"&lt;/span&gt; + time);&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;每个厨师的速度是不一样的, 他们花费的时间不同, 所以先开始的不一定先完成, 上面的代码运行的结果是:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607513102.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot060" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110290607522362.jpg" alt="ScreenShot060" width="221" height="206" border="0" /&gt;&lt;/a&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/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2228317.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/29/2228317.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/10/15/2212780.html</id><title type="text">不可不知的C#基础 2. -–从 struct 和 class的异同 说开去</title><summary type="text">我知道很多人都讨论过这个问题, 多我一个不多, 少我一个不少.最近有人又问到这个问题, 所以想再说说. 万丈高楼平地起, 地基很重要. 懂了的人不要嫌罗嗦, 欢迎补充或者纠正.从起源/定义说起Struct 从C 的时代就已经有了(向丹尼斯.里奇致敬), 它是Structure 的缩写 -- 就是结构的意思. 它是一种最初级的数据结构, 它包含一到多个相同类型或不同类型的值或者变量. 它就像是一个存储数据的"包".Class(类) 是有了面向对象概念之后才有的, 它"是创建对象的蓝图,描述了所创建的对象共同的属性和方法".从它们被创立的用途可以看出Clas</summary><published>2011-10-14T19:17:00Z</published><updated>2011-10-14T19:17:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/15/2212780.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/15/2212780.html"/><content type="html">&lt;p&gt;我知道很多人都讨论过这个问题, 多我一个不多, 少我一个不少.&lt;/p&gt;&lt;p&gt;最近有人又问到这个问题, 所以想再说说. 万丈高楼平地起, 地基很重要. 懂了的人不要嫌罗嗦, 欢迎补充或者纠正.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;从起源/定义说起&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Struct 从C 的时代就已经有了(向丹尼斯.里奇致敬), 它是Structure 的缩写 -- 就是结构的意思. 它是一种最初级的数据结构, 它包含一到多个相同类型或不同类型的值或者变量. 它就像是一个存储数据的"包".&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Class(类) 是有了面向对象概念之后才有的, 它"是创建对象的蓝图,描述了所创建的对象共同的属性和方法".&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;从它们被创立的用途可以看出Class 比Struct 负担了更大的使命.&lt;/p&gt;&lt;p&gt;类从出生的那天就被赋予了一个伟大的使命: 模拟真实世界的行为, 拥有继承和多态两种利器.&lt;/p&gt;&lt;p&gt;Struct 到了C#这个领域中有了一个进化, 它甚至可以实现接口(当然,这个也是C时代没有的东西), 在本文中会有一个简单的介绍.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;值类型 VS 引用类型&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;在.net 世界中, System.Object "支持 .NET Framework 类层次结构中的所有类，并为派生类提供低级别服务。 这是 .NET Framework 中所有类的最终基类；它是类型层次结构的根。" 从Object再衍生出所有类、结构、枚举和委托。&lt;/div&gt;&lt;div&gt;看看下面这个图对net中两大类型的描述, -- 当然还有一种"指针类型",在这里我们不予讨论.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110150316315139.gif"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="chappell5fig01" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110150316338006.gif" alt="chappell5fig01" width="486" height="365" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Struct 是属于值类型这个阵容, 而所有class 都是引用类型.&lt;/p&gt;&lt;p&gt;这意味着什么?&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;当我们使用等号"赋值"时, 对于Struct而言就是将同样的值复制给另一个变量; 而对于Class而言就只是将它们的名字指向同一个对象.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;看下面的实例:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; FooClass&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; FooValue;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;struct&lt;/span&gt; FooStruct&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; FooValue;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;    {&lt;br /&gt;        FooClass classObj = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; FooClass();&lt;br /&gt;&lt;br /&gt;        classObj.FooValue = 0;&lt;br /&gt;&lt;br /&gt;        FooClass classObj2 = classObj;&lt;br /&gt;&lt;br /&gt;        classObj2.FooValue = 1;&lt;br /&gt;&lt;br /&gt;        FooStruct structObj = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; FooStruct();&lt;br /&gt;&lt;br /&gt;        structObj.FooValue = 0;&lt;br /&gt;&lt;br /&gt;        FooStruct structObj2 = structObj;&lt;br /&gt;        &lt;br /&gt;        structObj2.FooValue = 1;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;再最后设个断点, 运行后取值:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110150316347873.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot047" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201110/201110150316359170.jpg" alt="ScreenShot047" width="571" height="113" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;structObj2 在初始时, &lt;strong&gt;会创建一个全新的副本, 然后&lt;/strong&gt;获取structObj 的所有数值;&lt;/div&gt;&lt;div&gt;classObj2 在初始时, 只是指向了classObj. 这就是值类型和引用类型的一个区别. 当修改classObj 或者 classObj2 时, 修改的是同一部分内存.&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Struct实现接口&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;前面提到了Struct可以实现接口, 下面我们引用一个实例:&lt;/p&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;interface&lt;/span&gt; IPromotion&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; promote();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;struct&lt;/span&gt; Employee : IPromotion&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Name;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; JobGrade;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; promote()&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        JobGrade++;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; Employee(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; name, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; jobGrade)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.Name = name;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.JobGrade = jobGrade;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ToString()&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080;"&gt;"{0} ({1})"&lt;/span&gt;, Name, JobGrade);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        Employee employee = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Employee(&lt;span style="color: #006080;"&gt;"Cool Guy"&lt;/span&gt;, 65);&lt;br /&gt;&lt;br /&gt;        IPromotion p = employee;&lt;br /&gt;&lt;br /&gt;        Console.WriteLine(employee);&lt;br /&gt;&lt;br /&gt;        p.promote();&lt;br /&gt;&lt;br /&gt;        Console.WriteLine(employee);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;一旦增加了这个功能, 我们就可以在应用Struct之前, 给予其一些接口的定义. 使一类的struct 在形式上保持一致.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;不同的用途&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;使用中在struct 和 class 两者间该选谁?&lt;/p&gt;&lt;p&gt;我们在编程中要实现某种数据结构时, 绝大部分情况下我们会选择class -- 因为它的强大和特定的使命. 但是当我们要传递或存储一些小数据结构时,可以考虑struct.&lt;/p&gt;&lt;p&gt;Net framework 下有很多已经定义好了的struct例如:&lt;/p&gt;&lt;p&gt;System.Drawing.Rectangle &lt;br /&gt;System.Drawing.Color &lt;br /&gt;System.Drawing.Point&lt;/p&gt;&lt;p&gt;使用时要记住struct的特性.&lt;/p&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2212780.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/15/2212780.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/10/13/2209603.html</id><title type="text">不可不知的C#基础 1. -- Extension 扩展方法</title><summary type="text">背景前几天有同事问到我一个简单的功能, 就是当你使用枚举时如何给每个一元素增加描述字符串并且可以很容易的读取出来.比如有一个枚举类型是列出对一个问题给出的选项(例如: 同意?不同意?中立?):当选择不同的答案时, 希望得到一些描述性的语句比方说:1. "强烈的反对"2. "反对"3. "持中立观点"4. "同意"5. "完全的同意"当然你可以建立一个数据库表格,存放这些信息, 但是我想起几年前,我...</summary><published>2011-10-12T19:13:00Z</published><updated>2011-10-12T19:13:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/13/2209603.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/13/2209603.html"/><content type="html">&lt;p&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;前几天有同事问到我一个简单的功能, 就是当你使用枚举时如何给每个一元素增加描述字符串并且可以很容易的读取出来.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;比如有一个枚举类型是列出对一个问题给出的选项(例如: 同意?不同意?中立?):&lt;/p&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;enum&lt;/span&gt; AssessmentAnswer&lt;br /&gt; {&lt;br /&gt;     Strongly_Disagree = 1,&lt;br /&gt;     Disagree = 2,&lt;br /&gt;     Neutral = 3,&lt;br /&gt;     Agree = 4,&lt;br /&gt;     Strongly_Agree = 5&lt;br /&gt; }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;当选择不同的答案时, 希望得到一些描述性的语句比方说:&lt;/div&gt;&lt;div&gt;1. "强烈的反对"&lt;/div&gt;&lt;div&gt;2. "反对"&lt;/div&gt;&lt;div&gt;3. "持中立观点"&lt;/div&gt;&lt;div&gt;4. "同意"&lt;/div&gt;&lt;div&gt;5. "完全的同意"&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;当然你可以建立一个数据库表格,存放这些信息, 但是我想起几年前,我在网上下载一个 EnumDescription 源码(忘记了是在哪里下载的), 就可以实现这一功能.&lt;/div&gt;&lt;div&gt;让我们一起来看看是怎么样用 Extension 做到的:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;实现&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;首先定义一个EnumDescription 类:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; EnumDescription : Attribute&lt;br /&gt; {&lt;br /&gt;     &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; Text&lt;br /&gt;     {&lt;br /&gt;         get { &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; _text; }&lt;br /&gt;     } &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; _text;&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; EnumDescription(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; text)&lt;br /&gt;     {&lt;br /&gt;         _text = text;&lt;br /&gt;     }&lt;br /&gt; }&lt;/div&gt;&lt;p&gt;注意它的父类是Attribute, 因为我们希望将描述的语句作为每一个对应元素的特性. 然后新建一个文件,命名EnumExtensions.cs&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; EnumExtensions&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ToDescription(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt; Enum enumeration)&lt;br /&gt;    {&lt;br /&gt;        Type type = enumeration.GetType();&lt;br /&gt;        MemberInfo[] memInfo = type.GetMember(enumeration.ToString());&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; != memInfo &amp;amp;&amp;amp; memInfo.Length &amp;gt; 0)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;[] attrs = memInfo[0].GetCustomAttributes(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;(EnumDescription), &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;);&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; != attrs &amp;amp;&amp;amp; attrs.Length &amp;gt; 0)&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; ((EnumDescription)attrs[0]).Text;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; enumeration.ToString();&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在这里我们定义了一个扩展函数ToDescription, 就像所有的扩展函数一样,它的参数是类似(this &amp;hellip;),&lt;/p&gt;&lt;p&gt;这个函数首先用GetType 得到了当前枚举的类型, 然后借助 GetMember按照元素的名字(值), 得到这个特定的元素, 最后用GetCustomAttributes 得到描述的内容.&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;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;enum&lt;/span&gt; AssessmentAnswer&lt;br /&gt;{&lt;br /&gt; [EnumDescription(&lt;span style="color: #006080;"&gt;"强烈的反对"&lt;/span&gt;)]&lt;br /&gt; Strongly_Disagree = 1,&lt;/p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [EnumDescription(&lt;span style="color: #006080;"&gt;"反对"&lt;/span&gt;)]&lt;br /&gt;    Disagree = 2,&lt;br /&gt;    Neutral = 3,&lt;br /&gt;    Agree = 4,&lt;br /&gt;    [EnumDescription(&lt;span style="color: #006080;"&gt;"完全的同意"&lt;/span&gt;)]&lt;br /&gt;    Strongly_Agree = 5&lt;br /&gt;}&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;当要获取描述语句时, 你可以轻松的调用ToDescription :&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;//返回 "强烈的反对"&lt;/p&gt;&lt;p&gt;AssessmentAnswer.Strongly_Disagree.ToDescription()&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;注意, 如果没有给元素加入特性, 你仍旧可以使用ToDescription, 可以参考上面的代码看看是为什么.&lt;/p&gt;&lt;p&gt;//返回 &amp;ldquo;Disagree&amp;rdquo;&lt;/p&gt;&lt;p&gt;AssessmentAnswer.Disagree.ToDescription()&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;扩展方法作为特殊的静态方法使您能够向现有类型&amp;ldquo;添加&amp;rdquo;方法，而无需创建新的派生类型、重新编译或以其他方式修改原始类型。&lt;/p&gt;&lt;p&gt;对于用 C# 和 Visual Basic 编写的客户端代码，调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;给初学者的话: 一旦当你实现扩展方法后, 你只需要复制dll 添加文件命名空间; 或者复制cs文件到你的项目中, 就可以使用这些方法,&amp;nbsp; 但是建议除非你有充分的理由才实现扩展方法。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;很多我们要用到的扩展方法都可以在网上得到, 所以一般在写自己的扩展前请先搜索一下.&lt;/p&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2209603.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/10/13/2209603.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/multiplesoftware/archive/2011/09/30/2196075.html</id><title type="text">WebMatrix教程(五) (快速建立数据图表的方案)</title><summary type="text">很多人都知道使用 Webmatrix -- Microsoft 推出的最新武器可以很容易帮助你在windows下设置安装最常用的php, asp.net 开源网络应用如：wordpress, DNN, Umbraco, mojoportal, Joomla 等。同时Webmatrix支持的Razor让你可以很快的建立小型动态的.net网站，其实Webmatrix 还有一个卖点就是它有Helper库，熟悉了解这些Helper才可能真正的使用Webmatrix来建立具有应用价值的网站。今天我们来看看图表的库： Chart。如果你以前没有接触过Webmatrix，建议你先快速阅读下面的文章：WebM</summary><published>2011-09-29T18:29:00Z</published><updated>2011-09-29T18:29:00Z</updated><author><name>拥有的都是恩典(宋历)</name><uri>http://www.cnblogs.com/multiplesoftware/</uri></author><link rel="alternate" href="http://www.cnblogs.com/multiplesoftware/archive/2011/09/30/2196075.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/multiplesoftware/archive/2011/09/30/2196075.html"/><content type="html">&lt;p&gt;很多人都知道使用 Webmatrix -- Microsoft 推出的最新武器可以很容易帮助你在windows下设置安装最常用的php, asp.net 开源网络应用如：wordpress, DNN, Umbraco, mojoportal, Joomla 等。&lt;/p&gt;&lt;p&gt;同时Webmatrix支持的Razor让你可以很快的建立小型动态的.net网站，其实Webmatrix 还有一个卖点就是它有Helper库，熟悉了解这些Helper才可能真正的使用Webmatrix来建立具有应用价值的网站。&lt;/p&gt;&lt;p&gt;今天我们来看看图表的库： Chart。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果你以前没有接触过Webmatrix，建议你先快速阅读下面的文章：&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/01/28/1946586.html"&gt;WebMatrix教程(一) (关注Microsoft 的最新武器：建立你的第一个WebMatrix网站）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/01/29/1947334.html"&gt;WebMatrix教程(二) (关注Microsoft 的最新武器：基于空白项目建立你的WebMatrix网站[上篇]）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/01/30/1947338.html"&gt;WebMatrix教程(三) (关注Microsoft 的最新武器：基于空白项目建立你的WebMatrix网站[下篇]）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/08/26/2153965.html"&gt;WebMatrix教程(四) (读取数据库)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;支持多种图表&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;先建立一个空白站点或者使用WebMatrix 的 Template 建立一个Starter Site：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300227529154.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="ScreenShot033" alt="ScreenShot033" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300227544430.jpg" border="0" height="347" width="296" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;新建一个cshtml 文件，命名为MyCharts.cshtml&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;删除自动生成代码，替换成下面的：&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;@{&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;var firstChart = new Chart(width: 350, height: 250)&lt;br /&gt;.AddTitle(&lt;span style="color: #006080;"&gt;"图表测试"&lt;/span&gt;)&lt;br /&gt;.AddSeries(&lt;br /&gt;name: &lt;span style="color: #006080;"&gt;"Teams"&lt;/span&gt;, chartType: &lt;span style="color: #006080;"&gt;"Bar"&lt;/span&gt;,&lt;br /&gt;xValue: new[] { &lt;span style="color: #006080;"&gt;"China"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"USA"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"Canada"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"UK"&lt;/span&gt; },&lt;br /&gt;yValues: new[] { &lt;span style="color: #006080;"&gt;"12"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"6"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"4"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"3"&lt;/span&gt;})&lt;br /&gt;.Write()&lt;span style="color: #008000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;点击 Run，在浏览器中生成的页面如下：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300227562803.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot034" alt="ScreenShot034" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300227597032.jpg" border="0" height="243" width="372" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;chart 帮助支持多种形式的图表，如饼图，线，填充，柱形图。如果你改变ChartType的值就可以轻松获取不同种类的图表：&lt;/p&gt;&lt;p&gt;将上面代码中的&lt;/p&gt;&lt;p&gt;name: "Teams", chartType: "Bar", &lt;/p&gt;&lt;p&gt;替换成：&lt;/p&gt;&lt;p&gt;name: "Teams", chartType: "Pie",&lt;/p&gt;&lt;p&gt;可以得到：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228018229.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot035" alt="ScreenShot035" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228023571.jpg" border="0" height="231" width="244" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;替换成：&lt;/p&gt;&lt;p&gt;name: "Teams", chartType: "Line"： &lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/20110930022805308.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot036" alt="ScreenShot036" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228061746.jpg" border="0" height="170" width="264" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;或者：&lt;/p&gt;&lt;p&gt;name: "Teams", chartType: "Area",&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228089912.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot037" alt="ScreenShot037" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228101906.jpg" border="0" height="189" width="281" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;当然数据来源还可以是database table 或者 xml 文件：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;从 Database 中读取&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在这里，我们建立一个名叫supermen的table，然后定义它的列如下：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228126135.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot038" alt="ScreenShot038" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228166644.jpg" border="0" height="169" width="367" /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;再输入一些初始数据：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228178082.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot039" alt="ScreenShot039" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228203948.jpg" border="0" height="143" width="422" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;将mycharts中原来的代码删除，替换成：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;@{&lt;br /&gt;var db = Database.Open(&lt;span style="color: #006080;"&gt;"StarterSite"&lt;/span&gt;);&lt;br /&gt;var data = db.Query(&lt;span style="color: #006080;"&gt;"SELECT Name, Power FROM Supermen"&lt;/span&gt;);&lt;br /&gt;  var secChart = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Chart(width: 350, height: 250)&lt;br /&gt;        .AddTitle(&lt;span style="color: #006080;"&gt;"超人大比拼"&lt;/span&gt;)&lt;br /&gt;        .DataBindTable(dataSource: data, xField: &lt;span style="color: #006080;"&gt;"Name"&lt;/span&gt;)&lt;br /&gt;        .Write();&lt;br /&gt;&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;DataBindTable 指定了数据源和X轴使用的数据。 &lt;/div&gt;&lt;div&gt;或者你也可以分别指定X轴和Y轴：&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;var secChart = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Chart(width: 350, height: 250)&lt;br /&gt;      .AddTitle(&lt;span style="color: #006080;"&gt;"超人大比拼"&lt;/span&gt;)        &lt;br /&gt;      .AddSeries(&lt;span style="color: #006080;"&gt;"Default"&lt;/span&gt;, &lt;br /&gt;      xValue: data, xField: &lt;span style="color: #006080;"&gt;"Name"&lt;/span&gt;,&lt;br /&gt;  yValues: data, yFields: &lt;span style="color: #006080;"&gt;"Power"&lt;/span&gt;).Write();&lt;/div&gt;&lt;p&gt;都生成下面的图表：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228226225.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot041" alt="ScreenShot041" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228245994.jpg" border="0" height="229" width="333" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;从XML中读取&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果要从XML中读取数据，我们要先建立两个文件：XML 数据文件，和XSD 结构文件。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在App_Data目录下新建一个文件命名为data.xml，编辑并改写文件内容如下:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;lt;?xml version="1.0" standalone="yes" ?&amp;gt; &lt;br /&gt;&amp;lt;NewDataSet xmlns="&lt;a href="http://tempuri.org/data.xsd&amp;quot;"&gt;http://tempuri.org/data.xsd"&lt;/a&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Name&amp;gt;Alex&amp;lt;/Name&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Age&amp;gt;31&amp;lt;/Age&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Name&amp;gt;Adam&amp;lt;/Name&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Age&amp;gt;30&amp;lt;/Age&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Name&amp;gt;Otto&amp;lt;/Name&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Age&amp;gt;23&amp;lt;/Age&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;User&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Name&amp;gt;Jessica&amp;lt;/Name&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Age&amp;gt;8&amp;lt;/Age&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/User&amp;gt; &lt;br /&gt;&amp;lt;/NewDataSet&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;再生成一个名为data.xsd的文件，使用如下对应的格式：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;lt;?xml version="1.0" ?&amp;gt; &lt;br /&gt;&amp;lt;xs:schema &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id="NewDataSet" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; targetNamespace="&lt;a href="http://tempuri.org/data.xsd&amp;quot;"&gt;http://tempuri.org/data.xsd"&lt;/a&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:mstns="&lt;a href="http://tempuri.org/data.xsd&amp;quot;"&gt;http://tempuri.org/data.xsd"&lt;/a&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns="&lt;a href="http://tempuri.org/data.xsd&amp;quot;"&gt;http://tempuri.org/data.xsd"&lt;/a&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:xs="&lt;a href="http://www.w3.org/2001/XMLSchema&amp;quot;"&gt;http://www.w3.org/2001/XMLSchema"&lt;/a&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; attributeFormDefault="qualified" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; elementFormDefault="qualified"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:element name="NewDataSet" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; msdata:IsDataSet="true" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; msdata:EnforceConstraints="False"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:complexType&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:choice maxOccurs="unbounded"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:element name="User"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:complexType&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:sequence&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:element &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name="Name" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type="xs:string" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; minOccurs="0" /&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xs:element &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name="Age" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type="xs:int" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; minOccurs="0" /&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:sequence&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:complexType&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:element&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:choice&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:complexType&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xs:element&amp;gt; &lt;br /&gt;&amp;lt;/xs:schema&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;最后我们新建一个名为users.cshtml的文件，并且编辑其内容为：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;@&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data;&lt;br /&gt;@{&lt;br /&gt;    var dataSet = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DataSet();&lt;br /&gt;    dataSet.ReadXmlSchema(Server.MapPath(&lt;span style="color: #006080;"&gt;"~/App_Data/data.xsd"&lt;/span&gt;));&lt;br /&gt;    dataSet.ReadXml(Server.MapPath(&lt;span style="color: #006080;"&gt;"~/App_Data/data.xml"&lt;/span&gt;));&lt;br /&gt;    var dataView = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DataView(dataSet.Tables[0]);&lt;br /&gt;&lt;br /&gt;    var myChart = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Chart(width: 350, height: 300)&lt;br /&gt;        .AddTitle(&lt;span style="color: #006080;"&gt;"用户年龄"&lt;/span&gt;)&lt;br /&gt;        .AddSeries(&lt;span style="color: #006080;"&gt;"图表"&lt;/span&gt;, &lt;br /&gt;            xValue: dataView, xField: &lt;span style="color: #006080;"&gt;"Name"&lt;/span&gt;,&lt;br /&gt;            yValues: dataView, yFields: &lt;span style="color: #006080;"&gt;"Age"&lt;/span&gt;)&lt;br /&gt;        .Write();&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;解释一下上面的代码 using System.Data 表示要引用 System.Data 类库.&lt;/p&gt;&lt;p&gt;DataSet.ReadXmlSchema 读取我们将要使用数据的结构,ReadXml读取数据源.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;DataView从dataSet中得到第一个表格,即我们要使用的数据:&lt;/p&gt;&lt;p&gt;点击run后,生成的页面如下:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228263570.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="ScreenShot042" alt="ScreenShot042" src="http://images.cnblogs.com/cnblogs_com/multiplesoftware/201109/201109300228288040.jpg" border="0" height="260" width="318" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;本文来自于&lt;a href="http://www.cnblogs.com/multiplesoftware/"&gt;喜乐的ASP.NET(Alex Song)&lt;/a&gt; 转贴请注明出处&lt;/p&gt;&lt;img src="http://www.cnblogs.com/multiplesoftware/aggbug/2196075.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/multiplesoftware/archive/2011/09/30/2196075.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
