﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Ivony...</title><link>http://www.cnblogs.com/Ivony/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 05 Jul 2009 16:46:48 GMT</lastBuildDate><pubDate>Sun, 05 Jul 2009 16:46:48 GMT</pubDate><ttl>60</ttl><item><title>“九种不够面向对象的对象“的在实际项目中的合理运用</title><link>http://www.cnblogs.com/Ivony/archive/2009/07/04/1516932.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Sat, 04 Jul 2009 11:59:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2009/07/04/1516932.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1516932.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2009/07/04/1516932.html#Feedback</comments><slash:comments>44</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1516932.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1516932.html</trackback:ping><description><![CDATA[<p>本文可以视为对<a href="http://www.cnblogs.com/DesignPatterns/archive/2009/07/04/nine-non-oo-o.html">http://www.cnblogs.com/DesignPatterns/archive/2009/07/04/nine-non-oo-o.html</a>文中观点的反面意见。</p>
<p>&nbsp;</p>
<p>在引用的这篇文章中，作者指出了九个其认为&#8220;不够面向对象&#8221;的对象。而本人一直不喜欢不是面向对象或者不够面向对象这样的提法，在本人看来，所有的这些对象不过是因为其不够饱满，而在实际的项目设计中，根本没有必要要求所有的对象都是饱满的。对象的饱满程度与对象的设计粒度有关系，简单的说，如果是一个非常简单的项目，比如说输入一个数输出某种算法的结果这样的小练习，一个对象负责交互、计算、计时等等工作是没有任何问题的。但是如果你是做一个计算器，那么你把这些东西都写在一个类型里面，粒度就明显过大了。</p>
<p>仍然用生物界来做例子，将对象比喻成细胞，那么对于原生生物而言，只需要一个细胞（一个对象）就够了，这个细胞可以自行增殖、吸取养分，甚至可以抵御外敌和自由行动。但是对于高级生物而言，则需要大量的细胞协同工作，这些细胞可以是没有行为的（骨骼细胞），也可以是不能增殖的（脂肪细胞），但这些都不影响它们在存在的合理性。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>废话不多说，下面随便指出几个所谓的不够面向对象在设计中的合理运用：</p>
<p>&nbsp;</p>
<p>1、贫血对象，事实上就是退化成数据结构的对象，对象可以视为是数据结构的扩展，对象=数据+行为。如果一个数据自己没有行为可不可以呢？没有道理不可以的，比如说狗会叫，石头会叫么？石头难道就不是对象了？没有行为的对象最著名的如string，另外如Uri，所有的基元类型也可以视为是所谓的贫血对象。不要以为这样的对象就与OO没有关系，没有石头用什么去打狗呢？说设计是不是合理，取决于这个东西是不是丢失了本来应该有的行为，而不是说没有行为的都不是Object了。</p>
<p>2、管理者对象，其实就是抛弃了数据结构只剩下方法退化成方法组的对象。同上面的对象的存在是合理的一样，只有方法组的对象存在也是合理的。而且非常重要，因为方法是多态的。绞肉机需要自己有肉么？刀子需要自己有苹果么？那么方法组为什么一定要带上数据呢？比如说我们定义一个刀子类，显然这个刀子是不需要自己有苹果的，没有人会new 刀( 一个苹果 )吧？而只可能是：一把刀.切( 一个苹果 )。而且，我们可以方便的class 花刀 : 刀，利用多态的特性来使得我们可以把苹果切成星型、三角形等各种形状。你能说这不是OO么？</p>
<p>3、储柜对象，事实上是一个强类型的Dictionary，这种对象存在的意义与Dictionary存在的意义是一样的（或者说就是1的情况）。既可以作为数据打包的传递，也可以作为一个适配器来对某个抽象的、不存在的东西进行控制。作为Dictionary的用途就不说了，说说适配器的用途。比如说DOM模型中的对象，大部分对象的属性都是R/W的，这样的对象实际上是文档模型的一个适配器，通过修改对象来修改文档。这又有何不可呢？</p>
<p>4、多管闲事的对象，虽然这大多数情况下是抽象的问题，但在一个优秀合理的设计中这种情况也并非不存在。就那篇文章的作者所举的例子而言，完全属于抽象的问题，Pet怎么可能都会CatchRat？这是很滑稽的。但一个类型将继承的方法屏蔽这种情况却&#8220;不都是&#8221;抽象的问题。比如说我们设计一个类：猫，那么猫一定会吃东西、能跑跳。但是残疾的猫和昏迷的猫呢？那么它们不是猫么？显然它们也是猫，但是并不是所有猫都具备的行为它们都有，这样的情形，就必须在派生类中屏蔽基类方法来实现。而不可能是我们将猫去继承于残疾猫。继承关系的最大原则是抽象关系，具体类型继承抽象类型。其他原则是帮助我们把握抽象关系的方法，而不是必须遵循的原则。</p>
<p>最后关于第8点谈谈，没有专属自己的数据，没有专属自己的行为，就不要一个类型这样的说法显然是不靠谱的，是不是需要一个类型，最重要的是看这个类型有没有意义，而不是这个类型有没有独特、专有的东西。类型的首先在于类型本身而不在于其成员。或者说，正确的设计是先确定类型，然后再设计其成员，而不是将成员列张表然后归纳出几个类型。比如说我们设计一个正方形类，继承于矩形，请问这个正方形是有什么它有而矩形没有的呢？但是这个类型是有意义的，比如说我们有些方法只能对正方形进行操作，就不应该接收一个矩形对象，然后判断这是不是一个正方形。</p><img src ="http://www.cnblogs.com/Ivony/aggbug/1516932.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47989/" target="_blank">Twitter无处不在 魔兽世界Twitter发送器插件发布</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>某个最近不知道为啥很火的小题目的LINQ实现</title><link>http://www.cnblogs.com/Ivony/archive/2009/06/30/1514132.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Tue, 30 Jun 2009 08:52:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2009/06/30/1514132.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1514132.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2009/06/30/1514132.html#Feedback</comments><slash:comments>19</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1514132.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1514132.html</trackback:ping><description><![CDATA[<p>题目是老赵的：</p>
<p><a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/06/21/1507847.html">http://www.cnblogs.com/JeffreyZhao/archive/2009/06/21/1507847.html</a></p>
<p>代码如下：</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;IEnumerable</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">[]</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;Compute(&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;min,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;max,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;sum,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;count&nbsp;)<br /></span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img id="Codehighlighter1_89_421_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_89_421_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_89_421_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_89_421_Closed_Text').style.display='inline';" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_89_421_Closed_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_89_421_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_89_421_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_89_421_Open_Text').style.display='inline';" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_89_421_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_89_421_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;list&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Enumerable.Range(&nbsp;min,&nbsp;max&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;min&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">1</span><span style="color: #000000">&nbsp;);<br /></span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(&nbsp;count&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">1</span><span style="color: #000000">&nbsp;)<br /></span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img id="Codehighlighter1_241_249_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_241_249_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_241_249_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_241_249_Closed_Text').style.display='inline';" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_241_249_Closed_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_241_249_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_241_249_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_241_249_Open_Text').style.display='inline';" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;from&nbsp;item&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;list&nbsp;</span><span style="color: #0000ff">where</span><span style="color: #000000">&nbsp;item&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;sum&nbsp;select&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">[]&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_241_249_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_241_249_Open_Text"><span style="color: #000000">{&nbsp;item&nbsp;}</span></span><span style="color: #000000">;<br /></span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;list.SelectMany(&nbsp;number&nbsp;</span><span style="color: #000000">=&gt;</span><span style="color: #000000">&nbsp;Compute(&nbsp;number,&nbsp;max,&nbsp;sum&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;number,&nbsp;count&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">1</span><span style="color: #000000">&nbsp;)<br /></span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img id="Codehighlighter1_388_398_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_388_398_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_388_398_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_388_398_Closed_Text').style.display='inline';" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_388_398_Closed_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_388_398_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_388_398_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_388_398_Open_Text').style.display='inline';" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Select(&nbsp;item&nbsp;</span><span style="color: #000000">=&gt;</span><span style="color: #000000">&nbsp;item.Concat(&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">[]&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_388_398_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_388_398_Open_Text"><span style="color: #000000">{&nbsp;number&nbsp;}</span></span><span style="color: #000000">&nbsp;).ToArray()&nbsp;)&nbsp;);<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">11</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span></div>
<p>&nbsp;</p>
<p>代码随手写成，仅仅只是用LINQ来实现了一下而已。事实上也能看出LINQ之强大，绝不仅仅是语法糖那么简单</p>
<p>&nbsp;</p>
<p>另外也顺便出道小题目，大家也可以尝试用LINQ来解一下。</p>
<p>分解质因数，输入一个正整数，要求输出其质因数分解形式</p>
<p>如输入：66，应输出：</p>
<p>66 = 3 * 2 * 11</p>
<p>而</p>
<p>66 = 6 * 11</p>
<p>是错误的。</p>
<p>&nbsp;</p>
<p>又如24，应输出：</p>
<p>24 = 2 * 2 * 2 * 3</p><img src ="http://www.cnblogs.com/Ivony/aggbug/1514132.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47988/" target="_blank">Firefox 3.5匆忙推出漏洞多 Mozilla本月将更新</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>XCommunity权限控制和配置体系</title><link>http://www.cnblogs.com/Ivony/archive/2009/06/28/1512817.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Sun, 28 Jun 2009 11:46:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2009/06/28/1512817.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1512817.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2009/06/28/1512817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1512817.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1512817.html</trackback:ping><description><![CDATA[<p>1、问题</p>
<p>我们知到一般说到权限管理配置，最常见的就是这样的形式：</p>
<p>in:某人、某事</p>
<p>out:允许或拒绝。</p>
<p>更强大一些无非加入用户组的概念，某用户组的人，某事。</p>
<p>但实际上，在稍微复杂的系统中，这样的模式是很糟糕的，比如说论坛。</p>
<p>&nbsp;</p>
<p>比如说，我要定义一个这样的权限：</p>
<p>用户可以在自己发起的话题中修改自己发布的回复。</p>
<p>这里的某人是针对任何人的，而某事是：&#8220;在自己发起的话题中修改自己发布的回复&#8221;，最后控制级别是允许。</p>
<p>&nbsp;</p>
<p>这里面有两个问题：</p>
<p>1、某人和某事是紧密联系在一起的，某事是针对特定的人的。而在传统的模式中，这两者是分开的，操作发起方应告诉权限控制系统完整的某事，即操作方还必须去判断这个是不是自己的话题和回复。</p>
<p>2、这个某事可以由几个基本条件组合出非常多的变化，不可能一开始都想到。</p>
<p>&nbsp;</p>
<p>为了便于理解，我还是啰嗦两句，说明传统的方式会遇到多大的麻烦：</p>
<p>因为传统的权限控制方式只是简单的接受两个参数（某人，某事）然后查权限控制表，组合一下权限控制级别（Deny &gt; Allow），然后告诉我们，你可不可以这么做。</p>
<p>那么，当用户点击修改按钮的时候，这个按钮必须自己判断出来，这个用户是不是在修改自己发表的回复，以及是不是在自己发起的话题里，然后告诉权限控制系统，这个用户正&#8220;在自己发起的话题中修改自己发布的回复&#8221;或者正&#8220;在不是自己发起的话题中修改自己发布的回复&#8221;或者。。。。。。</p>
<p>这样的组合我们不知道有多少种。</p>
<p>然后权限控制系统根据如此这些信息，查表得出结论，可以这么做。</p>
<p>&nbsp;</p>
<p>所以，这种权限管理方式是不现实的。</p>
<p>&nbsp;</p>
<p>2、权限项（ControlItem）</p>
<p>XCommunity的权限配置体系最小的配置项是权限控制项（ControlItem）。其定义为：</p>
<p>&nbsp;</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000"> IControlItem<br /></span><span style="color: #008080">2</span><span style="color: #000000"><img id="Codehighlighter1_30_186_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_30_186_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif"  alt="" /></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_30_186_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_30_186_Open_Text"><span style="color: #000000">{ <br /></span><span style="color: #008080">3</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">4</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp; </span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsSatisfied( IPrincipal user, </span><span style="color: #0000ff">string</span><span style="color: #000000"> verb, </span><span style="color: #0000ff">params</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">object</span><span style="color: #000000">[] frameObjects ); <br /></span><span style="color: #008080">5</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">6</span><span style="color: #000000"><img id="Codehighlighter1_149_157_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_149_157_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp; EntryControlType ControlType </span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_149_157_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_149_157_Open_Text"><span style="color: #000000">{ </span><span style="color: #0000ff">get</span><span style="color: #000000">; }</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">7</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">8</span><span style="color: #000000"><img id="Codehighlighter1_174_182_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_174_182_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp; </span><span style="color: #0000ff">string</span><span style="color: #000000"> Name </span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_174_182_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_174_182_Open_Text"><span style="color: #000000">{ </span><span style="color: #0000ff">get</span><span style="color: #000000">; }</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">9</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">10</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">11</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span></div>
<p>一个权限控制项就如同刚才我描述权限的那一个陈述句一样：&#8220;用户可以在自己发起的话题中修改自己发布的回复&#8221;。 
<p>将这个陈述句拆分成两个部分：&#8220;用户在自己发起的话题中修改自己发布的回复&#8221;，&#8220;可以&#8221;。</p>
<p>即条件（Condition）和控制类别（允许或拒绝）。</p>
<p>IsSatisfied方法用于判断当前是不是&#8220;用户在自己发起的话题中修改自己发布的回复&#8221;。</p>
<p>ControlType属性则告诉权限管理系统，如果是，则&#8220;可以&#8221;。</p>
<p>&nbsp;</p>
<p>IsSatisfied方法的参数用于描述当前的情况（instance），使用了一个主谓宾结构来描述：</p>
<p>user，发起者，主语</p>
<p>verb，动词，谓语</p>
<p>frameObjects，所涉及到的框架对象，宾语。</p>
<p>&nbsp;</p>
<p>这个结构中的核心是verb，动词。动词决定了宾语的结构，XCommunity预定义的动词与宾语结构的关系如下：</p>
<table border="0" cellspacing="0" cellpadding="2" width="752">
<tr>
<td valign="top" width="118">verb</td>
<td valign="top" width="182">动词描述</td>
<td valign="top" width="102">BoardFrame</td>
<td valign="top" width="105">TopicFrame</td>
<td valign="top" width="91">PostFrame</td>
<td valign="top" width="152">PublishedDocument</td></tr>
<tr>
<td valign="top" width="118">ModifyPost</td>
<td valign="top" width="182">修改一个帖子</td>
<td valign="top" width="102">&nbsp;</td>
<td valign="top" width="105">帖子所属的话题</td>
<td valign="top" width="91">被修改的帖子</td>
<td valign="top" width="152">&nbsp;</td></tr>
<tr>
<td valign="top" width="118">DeletePost</td>
<td valign="top" width="182">从话题删除一个帖子</td>
<td valign="top" width="102">&nbsp;</td>
<td valign="top" width="105">帖子所属的话题</td>
<td valign="top" width="91">被删除的帖子</td>
<td valign="top" width="152">&nbsp;</td></tr>
<tr>
<td valign="top" width="118">ModifyTopicTitle</td>
<td valign="top" width="182">修改话题的标题</td>
<td valign="top" width="102">话题所在的版面</td>
<td valign="top" width="105">被修改的话题</td>
<td valign="top" width="91">&nbsp;</td>
<td valign="top" width="152">&nbsp;</td></tr>
<tr>
<td valign="top" width="118">DeleteTopic</td>
<td valign="top" width="182">从版面删除一个话题</td>
<td valign="top" width="102">话题所在的版面</td>
<td valign="top" width="105">被修改的话题</td>
<td valign="top" width="91">&nbsp;</td>
<td valign="top" width="152">&nbsp;</td></tr>
<tr>
<td valign="top" width="118">LaunchTopic</td>
<td valign="top" width="182">在版面发起一个话题</td>
<td valign="top" width="102">发起话题的版面</td>
<td valign="top" width="105">&nbsp;</td>
<td valign="top" width="91">&nbsp;</td>
<td valign="top" width="152">用于发起话题的文档</td></tr>
<tr>
<td valign="top" width="118">AttachTopic</td>
<td valign="top" width="182">加入一个话题的讨论</td>
<td valign="top" width="102">&nbsp;</td>
<td valign="top" width="105">被参与的话题</td>
<td valign="top" width="91">&nbsp;</td>
<td valign="top" width="152">用于发表回复的文档</td></tr></table>
<p>&nbsp;</p>
<p>BoardFrame、TopicFrame、PostFrame、PublishedDocument统称为框架对象（FrameObject）。frameObjects参数包含了所有相关的框架对象，由于在每一种宾语结构中，每个类型的对象都只有一个，所以用OfType方法来找出需要的框架对象。</p>
<p>&nbsp;</p>
<p>用于描述&#8220;用户可以在自己发起的话题中修改自己发布的回复&#8221;的权限控制项的实现就可以是这样的：</p>
<p>&nbsp;</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000"> AllowModifyOwnResponseInOwnTopic : IControlItem<br /></span><span style="color: #008080">2</span><span style="color: #000000"><img id="Codehighlighter1_61_728_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_61_728_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif"  alt="" /></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_61_728_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_61_728_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">3</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp; </span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000"> IsSatisfied( IPrincipal user, </span><span style="color: #0000ff">string</span><span style="color: #000000"> verb, </span><span style="color: #0000ff">params</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">object</span><span style="color: #000000">[] frameObjects )<br /></span><span style="color: #008080">4</span><span style="color: #000000"><img id="Codehighlighter1_153_549_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_153_549_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp; </span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_153_549_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_153_549_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">5</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000"> ( verb </span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">ModifyPost</span><span style="color: #800000">"</span><span style="color: #000000"> )<br /></span><span style="color: #008080">6</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">; <br /></span><span style="color: #008080">7</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">8</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; var topic </span><span style="color: #000000">=</span><span style="color: #000000"> frameObjects.OfType</span><span style="color: #000000">&lt;</span><span style="color: #000000">ITopicFrame</span><span style="color: #000000">&gt;</span><span style="color: #000000">().Single();<br /></span><span style="color: #008080">9</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000"> ( </span><span style="color: #000000">!</span><span style="color: #000000">user.Identity.IsMySelf( topic.Meta.Launcher ) )<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">; <br /></span><span style="color: #008080">11</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">12</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; var post </span><span style="color: #000000">=</span><span style="color: #000000"> frameObjects.OfType</span><span style="color: #000000">&lt;</span><span style="color: #000000">IPostFrame</span><span style="color: #000000">&gt;</span><span style="color: #000000">().Single();<br /></span><span style="color: #008080">13</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000"> ( post.IsTheme )<br /></span><span style="color: #008080">14</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">; <br /></span><span style="color: #008080">15</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">16</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000"> ( </span><span style="color: #000000">!</span><span style="color: #000000">user.Identity.IsMySelf( post.Author ) )<br /></span><span style="color: #008080">17</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">; <br /></span><span style="color: #008080">18</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">19</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">; <br /></span><span style="color: #008080">20</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">21</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp; }</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">22</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">23</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp; </span><span style="color: #0000ff">public</span><span style="color: #000000"> EntryControlType ControlType<br /></span><span style="color: #008080">24</span><span style="color: #000000"><img id="Codehighlighter1_592_640_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_592_640_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp; </span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_592_640_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_592_640_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">25</span><span style="color: #000000"><img id="Codehighlighter1_602_636_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_602_636_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_602_636_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_602_636_Open_Text"><span style="color: #000000">{ </span><span style="color: #0000ff">return</span><span style="color: #000000"> EntryControlType.Allow; }</span></span><span style="color: #000000"><br /></span><span style="color: #008080">26</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp; }</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">27</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /><br /></span><span style="color: #008080">28</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" />&nbsp; </span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">string</span><span style="color: #000000"> Name<br /></span><span style="color: #008080">29</span><span style="color: #000000"><img id="Codehighlighter1_666_726_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_666_726_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp; </span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_666_726_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_666_726_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">30</span><span style="color: #000000"><img id="Codehighlighter1_676_722_Open_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_676_722_Closed_Image" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_676_722_Closed_Text"><img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span id="Codehighlighter1_676_722_Open_Text"><span style="color: #000000">{ </span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">AllowModifyOwnResponseInOwnTopic</span><span style="color: #800000">"</span><span style="color: #000000">; }</span></span><span style="color: #000000"><br /></span><span style="color: #008080">31</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp; }</span></span><span style="color: #000000"><br /></span><span style="color: #008080">32</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000">&nbsp;<br /></span><span style="color: #008080">33</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br /></span><span style="color: #008080">34</span><span style="color: #000000"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span></div>
<p>&nbsp; 
<p>这样，所有已想到和没想到的权限设置都可以用一个个的类型来描述了。 
<p>3、配置</p>
<p>但是如果所有的权限控制项都用代码来实现，是不现实的。所以，同样的，权限控制项可以通过XML文件来配置。</p>
<p>一个权限控制项典型的配置如下：</p>
<p>&nbsp;</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
<p><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">verb</span><span style="color: #0000ff">=&#8221;DeletePost&#8221;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Deny</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span></p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>其中condition元素对应为IsSatisfied方法，control-type则对应ControlType属性。该控制项表示任何情况下都禁止删除帖子的操作。</p>
<p>&lt;condition&gt;元素主要有两种配置方案：</p>
<p>设置一个类或者方法来处理，如：</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=&#8221;XCommunity.Forums.Users.ControlConditions.ModifyOwnResponse&#8221;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />或<br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">method</span><span style="color: #0000ff">=&#8221;XCommunity.Forums.Users.ControlConditions.IsModifyOwnResponse&#8221;&nbsp;</span><span style="color: #0000ff">/&gt;</span></div>
<p>&nbsp;</p>
<p>直接通过XML来配置一系列条件的组合，如上例的&#8220;用户可以在自己发起的话题中修改自己发布的回复&#8221;可以如此设置：</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">verb</span><span style="color: #0000ff">=&#8221;ModifyPost&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">topic&nbsp;</span><span style="color: #ff0000">launcher</span><span style="color: #0000ff">=&#8221;#current-logged&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">post&nbsp;</span><span style="color: #ff0000">theme</span><span style="color: #0000ff">=&#8221;false&#8221;&nbsp;</span><span style="color: #ff0000">author</span><span style="color: #0000ff">=&#8221;#current-logged&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">condition</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Allow</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span></div>
<p>&nbsp;</p>
<p>其中的topic和post会自动对应为frameObjects中的ITopicFrame对象和IPostFrame对象。当然，如果要对自定义类型的对象进行条件判断，也可以透过简单的语法实现：</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">verb</span><span style="color: #0000ff">=&#8221;AttachTopic&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">frame-object&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=&#8221;MyTopic&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">=&#8221;locked&#8221;&nbsp;</span><span style="color: #ff0000">value</span><span style="color: #0000ff">=&#8221;false&#8221;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">frameObject</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">condition</span><span style="color: #0000ff">&gt;</span></div>
<p>&nbsp;</p>
<p>condition元素可以包含多个条件，各个条件之间都是与的关系，如果某个条件因为某些原因无法判断，例如找不到指定类型的对象，则直接判否。</p>
<p>&nbsp;</p>
<p>4、控制组</p>
<p>权限控制项的粒度是很小的，很多时候我们需要设置一批权限控制项，所以我们需要将一些权限控制项组合在一起加以管理，这就是权限控制组，同样用XML文件来配置：</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-group&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">=&#8221;DemoGroup&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">verb</span><span style="color: #0000ff">=&#8221;ModifyPost&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">topic&nbsp;</span><span style="color: #ff0000">launcher</span><span style="color: #0000ff">=&#8221;#current-logged&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">post&nbsp;</span><span style="color: #ff0000">theme</span><span style="color: #0000ff">=&#8221;false&#8221;&nbsp;</span><span style="color: #ff0000">author</span><span style="color: #0000ff">=&#8221;#current-logged&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">condition</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Allow</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">verb</span><span style="color: #0000ff">=&#8221;AttachTopic&#8221;&gt;<br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000">&lt;frame-object&nbsp;type</span><span style="color: #0000ff">=&#8221;MyTopic&#8221;&gt;<br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000">&lt;property&nbsp;name</span><span style="color: #0000ff">=&#8221;locked&#8221;&nbsp;</span><span style="color: #ff0000">value</span><span style="color: #0000ff">=&#8221;false&#8221;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">frameObject</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">condition</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-group</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span></div>
<p>&nbsp;</p>
<p>但有时候同一个权限项可能被多个组包含，为了避免重复代码，所以还支持这样的语法。</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">=&#8221;AllowModifyOwnResponseInOwnTopic&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">condition&nbsp;</span><span style="color: #ff0000">verb</span><span style="color: #0000ff">=&#8221;ModifyPost&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">topic&nbsp;</span><span style="color: #ff0000">launcher</span><span style="color: #0000ff">=&#8221;#current-logged&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">post&nbsp;</span><span style="color: #ff0000">theme</span><span style="color: #0000ff">=&#8221;false&#8221;&nbsp;</span><span style="color: #ff0000">author</span><span style="color: #0000ff">=&#8221;#current-logged&#8221;&nbsp;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">condition</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Allow</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-type</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-group</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">control-item&nbsp;</span><span style="color: #ff0000">ref</span><span style="color: #0000ff">=&#8221;AllowModifyOwnResponseInOwnTopic&#8221;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /><img align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">control-group</span><span style="color: #0000ff">&gt;</span></div>
<p>&nbsp;</p>
<p>同样的，控制组也可以命名，并且被包含于其他控制组内。</p>
<p>权限控制组和控制项的定义都必须包含在授权配置元素（authorities）内。不包含在任何权限控制组内的权限控制项和组定义必须是命名的（name属性是必须的），而在控制组内的内联定义则不能命名（不能有name属性），即authorities的直接子元素的control-item和control-group是必须具备name属性的，而control-group内的control-item和control-group则是不能有name属性的。</p><img src ="http://www.cnblogs.com/Ivony/aggbug/1512817.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47987/" target="_blank">预测：Twitter最可能收购的十家公司</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>寻求空间支持</title><link>http://www.cnblogs.com/Ivony/archive/2009/06/25/1510980.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Thu, 25 Jun 2009 06:46:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2009/06/25/1510980.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1510980.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2009/06/25/1510980.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1510980.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1510980.html</trackback:ping><description><![CDATA[寻求支持.NET Framework 3.5以及SQL Server的空间，最好有本地磁盘读写权限（特定数据目录）。<img src ="http://www.cnblogs.com/Ivony/aggbug/1510980.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47986/" target="_blank">网易澄清:与暴雪合资公司仅提供技术支持</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>线程冲突详解</title><link>http://www.cnblogs.com/Ivony/archive/2009/05/14/1457056.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Thu, 14 May 2009 11:03:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2009/05/14/1457056.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1457056.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2009/05/14/1457056.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1457056.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1457056.html</trackback:ping><description><![CDATA[<p>今天被GF问到一个问题，某个函数在多线程环境中，会不会有冲突。在帮她解答这个问题的过程中，发现很多人对线程冲突和线程安全的理解并不是很全面，所以萌发了写这么一篇文章的想法，也算是对GF的问题的一个完整的解答。</p> <p>水平有限，如有错漏指出敬请指出。</p> <p>&nbsp;</p> <h2>一、什么是线程冲突</h2> <p>线程冲突其实就是指，两个或以上的线程同时对同一个共享资源进行操作而造成的问题。</p> <p>一个比较经典的例子是，用一个全局变量做计数器，然后开N个线程去完成某个任务，每个线程完成一次任务就将计数器加一，直到完成100次任务。如果不考虑线程冲突问题，用类似下面的代码去做，则很可能会超额完成任务，线程越多，完成任务次数超出100次的可能性就越大。</p> <p>伪代码如下：</p> <p>&nbsp;</p> <p>int count = 0;//全局计数器</p> <p>&nbsp;</p> <p>void ThreadMethod()//运行在每个线程的方法</p> <p>{</p> <p>&nbsp; while( true )</p> <p>&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp; if ( count &gt;= 100 )//如果达到任务指标</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;//中断线程执行</p> <p>&nbsp;&nbsp;&nbsp; DoSomething();//完成某个任务</p> <p>&nbsp;&nbsp;&nbsp; count++;</p> <p>&nbsp; }</p> <p>}</p> <p>//省略线程的创建等代码。</p> <p>&nbsp;</p> <p>具体的，为什么会超额完成任务的原因在这里我就不赘述了，这个例子在单线程环境中是绝对不会超额完成任务的。</p> <p>当然，在这个例子中，将count++放到if语句中，也许能降低一些事故发生的概率，但那不是绝对的，换言之这样的程序不能杜绝超额完成任务的可能。</p> <p>&nbsp;</p> <p>其实从线程冲突的定义中我们不难发现，要造成线程冲突有两个必要条件：多线程和共享资源。这两个条件中有一个不成立，就不可能发生线程冲突问题。</p> <p>所以，在单线程环境中，是不存在线程冲突的问题的。不过很可惜的是，我们的软件早已进化到了多进程多线程的时代，单线程的程序几乎是不存在的，无论是WinForm还是WebForm，程序运行的环境都是多线程的，而不论你自己是不是明确的开启了一个线程。</p> <p>既然多线程是不可避免的，那么要避免线程冲突就只能从共享资源来开刀了。</p> <p>&nbsp;</p> <h2>二、线程安全的资源</h2> <p>如果大家经常看MSDN或者VS帮助中的.NET类库参考的话，就不难发现几乎所有的类型都有这么一句话的描述：“此类型的任何公共 static（在 Visual Basic中为 Shared） 成员都是线程安全的。但不保证所有实例成员都是线程安全的。”那么线程安全到底是什么意思？</p> <p>其实线程安全很简单，就是指一个函数（方法、属性、字段或者别的）在同一时间被不同线程使用，不会造成任何线程冲突的问题。就说这个东西是线程安全的。</p> <p>接下来来谈谈什么样的资源是线程安全的。</p> <p>&nbsp;</p> <p>之所以使用资源这个词，是因为线程冲突不仅仅会发生在共享的变量上，两个线程同时对同一个文件进行读写，两个程序同时用同一个端口与同一个地址进行通信，都会造成线程冲突。只不过是操作系统和帮我们协调了这些冲突而已。</p> <p>&nbsp;</p> <p>一个线程安全的资源即是指，在不同线程中使用不会导致线程冲突问题的资源。</p> <p>&nbsp;</p> <p>一个不能被改变的资源是线程安全的，比如说一个常量：</p> <p>const decimal pai = 3.14159265;</p> <p>//C++: const double pai = 3.14159265;</p> <p>因为pai的值不可能被改变，所以在不同的线程中使用也不会造成冲突。换言之它在不同的线程中同时被使用和在一个线程中被使用是没有区别的，所以这个东西<strong>是</strong>线程安全的。</p> <p>同样的，在.NET中，一个字符串的<strong>实例</strong>也是线程安全的，因为字符串的实例在.NET中也是不可以被改变的。一个字符串的实例一旦被创建，对其所有的属性、方法调用的结果都是唯一确定的，永远不会改变的。所以.NET类库参考中String类型才有：“此类型是线程安全的。”，与之类似的Type类型、Assembly类型，都是线程安全的。</p> <p>但string的<strong>实例</strong>是线程安全的，却不代表string的<strong>变量</strong>是线程安全的，换言之，假设有一个静态变量：</p> <p>public static string str = “123”;</p> <p>str不是线程安全的，因为str这个变量的字符串实例可以被任何线程修改。</p> <p>&nbsp;</p> <p>再考虑这样的例子：</p> <p>public static readonly SqlConnection connection = new SqlConnection( “connectionString” );</p> <p>虽然connection本身虽然是线程安全的，但connection的任何成员都不是线程安全的。</p> <p>比如说，我在一个线程中对这个connection调用了Open方法，然后进行查询操作。但在同一时刻，另一个线程调用了Close方法，这时候，就出现错误了。</p> <p>但，单纯的使用connection而不使用其任何成员，比如说if ( connection != null )这样的代码，是不存在线程冲突的。</p> <p>&nbsp;</p> <p>线程安全的资源其实还有很多，在此不一一赘述。</p> <p>&nbsp;</p> <p>对于.NET Framework的类型的成员来说，只读的字段是线程安全的。</p> <p>那么对于属性和方法来说，怎么知道是不是线程安全的？</p> <p>&nbsp;</p> <h2>三、线程安全的函数</h2> <p>因为属性和方法都是函数组成的，所以我们探讨一下什么是线程安全的函数。</p> <p>上面我们说到，线程冲突的必要条件是多线程和共享资源。那么如果一个函数里面没有使用任何可能共享的资源，那么就不可能出现线程冲突，也就是线程安全的。比如说这样的函数：</p> <p>public static int Add( int a, int b )</p> <p>{</p> <p>&nbsp; return a + b;</p> <p>}</p> <p>这个函数中所使用的所有的资源都是自己的局部变量，而函数的局部变量是储存在堆栈上的，每个线程都有自己独立的堆栈，所以局部变量不可能跨线程共享。所以这样的函数显然是线程安全的。</p> <p>&nbsp;</p> <p>但值得注意的是：下面的函数<strong>不是</strong>线程安全的：</p> <p>public static void Swap( ref int a, ref int b )</p> <p>//C++: void Swap( in&amp; a, int&amp; b )</p> <p>{</p> <p>&nbsp; int c = a;</p> <p>&nbsp; a = b;</p> <p>&nbsp; b = c;</p> <p>}</p> <p>因为ref的存在，使得函数的参数是按引用传递进来的，换言之a和b看起来是函数的局部变量，但实际上却是函数外面的东西，如果这两个东西是另一个函数的局部变量，倒也没有问题，如果这两个东西是全局变量（静态成员），就不能确保没有线程冲突了。而在上个例子中，a和b在传入函数之时，就做了一个拷贝的动作，所以传进来的a、b到底是全局变量还是静态成员都没有关系了。</p> <p>&nbsp;</p> <p>同样，这样的函数也<strong>不是</strong>线程安全的：</p> <p>public static int Add( INumber a, INumber b )</p> <p>//C++: int Add( INumber* a, INumber* b );</p> <p>{</p> <p>&nbsp; return a.Number + b.Number;</p> <p>&nbsp; //C++: return a-&gt;Number + b-&gt;Number;</p> <p>}</p> <p>原因在于a和b虽然是函数的内部变量没错，但a.Number和b.Number却不是，它们不存在于堆栈上，而是在托管堆上，可能被其他线程更改。</p> <p>&nbsp;</p> <p>但只使用局部变量的函数在.NET类库中是很少的，但.NET类库中还是有那么多线程安全的函数，是为什么呢？</p> <p>因为，即使一个函数使用了共享资源，如果其所使用的共享资源都是线程安全的，则这个函数也是线程安全的。</p> <p>比如说这样的函数：</p> <p>&nbsp;</p> <p>private const string connectionString = “…”;</p> <p>public string GetConnectionString()</p> <p>{</p> <p>&nbsp; return connectionString;</p> <p>}</p> <p>虽然这个函数使用了一个共享资源connectionString，但因为这个资源是线程安全的，所以这个函数还是线程安全的。</p> <p>&nbsp;</p> <p>同样的，我们可以得出，如果一个函数只调用线程安全的函数，只使用线程安全的共享资源，那么这个函数也是线程安全的。</p> <p>&nbsp;</p> <p>这里有一个容易被忽略的问题，运算符。并不是所有的运算符（尤其是重载后的运算符）都是线程安全的。</p> <p>&nbsp;</p> <h2>四、互斥锁</h2> <p>有时候我们不得不面对线程不安全的问题，比如说在一开始提出来的那个例子，多线程完成100次任务，我们怎样才能解决这个问题，一个简单的办法就是给共享资源加上互斥锁。在C#中这很简单。比如一开始的那个例子：</p> <p>public static class Environment</p> <p>{</p> <p>&nbsp; public static int count = 0;//全局计数器</p> <p>}</p> <p>//…</p> <p>&nbsp;</p> <p>void ThreadMethod()//运行在每个线程的方法</p> <p>{</p> <p>&nbsp; while( true )</p> <p>&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp; lock ( typeof( Environment ) )</p> <p>&nbsp;&nbsp;&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( count &gt;= 100 )//如果达到任务指标</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;//中断线程执行</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DoSomething();//完成某个任务</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count++;</p> <p>&nbsp;&nbsp;&nbsp; }</p> <p>&nbsp; }</p> <p>}</p> <p>通过互斥锁，使得一个线程在使用count字段的时候，其他所有的线程都无法使用，而被阻塞等待。达到了避免线程冲突的效果。</p> <p>当然，这样的锁会使得这个多线程程序退化成同时只有一个线程在跑，所以我们可以把count++提前，使得lock的范围缩小，如这样：</p> <p>void ThreadMethod()//运行在每个线程的方法</p> <p>{</p> <p>&nbsp; while( true )</p> <p>&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp; lock ( typeof( Environment ) )</p> <p>&nbsp;&nbsp;&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( count++ &gt;= 100 )//如果达到任务指标</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;//中断线程执行</p> <p>&nbsp;&nbsp;&nbsp; }</p> <p>&nbsp;&nbsp;&nbsp; DoSomething();//完成某个任务</p> <p>&nbsp; }</p> <p>}</p> <p>&nbsp;</p> <p>最后来聊聊SyncRoot的问题。</p> <p>用.NET的一定会有很多朋友困惑，为什么对一个容器加锁，需要这样写：</p> <p>lock( Container.SyncRoot )</p> <p>而不是直接lock( Container )</p> <p>&nbsp;</p> <p>因为锁定一个容器并不能保证不会对这个容器进行修改，考虑这样一个容器：</p> <p>&nbsp;</p> <p>public class Collection</p> <p>{</p> <p>&nbsp; private ArrayList _list;</p> <p>&nbsp; public Add( object item )</p> <p>&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp; _list.Add( item );</p> <p>&nbsp; }</p> <p>&nbsp; public object this[ int index ]</p> <p>&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp; get { return _list[index]; }</p> <p>&nbsp;&nbsp;&nbsp; set { _list[index] = value;}</p> <p>&nbsp; }</p> <p>}</p> <p>看起来，将其lock起来后，就万事大吉了，没有人能修改这个容器，但实际上这个容器不过是用一个ArrayList实例来实现的，如果某段代码绕过这个容器而直接操作_list的话，则对这个容器对象lock也不可能保证容器不被修改了。</p><img src ="http://www.cnblogs.com/Ivony/aggbug/1457056.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47985/" target="_blank">杰克逊悼念仪式或成史上最大规模Web活动</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>漫谈社区架构</title><link>http://www.cnblogs.com/Ivony/archive/2008/10/31/1323388.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Thu, 30 Oct 2008 17:27:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2008/10/31/1323388.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1323388.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2008/10/31/1323388.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1323388.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1323388.html</trackback:ping><description><![CDATA[<p>现在Web最火的是什么？Web 2.0？Web 2.0最火的是什么？论坛和博客。论坛和博客以及诸如SNS等等，又可以合称为社区（Community）。</p>  <p>&#160;</p>  <p>一直以来，做一个属于自己的论坛就是我的梦想，一个可以想怎么扩展就怎么扩展的论坛，一个内部架构与表现层完全分离的论坛，一个稍加改动就可以变成博客或者你所能想到的所有的东西的论坛。</p>  <p>&#160;</p>  <p>这个东西如何才能从梦想变成一个切实的东西。最重要的便是，抽象架构。本文试图从笔者自己对论坛和博客的理解，谈谈社区的抽象架构。</p>  <p>&#160;</p>  <p>&#160;</p>  <p>首先社区是由用户发布的东西所构成的，这个东西可以是帖子、博文、照片等等等等，所有的这些，我通称为文档。文档被定义为，用户可以发布的最小单位。也就是说，用户最少一次只能发布一个文档（Document），而不能是一个文档片段或者其他的什么。文档这个东西，在论坛中，就是一个帖子，一个回复，一个BT种子（BitTorrentFileDocument）。而在博客中，便是一篇博文，一个评论，一个图片（PictureDocument），或者其他任何可以发布的东西。</p>  <p>&#160;</p>  <p>一个东西被发布（Publish）后，用户就必须舍弃一部分权利。比如说，一个帖子如果被发布到一个重要的板块（如投诉、建议、公告），就不能随便修改。从法理上来说，一个文档一旦被发布，其发布者就必须对发布时的状态负责，而无论这个文档是不是被人看过（比如说其中包含不实或诋毁他人的言论，或者一幅包含XX内容的图片）。所以，一个文档的发布与否，是非常重要的一件事情。所以我必须引入另一个概念，&#8220;已发布的文档&#8221;（PublishedDocument）。</p>  <p>&#160;</p>  <p>文档发布后想要让大家看到，就必须有个地方来展示。这个展示文档的东西，我暂时就叫它话题（Topic）吧。如果你想要发布一个东西引起大家的讨论，这就叫发起一个话题（LunchTopic）。如果你对这个话题有话要说，那么就叫做参与这个话题（AttachTopic），而你要说的话，还是必须被先包装成文档（Document），并发布（Publish）。</p>  <p>&#160;</p>  <p>话题其实是很多东西的一个抽象表达，因为我们刚才说了，Document本身就是一个抽象的东西，可以是一个文本文档（TextDocument），一个照片（PhotoDocument）。那么显然，话题除了可以是一篇博文和它的评论或者一个帖子和它的回复，还可以是一个照片和它的评论，一个投票和他的参与以及评论，一个问题和大家的回答，一个相册和大家的评价，等等等等&#8230;&#8230;总而言之，一个&#8220;发布的文档&#8221;的集合。当然，话题也可以仅仅就是一个公告，它就只有一个文档。</p>  <p>&#160;</p>  <p>但是话题又显然不是一个文档集合这么简单，这是因为话题包含了&#8220;已发布的文档&#8221;的关系和状态。一个显而易见的关系就是回应关系，我这个回复是针对哪个回复的，或者说我这个评论是针对哪个评论的。这是论坛上一个非常常见的功能。虽然这个关系可以用引用回复来解决，但这只是一种实现手段却不是说抽象模型中没有这个东西。</p>  <p>&#160;</p>  <p>话题中文档的另一个关系或状态我将它称为覆盖或者叫遮盖，在谈这个关系之前，我必须说说&#8220;已发布的文档&#8221;不可修改原则。</p>  <p>&#160;</p>  <p>显然，一个文档的修改与发布一个新的文档在本质上是没有任何不同的，而且在实际操作中，修改功能已经凸现出越来越多的弊端了。比如说&#8220;占楼&#8221;，意思就是指，先把位置占住，然后再利用修改功能将要发布的东西放到那个位置去。所以，文档的修改版本是不是要与原来的文档版本相同或者是在其上修改，这完全是一个良心问题。修改在很多时候也可以当作删除功能来使用，将回复修改成：&#8220;已被作者删除&#8221;，就完成了与删除回复雷同的功能。并且，很多人都习惯用修改来逃避应有的责任，虽然说这也是论坛上避免争端的一个方法（删除自己头脑发热的言论）。但是一个已经发布的东西改来改去带来的扯皮远比好处多。</p>  <p>&#160;</p>  <p>综上所述，不如干脆直接屏蔽&#8220;已发布的文档&#8221;的修改功能，这个功能的替代是&#8220;重发布&#8221;（Republish）。这不仅仅是改个名字而已，而是在架构上重新设计了。重发布的意思是，再发布一个文档到话题，以替换掉原先的文档。这个原先的文档（HistoricalDocument）的状态，就叫做被被覆盖（Shadowed）。这样修改后，至少在架构上，所有已发布的文档都会一直在话题中存在，至于被覆盖的文档，是不是被显示出来，这完全是UI的问题。</p>  <p>&#160;</p>  <p>这样设计的好处是相当多的，&#8220;已发布的文档&#8221;的版本关系不再是文档本身的属性，而是话题的属性。这样恰好避免了另一个问题：&#8220;管辖权限冲突&#8221;。这个冲突其实是比较麻烦的，也就是说，一个&#8220;已发布的文档&#8221;的所有者（作者、发布者）所拥有的权限（如修改，删除）会和这个文档所处的话题的管理者的权限相冲突。简单的说，你在一个板块发了一个帖子，版主修改了你的帖子，你不满意版主的做法，把帖子又擅自改回，版主又改过去。然后版主删掉你的帖子，使得你的成果丢失，你非常气恼，离开论坛。或者，一个菜鸟在他的博客上发表了一个问题，你觉得这个问题不怎么样，但是延伸开来有很多有价值的东西可以说，你去发表一篇很长的回复，结果那个菜鸟不明就里的把你的回复给删掉了，你气恼，你苦闷，你无助，离开这个博客。</p>  <p>&#160;</p>  <p>或者反过来，某人发表了一个诋毁你的言论，你气恼，你回应了一篇长篇大论来驳斥这个胡说八道，但是，那个家伙把他的帖子删掉了，这下子大家只看到你一个人在那里被当猴耍。</p>  <p>&#160;</p>  <p>OK，其实上面这些问题都是私有权限和公有权限不明确所造成的。一个已发布的文档不可以被修改（允许修改就等于允许删除），已发布的文档不能被所有者删除。就能彻底的解决上面这些乱七八糟的问题。</p>  <p>&#160;</p>  <p>事实上我考虑清楚重发布的问题后，很多问题都变得清晰起来了。</p>  <p>&#160;</p>  <p>一个文档没有被发布之前，这个东西是用户的私有财产，可以随便乱改，随便乱删。但是一旦被发布，就会出来一个&#8220;已发布的文档&#8221;的副本，不再是你的私有财产，必须受到话题的管辖。话题可以赋予用户修改（重发布）和删除的权利，也可以不赋予。并且，你发布后也可以对文档进行修改，或者别的操作，不过这些操作都是对你的私有副本的操作，而不是那个&#8220;已发布的文档&#8221;的副本。</p>  <p>&#160;</p>  <p>而且，以前那些纠缠不清操作和权限，一下子全清楚了。</p>  <p>&#160;</p>  <p>文档显然是可以被修改（Modify）的，也可以被删除（Delete）。但是一个话题里面的文档要被修改就叫做重发布（Republish），要删除一个话题里面的文档叫做从话题中移除（RemoveFromTopic）。</p>  <p>&#160;</p>  <p>这样梳理后，话题也可以被赋予一个新的定义，也就是管理权限的最小单位，所有的管理权限都可以被当成是对话题结构的修改（重发布、移除、拆分、合并、添加精华标记）。自此，话题成为公有区域和私有区域交接处。</p><img src ="http://www.cnblogs.com/Ivony/aggbug/1323388.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47984/" target="_blank">《商业周刊》:Mozilla的志愿者开发模式被复制</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>LINQ本质(再版)第二篇 运算</title><link>http://www.cnblogs.com/Ivony/archive/2008/10/14/1309807.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Tue, 14 Oct 2008 11:54:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2008/10/14/1309807.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1309807.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2008/10/14/1309807.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1309807.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1309807.html</trackback:ping><description><![CDATA[<p><font face="Consolas" size="2">从<a href="http://www.cnblogs.com/Ivony/archive/2008/08/28/1278643.html" target="_blank">上一篇文章</a>的论述中我们可以知道，.NET Framework使用IEnumerable&lt;T&gt;表示一个关系（集合），但反之不然。</font></p>  <p><font face="Consolas" size="2">不过IEnumerable&lt;T&gt;的本质是一个序列枚举器，所以IEnumerable&lt;T&gt;本身就具备三重特性，集合、关系、序列。</font></p>  <p><font face="Consolas" size="2">&#160;</font></p>  <p><font face="Consolas" size="2">.NET Framework定义了一个扩展类Enumerable用于对IEnumerable进行运算扩展，主要可以分为四部分：</font></p>  <p><font face="Consolas" size="2">一、查询/集合运算</font></p>  <blockquote>   <p><font face="Consolas" size="2"></font>&#160;</p>    <p><font face="Consolas" size="2">1、集合运算</font></p>    <p><font face="Consolas" size="2">Intersect 交集运算</font></p>    <p><font face="Consolas" size="2">Union 并集运算</font></p>    <p><font face="Consolas" size="2">Except 差集运算</font></p>    <p><font face="Consolas" size="2"></font>&#160;</p>    <p><font face="Consolas" size="2">2、查询运算</font></p>    <p><font face="Consolas" size="2">Where 筛选</font></p>    <p><font face="Consolas" size="2">Select和SelectMany 投射</font></p>    <p><font face="Consolas" size="2">GroupBy 分组</font></p>    <p><font face="Consolas" size="2">Join和GroupJoin 连接</font></p>    <p><font face="Consolas" size="2">OrderBy、OrderByDescending、ThenBy和ThenByDescending 排序</font></p>    <p><font face="Consolas" size="2"></font>&#160;</p>    <p><font face="Consolas" size="2">3、集合谓词逻辑</font></p>    <p><font face="Consolas" size="2">Any </font></p>    <p><font face="Consolas" size="2">All</font></p> </blockquote>  <p><font face="Consolas" size="2">&#160;</font></p>  <p><font face="Consolas" size="2">二、聚合运算</font></p>  <blockquote>   <p><font face="Consolas" size="2">Aggregate 迭代聚合</font></p>    <p><font face="Consolas" size="2">Max 最大</font></p>    <p><font face="Consolas" size="2">Min 最小</font></p>    <p><font face="Consolas" size="2">Sum 求和</font></p>    <p><font face="Consolas" size="2">Average 平均值</font></p>    <p><font face="Consolas" size="2">Count和LongCount 计数</font></p> </blockquote>  <p><font face="Consolas" size="2">&#160;</font></p>  <p><font face="Consolas" size="2">三、序列运算</font></p>  <blockquote>   <p><font face="Consolas" size="2">Take和TakeWhile</font></p>    <p><font face="Consolas" size="2">Skip和SkipWhile</font></p>    <p><font face="Consolas" size="2">First和FirstOrDefault</font></p>    <p><font face="Consolas" size="2">Last和LastOrDefault</font></p>    <p><font face="Consolas" size="2">ElementAt和ElementAtOrDefault</font></p>    <p><font face="Consolas" size="2">Contact</font></p>    <p><font face="Consolas" size="2">Reverse</font></p> </blockquote>  <p><font face="Consolas" size="2">&#160;</font></p>  <p><font face="Consolas" size="2">四、转换</font></p>  <blockquote>   <p><font face="Consolas" size="2">OfType 按类型筛选</font></p>    <p><font face="Consolas" size="2">Distinct 去除重复值</font></p>    <p><font face="Consolas" size="2"></font>&#160;</p>    <p><font face="Consolas" size="2">ToArray</font> </p>    <p><font face="Consolas" size="2">ToDictionary</font> </p>    <p><font face="Consolas" size="2">ToList</font> </p>    <p><font face="Consolas" size="2">ToLookup</font></p> </blockquote>  <p><font face="Consolas" size="2">对于LINQ而言，我们主要关注的是查询运算，即筛选、投射、分组、连接和排序。</font> </p>  <p><font face="Consolas" size="2">LINQ为C#和VB两种语言都发明了一种叫做LINQ Expression的东西来辅助我们编写查询，避免去冗长的调用那些方法。在这里，我们简单的对C#所支持的LINQ Expression做一个介绍。</font> </p>  <p><font face="Consolas" size="2">C#的LINQ Expression总是以一个from子句开始，from子句的格式与foreach的有些类似：</font> </p>  <p><font face="Consolas" size="2">from element in set</font> </p>  <p><font face="Consolas" size="2">from子句的最大作用在于定义元素与集合的关系用于后文使用，set是集合（IEnumerable&lt;T&gt;），element是集合元素（类型自动推导为T）。</font> </p>  <p><font face="Consolas" size="2">只有from子句的LINQ Expression是不合法的。一个合法的LINQ Expression必须要有select子句或者group by子句（因为只有这两个子句才造成输出），下面对这两个子句作一简单介绍。</font> </p>  <p><font face="Consolas" size="2">IEnumerable&lt;string&gt; result = from item in list select item.ToString();</font> </p>  <p><font face="Consolas" size="2">这条语句的用途为将list中的每一项（item）调用ToString方法，并将结果集合返回，所以这个LINQ Expression的返回类型就是IEnumerable&lt;string&gt;。select子句可以直接创建匿名对象，不过如果创建匿名对象，就必须用var来代替明确的返回类型。另外，LINQ Expression不是一个可以独立成为语句的表达式，所以下面的代码会是一个编译错误：</font> </p>  <p><font face="Consolas" size="2">from item in list select item.ToString();</font>&#160;</p>  <p>&#160;</p>  <p><font face="Consolas" size="2">group by子句由两个关键字组成，group和by，语法如下：</font> </p>  <p><font face="Consolas" size="2">group item by key</font> </p>  <p><font face="Consolas" size="2">item是需要被包括于分组中的项，而key则是分组依据。group by子句执行的操作是：对于集合中的每一个元素，检索其key的值，key值相同的元素的item组成一个集合，生成一个IGrouping&lt;TKey,TValue&gt;类型的对象。这是一个包含一个key值（IGrouping.Key属性）和一个item集合（IGouping继承于IEnumerable&lt;TValue&gt;）的对象，每一个这样的对象对象表示一个key值的分组。而group by最终的结果为这些分组的集合，即group by操作的最终结果是一个类型为IEnumerable&lt; IGrouping&lt; key的类型, item的类型 &gt; &gt;的对象。</font></p>  <p><font face="Consolas" size="2"></font>&#160;</p>  <p><font face="Consolas" size="2">下面这个表达式用于数据分组（假设data是一个这样的类型：IEnumerable&lt;Data&gt;，而Data{ string Key, int Value }）：</font></p>  <p><font face="Consolas" size="2">var result = from item in data <strong><font color="#008080">group</font></strong> item <strong><font color="#008080">by</font></strong> item.Key</font></p>  <p><font face="Consolas" size="2">但是这个result的结果是IEnumerable&lt;IGrouping&lt;string,Data&gt;&gt;</font></p>  <p><font face="Consolas" size="2"></font>&#160;</p>  <p><font face="Consolas" size="2">如果我们希望对分组后的Value进行求和（Sum），就必须对其再进行一次select：</font></p>  <p><font face="Consolas" size="2">var result2 = from item in result select new { Key = item.Key, Sum = item.<strong><font color="#ff0000">Sum</font></strong>( dataItem =&gt; dataItem.Value ) };</font></p>  <p><font face="Consolas" size="2">//小说明，因为IGrouping&lt;string,Data&gt;继承于IEnumerable&lt;Data&gt;，所以这里的<font color="#ff0000"><strong>Sum</strong></font>方法其实正是Enumerable类中定义的扩展方法IEnumerable&lt;Data&gt;.Sum( Func&lt;Data,int&gt; selector )</font></p>  <p><font face="Consolas" size="2"></font>&#160;</p>  <p><font face="Consolas" size="2">这样的写法非常麻烦，而且也难看，所以C#提供了into关键字来帮助我们改善这种语法：</font></p>  <p><font face="Consolas" size="2">var result = from item in data group item by item.Key <strong><font color="#008080">into</font></strong> groupItem select new { Key = groupItem.Key, Sum = groupItem.Sum( dataItem =&gt; dataItem .Value ) };</font></p>  <p><font face="Consolas" size="2"></font>&#160;</p>  <p><font face="Consolas" size="2">into的语法其实很简单，可以视为把from翻转过来。</font></p>  <p><font face="Consolas" size="2">set into element</font></p>  <p><font face="Consolas" size="2">只不过在这里set是一个LINQ表达式。但实际上from子句中的set也可以是一个表达式，LINQ Expression中绝大多数子句的参数都可以是一个表达式，一般而言只要类型匹配就可以使用。</font></p>  <p>&#160;</p>  <p><font face="Consolas" size="2"></font>&#160;</p>  <p><font face="Consolas" size="2">最后，我们发现其实只有Value属性参与了统计，所以这个表达式还可以简化如下：</font></p>  <p><font face="Consolas" size="2">var result = from item in data <font color="#008080"><strong>group item.Value</strong></font> by item.Key <strong><font color="#008080">into</font></strong> groupItem select new { Key = groupItem.Key, Sum = <strong><font color="#008080">groupItem.Sum()</font></strong> };</font></p>  <p><font face="Consolas" size="2"></font>&#160;</p>  <p><font face="Consolas" size="2">关于orderby和join还有let子句在此略过。</font></p>  <p><font face="Consolas" size="2"></font></p>  <p><font face="Consolas" size="4"><strong>写在后面</strong></font></p>  <p><font face="Consolas" size="2">非常值得注意的一点是LINQ Expression不等于SQL，只是看起来相似的两个东西。不同语言的LINQ Expression也都有自己的特色，C#的LINQ Expression就更类似于函数式，而VB的则更接近于自然语言。不过LINQ Expression与SQL之间还有一个最显著的区别就是他们所查询的目标是不同的，LINQ Expression查询的总的来说还是一个对象集合，而SQL面向的是一个关系。所以在LINQ Expression中，对象是主体，但与之对应的记录（Record，或行Row）在SQL表达式中则几乎无法体现，因为在纯关系中，有序N元组本来就没多少意义。</font><font face="Consolas" size="2">这一点使得LINQ有强大于SQL的地方，也使得LINQ不能实现SQL所有的功能。</font></p>  <p><font face="Consolas" size="2">&#160;</font></p>  <p><font face="Consolas" size="2">现在我们可以来谈谈为什么在本系列第一篇文章为什么要着力于一个晦涩难懂的抽象概念：&#8220;关系&#8221;。这是因为它是LINQ与SQL的唯一联系。LINQ Expression和SQL Expression是完全不同的两个东西，唯一相同的地方就是它们都是描述面向关系的查询的。关系是一个抽象的概念，在.NET Framework中，它被表现为一个强类型的枚举器（IEnumerable&lt;T&gt;），在关系型数据库中，它被表现为一个二维表。</font></p><img src ="http://www.cnblogs.com/Ivony/aggbug/1309807.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47977/" target="_blank">Mono 的Virtual PC 虚拟机</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>好吧，不得不说说这篇在首页恶心人的文章</title><link>http://www.cnblogs.com/Ivony/archive/2008/09/25/1298654.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Thu, 25 Sep 2008 03:56:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2008/09/25/1298654.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1298654.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2008/09/25/1298654.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1298654.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1298654.html</trackback:ping><description><![CDATA[<p>http://www.cnblogs.com/zpino/archive/2008/09/23/1297525.html</p>
<p>首先这篇所谓的原创文章到底有多少是原创的，相信有点儿基础的一眼就能看出来。</p>
<p>瞎吹原创也不说了，放在首页碍眼也罢了，但是把评论都删了还禁止评论，就着实令人恶心了。这是我在首页看到的第一篇禁止评论的文章。<br />
</p><img src ="http://www.cnblogs.com/Ivony/aggbug/1298654.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47970/" target="_blank">19岁天才黑客发布首个iPhone 3GS破解软件</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>C＃关于参数为null（空值）的方法调用，重载顺序选择彻底研究</title><link>http://www.cnblogs.com/Ivony/archive/2008/09/24/1297907.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Wed, 24 Sep 2008 05:43:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2008/09/24/1297907.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1297907.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2008/09/24/1297907.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1297907.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1297907.html</trackback:ping><description><![CDATA[<p>其实这是一个很老的问题了，很久以前就在园子里看到有人对此迷惑，当时也没太在意，觉得哪会有人那么写代码。直到最近丁学君的这篇文章：&#8220;<a href="http://www.cnblogs.com/dingxue/archive/2008/09/24/1297600.html">关于参数为可空值类型的多个重载的优先级</a>&#8221;才让我对这个问题重新有了兴趣。并且做出了一个大胆的猜想，现在这个猜想已经被我验证了。</p> <p>&nbsp;</p> <p>所有具备单向隐式类型转换或者存在继承关系的类型的方法重载，当使用null值调用时，将会使用隐式类型转换的方向来确定调用哪个方法。</p> <p>&nbsp;</p> <p>简而言之，假设TypeA和TypeB之间存在一个隐式类型转换或者继承关系，方向是TypeA对象可以隐式转换为TypeB（TypeA存在一个到TypeB的隐式类型转换或者TypeA派生于TypeB）。</p> <p>又有两个方法的重载如下：</p> <p>public void MyMethod( TypeA obj ){ &#8230; }//重载A</p> <p>public void MyMethod( TypeB obj ){ &#8230; }//重载B</p> <p>&nbsp;</p> <p>那么MyMethod( null )一定会选择重载A。</p> <p>&nbsp;</p> <p>但是这还没完，我仔细测定了各种情况的调用情况，并和装配脑袋一起分析整理了一下，还有如下结论：</p> <p>&nbsp;</p> <p>1、对于Nullable&lt;T&gt;类型而言，T所拥有的运算符（包括隐式类型转换运算符）都会被投射到T?类型。比如说，int有一个隐式类型转换到long，那么int?也就会自动存在一个隐式类型转换到long?。同样的，TypeA?也有一个隐式类型转换到TypeB?（如果TypeA和TypeB是值类型）。这就解释了丁学文章中所说的问题。</p> <p>&nbsp;</p> <p>2、如果两个类型之间存在双向的隐式类型转换，即TypeA可以隐式类型转换为TypeB，而TypeB也可以隐式类型转换为TypeA，这种情况下，使用null值调用会是一个编译错误。推广开来，如果多个类型之间存在一个闭环的隐式类型转换，比如说TypeA-&gt;TypeB，TypeB-&gt;TypeC，TypeC-&gt;TypeA，那么如果这三个类型的重载都存在的话，使用null值调用同样的编译错误，但是如果只有两个类型的重载存在（即方法重载的参数类型不存在闭环）那么也不会有错误。</p> <p>&nbsp;</p> <p>3、数组的协变也会被看作是一个隐式类型转换，比如说TypeA派生于TypeB，则TypeA[]存在一个到TypeB[]的隐式转换，这个被称之为数组的协变。那么这个隐式转换也会被这个规则采信，即如果两个方法的参数是TypeA[]和TypeB[]的话，采用null值调用会选择TypeA[]的重载。</p> <p>&nbsp;</p> <p>4、VB中也采用类似的规则，这一点有待装配脑袋的确认。</p>  <img src ="http://www.cnblogs.com/Ivony/aggbug/1297907.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47969/" target="_blank">新浪邮箱大本营粉墨登场！Sina.cn开放注册</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>今天你LINQ了么？</title><link>http://www.cnblogs.com/Ivony/archive/2008/09/09/1287988.html</link><dc:creator>Ivony...</dc:creator><author>Ivony...</author><pubDate>Tue, 09 Sep 2008 15:07:00 GMT</pubDate><guid>http://www.cnblogs.com/Ivony/archive/2008/09/09/1287988.html</guid><wfw:comment>http://www.cnblogs.com/Ivony/comments/1287988.html</wfw:comment><comments>http://www.cnblogs.com/Ivony/archive/2008/09/09/1287988.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ivony/comments/commentRss/1287988.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ivony/services/trackbacks/1287988.html</trackback:ping><description><![CDATA[摘要: 老实说这个标题的确有点儿哗众取宠，事实上我想在这篇文章里所说的东西，可能与大家所理解的LINQ有所不同。今天你LINQ了么？你是否将LINQ融入了你的思维？你是否运用了LINQ的思维？当然，大家完全可以认为这篇文章是对那个LINQ本质系列的教条文章的一篇辩白。因为我希望用这篇文章的实例来说明为什么LINQ的思想非常重要。好了废话少说，切入正题。最近我正在做一个论坛项目，准确的说是做了N年却一直停留&nbsp;&nbsp;<a href='http://www.cnblogs.com/Ivony/archive/2008/09/09/1287988.html'>阅读全文</a><img src ="http://www.cnblogs.com/Ivony/aggbug/1287988.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47968/" target="_blank">IE市场份额首次跌破60%</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item></channel></rss>