<?xml version="1.0" encoding="GBK"?>
<rss version="2.0" >
<channel> <title><![CDATA[51CTO技术博客-领先的IT技术博客]]></title>
 <link><![CDATA[http://blog.51cto.com]]></link>
 <description><![CDATA[Latest 20 blogs of lihuijun]]></description>
 <copyright><![CDATA[Copyright(C) 51CTO技术博客-领先的IT技术博客]]></copyright>
 <generator><![CDATA[51CTO BLOG by 51CTO Studio]]></generator>
 <lastBuildDate><![CDATA[Wed, 10 Feb 2010 03:59:10 +0000]]></lastBuildDate>
  <image>
 <url><![CDATA[http://img1.51cto.com/image/skin/1/rss.gif]]></url>
 <title><![CDATA[51CTO BLOG]]></title>
 <link><![CDATA[http://blog.51cto.com]]></link>
 <description><![CDATA[51CTO技术博客-领先的IT技术博客]]></description>
  </image>
<item>
 <title><![CDATA[《Silverlight 2完美征程》：书稿目录 ]]></title>
 <description><![CDATA[<h2>内容简介</h2>
<div>本书详细介绍了微软下一代富互联网开发技术Silverlight，分为基础篇、进阶篇、高级篇和案例篇四个部分，共22个章节，以Silverlight 2为主要版本从不同的层面进行了阐释，第一部分介绍Silverlight 中的基础知识、控件模型以及它在绘图方面的能力；第二部分介绍了Silverlight中丰富的网络通信功能、托管代码与浏览器之间的互操作性以及数据绑定等；第三部分对Silverlight应用程序的生命周期进行剖析，并介绍了一些调试技巧；最后一部分开发了Deep Zoom应用程序和图表应用程序两个案例。全书对每个知识点都通过示例进行讲解，一步一步带您进入Silverlight世界。</div>
<div>详情敬请访问《Silverlight 2完美征程》官方网站：<a href="http://www.dotneteye.cn/silverlight"><font color="#ff6600">[url]http://www.dotneteye.cn/silverlight[/url]</font></a></div>
<h2>第一章 进入Silverlight世界</h2>
<div>1.1 Silverlight概述</div>
<div>1.2 创建基本的Silverlight应用</div>
<div>1.3 开发工具简介</div>
<div>1.4 认识XAML</div>
<div>1.5 应用案例</div>
<div>1.6 本章小结</div>
<h2>第二章 基本控件</h2>
<div>2.1 控件模型概述</div>
<div>2.2 命令控件</div>
<div>2.3 文本编辑控件</div>
<div>2.4 选择控件</div>
<div>2.5 列表控件</div>
<div>2.6 日期控件</div>
<div>2.7 信息显示控件</div>
<div>2.8 数据显示控件</div>
<div>2.9 多媒体控件</div>
<div>2.10 布局控件</div>
<div>2.11 本章小结</div>
<h2>第三章 界面布局</h2>
<div>3.1 界面布局概览</div>
<div>3.2 使用Canvas绝对布局</div>
<div>3.3 使用StackPanel局部布局</div>
<div>3.4 使用Grid相对布局</div>
<div>3.5 使用边距</div>
<div>3.6 使用边框控件</div>
<div>3.7自定义布局面板</div>
<div>3.8 全屏支持</div>
<div>3.9 实例开发</div>
<div>3.10本章小结</div>
<h2>第四章 封装控件观感</h2>
<div>4.1 控件观感概览</div>
<div>4.2 使用样式</div>
<div>4.3 使用控件模板</div>
<div>4.4 视觉状态管理</div>
<div>4.5 本章小结</div>
<h2>第五章 事件处理</h2>
<div>5.1 事件概述</div>
<div>5.2 鼠标事件处理</div>
<div>5.3 键盘事件处理</div>
<div>5.4 焦点支持</div>
<div>5.5 实例开发</div>
<div>5.6 本章小结</div>
<h2>第六章 绘图应用</h2>
<div>6.1 绘图概览</div>
<div>6.2 直线Line </div>
<div>6.3 矩形Rectangle </div>
<div>6.4 椭圆形Ellipse </div>
<div>6.5 多边形Polygon </div>
<div>6.6 多线形Polyline </div>
<div>6.7 路径Path </div>
<div>6.8 实例开发</div>
<div>6.9 本章小结</div>
<h2>第七章 画刷应用</h2>
<div>7.1 画刷简介</div>
<div>7.2 单色实心画刷SolidColorBrush</div>
<div>7.3 线性渐变画刷LinearGradientBrush</div>
<div>7.4 放射性渐变画刷RadialGradientBrush</div>
<div>7.5 图像画刷ImageBrush</div>
<div>7.6 视频画刷VideoBrush</div>
<div>7.7 实例开发</div>
<div>7.8 本章小结</div>
<h2>第八章 图像处理</h2>
<div>8.1 图像处理简介</div>
<div>8.2 创建图像</div>
<div>8.3 图像拉伸</div>
<div>8.4 图像裁剪</div>
<div>8.5 半透明遮罩</div>
<div>8.6 实例开发</div>
<div>8.7 本章小结</div>
<h2>第九章几何图形</h2>
<div>9.1 几何图形介绍</div>
<div>9.2 几何图形的使用</div>
<div>9.3 简单几何图形</div>
<div>9.4 复杂几何图形</div>
<div>9.5 组合几何图形</div>
<div>9.6 本章小结</div>
<h2>第十章 变形效果应用</h2>
<div>10.1 变换对象简介</div>
<div>10.2 RotateTransform旋转变换</div>
<div>10.3 ScaleTransform缩放变换</div>
<div>10.4 SkewTransform倾斜变换</div>
<div>10.5 TranslateTransform移动变换</div>
<div>10.6 TransformGroup变换组</div>
<div>10.7 MatrixTransform矩阵变换</div>
<div>10.8 实现动画变换</div>
<div>10.9 动态添加变换</div>
<div>10.10 实例开发</div>
<div>10.11 本章小结</div>
<h2>第十一章 数据绑定</h2>
<div>11.1 数据绑定简介</div>
<div>11.2 绑定数据对象</div>
<div>11.3 数据绑定模式</div>
<div>11.4 绑定对象集合</div>
<div>11.5 构建数据服务</div>
<div>11.6 使用数据模板</div>
<div>11.7 DataGrid控件</div>
<div>11.8 数据转换</div>
<div>11.9 数据验证</div>
<div>11.10 实例开发</div>
<div>11.11 本章小结</div>
<h2>第十二章 网络与通信</h2>
<div>12.1 数据与通信概述</div>
<div>12.2 调用Web Service</div>
<div>12.3 调用WCF服务</div>
<div>12.4 使用WebClient通信</div>
<div>12.5 访问RESTful服务</div>
<div>12.6 使用HttpWebRequest通信</div>
<div>12.7 数据操作格式</div>
<div>12.8 访问ADO.NET Data Service</div>
<div>12.9 跨域通信策略</div>
<div>12.10 本章小结</div>
<h2>第十三章 与浏览器交互</h2>
<div>13.1 浏览器交互简介</div>
<div>13.2 访问文档对象模型</div>
<div>13.3 使用托管代码调用JavaScript</div>
<div>13.4 使用JavaScript调用托管代码</div>
<div>13.5 使用托管代码处理DOM元素事件</div>
<div>13.6 使用JavaScript处理托管事件</div>
<div>13.7 混合HTML和Silverlight</div>
<div>13.8 与浏览器交互相关辅助方法</div>
<div>13.9 安全设置</div>
<div>13.10 实例开发</div>
<div>13.11 本章小结</div>
<h2>第十四章 影音播放</h2>
<div>14.1 影音播放概述</div>
<div>14.2 MediaElement对象</div>
<div>14.3 媒体状态控制</div>
<div>14.4 VideoBrush和MediaElement</div>
<div>14.5 本章小结</div>
<h2>第十五章 制作动画</h2>
<div>15.1 动画概述</div>
<div>15.2 时间线</div>
<div>15.3 故事板</div>
<div>15.4 From/To/By动画</div>
<div>15.5 关键帧动画</div>
<div>15.6 编程方式控制动画</div>
<div>15.7 实例开发</div>
<div>15.8 本章小结</div>
<h2>第十六章 自定义控件</h2>
<div>16.1 控件模型</div>
<div>16.2 自定义简单按钮控件</div>
<div>16.3 本章小结</div>
<h2>第十七章 独立存储</h2>
<div>17.1 独立存储概述</div>
<div>17.2 使用独立存储</div>
<div>17.3 管理存储空间</div>
<div>17.4 读写应用程序配置</div>
<div>17.5 进一步认识独立存储</div>
<div>17.6 本章小结</div>
<h2>第十八章 墨迹标注使用</h2>
<div>18.1 InkPresenter控件使用</div>
<div>18.2 收集显示数据</div>
<div>18.3 笔画设计</div>
<div>18.4 美化InkPresenter</div>
<div>18.5 标注存储</div>
<div>18.6 本章小结</div>
<h2>第十九章 应用程序剖析</h2>
<div>19.1 应用程序概述</div>
<div>19.2 应用程序生命周期</div>
<div>19.3 应用程序宿主</div>
<div>19.4 应用程序包揭秘</div>
<div>19.5 应用程序部署</div>
<div>19.6 本章小结</div>
<h2>第二十章 异常处理与调试</h2>
<div>20.1 异常处理</div>
<div>20.2 使用Visual Studio基本调试</div>
<div>20.3 使用Windbg高级调试</div>
<div>20.4 本章小结</div>
<h2>第二十一章 开发Deep Zoom应用程序</h2>
<div>21.1 Deep Zoom概述</div>
<div>21.2 Deep Zoom示例</div>
<div>21.3 本章小结</div>
<h2>第二十二章 开发图表应用程序</h2>
<div>22.1 Silverlight Toolkit概述</div>
<div>22.2 开发图表示例</div>
<div>22.3 本章小结</div>
<div>详情敬请访问《Silverlight 2完美征程》官方网站：<a href="http://www.dotneteye.cn/silverlight"><font color="#ff6600">[url]http://www.dotneteye.cn/silverlight[/url]</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/152858]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[.Net]]></category>
 <pubdate><![CDATA[Fri, 24 Apr 2009 11:26:07 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[技巧：使用可扩展对象模式扩展HttpApplication ]]></title>
 <description><![CDATA[接口：IExtensibleObject、IExtension和IExtensionCollection，这是可扩展对象模式中最重要的三个接口，也只有这三个接口。
<div>IExtensibleObject自然是定义了可扩展对象，即我们要对谁进行扩展，它的定义非常简单，仅仅是提供了一个只读的属性Extensions，用来提供所有扩展对象的集合，如下代码所示：</div><pre class=code><span style="color: blue">public interface </span><span style="color: #2b91af">IExtensibleObject</span>&lt;T&gt; <span style="color: blue">where </span>T : <span style="color: #2b91af">IExtensibleObject</span>&lt;T&gt;
{
    <span style="color: #2b91af">IExtensionCollection</span>&lt;T&gt; Extensions { <span style="color: blue">get</span>; }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>IExtension定义了扩展对象的契约，使对象可以通过聚合扩展另一个对象（此处的另一个对象，就是指上面所讲的扩展宿主IExtensibleObject），在IExtension中定义了两个非常重要的方法Attach和Detach方法，分别用来提供聚合或解聚的通知。</div><pre class=code><span style="color: blue">public interface </span><span style="color: #2b91af">IExtension</span>&lt;T&gt; <span style="color: blue">where </span>T : <span style="color: #2b91af">IExtensibleObject</span>&lt;T&gt;
{
    <span style="color: blue">void </span>Attach(T owner);
    <span style="color: blue">void </span>Detach(T owner);
}</pre>
<div>当一个扩展对象IExtension附加到可扩展对象的扩展集合中时，它的Attach方法将会被调用；反之如果从集合中移除一个扩展对象时，它的Detach方法会被调用。这一点我们可以通过Reflector来得到验证，如下代码所示：</div><pre class=code><span style="color: blue">protected override void </span>InsertItem(<span style="color: blue">int </span>index, IExtension&lt;T&gt; item)
{
    <span style="color: blue">lock </span>(<span style="color: blue">base</span>.SyncRoot)
    {
        item.Attach(<span style="color: blue">this</span>.owner);
        <span style="color: blue">base</span>.InsertItem(index, item);
    }
}
<span style="color: blue">protected override void </span>RemoveItem(<span style="color: blue">int </span>index)
{
    <span style="color: blue">lock </span>(<span style="color: blue">base</span>.SyncRoot)
    {
        <span style="color: blue">base</span>.Items[index].Detach(<span style="color: blue">this</span>.owner);
        <span style="color: blue">base</span>.RemoveItem(index);
    }
}</pre>
<div>最后一个接口是IExtensionCollection，它是IExtension对象的集合。</div>
<h2>对HttpApplication进行扩展</h2>
<div>下面我们就看一下如何使用可扩展对象模式对HttpApplication进行扩展，首先定义可扩展对象，让ExtensibleHttpApplication派生于HttpApplication，并实现了IExtensibleObject接口，泛型的参数类型就是它自身，如下代码所示：</div><pre class=code><span style="color: blue">public class </span><span style="color: #2b91af">ExtensibleHttpApplication </span>: <span style="color: #2b91af">HttpApplication</span>,
    <span style="color: #2b91af">IExtensibleObject</span>&lt;<span style="color: #2b91af">ExtensibleHttpApplication</span>&gt;
{
    <span style="color: blue">private </span><span style="color: #2b91af">IExtensionCollection</span>&lt;<span style="color: #2b91af">ExtensibleHttpApplication</span>&gt; _extensions;
    
    <span style="color: blue">public </span>ExtensibleHttpApplication()
    {
        <span style="color: blue">this</span>._extensions = <span style="color: blue">new </span><span style="color: #2b91af">ExtensionCollection</span>&lt;<span style="color: #2b91af">ExtensibleHttpApplication</span>&gt;(<span style="color: blue">this</span>);
    }
    <span style="color: blue">public </span><span style="color: #2b91af">IExtensionCollection</span>&lt;<span style="color: #2b91af">ExtensibleHttpApplication</span>&gt; Extensions
    {
        <span style="color: blue">get
        </span>{
            <span style="color: blue">return this</span>._extensions;
        }
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>有了可扩展的HttpApplication之后，需要在HttpApplication中实现任何功能，都可以作为一个扩展附加到ExtensibleHttpApplication上去，如实现ASP.NET MVC路由，可以定义一个如下代码所示的扩展对象：</div><pre class=code><span style="color: blue">public class </span><span style="color: #2b91af">MvcHttpApplication </span>: <span style="color: #2b91af">IExtension</span>&lt;<span style="color: #2b91af">ExtensibleHttpApplication</span>&gt;
{
    <span style="color: blue">public void </span>Attach(<span style="color: #2b91af">ExtensibleHttpApplication </span>owner)
    {
        <span style="color: #2b91af">RouteTable</span>.Routes.IgnoreRoute(<span style="color: #a31515">"{resource}.axd/{*pathInfo}"</span>);
        <span style="color: #2b91af">RouteTable</span>.Routes.MapRoute(
            <span style="color: #a31515">"Default"</span>,                                              <span style="color: green">// Route name
            </span><span style="color: #a31515">"{controller}/{action}/{id}"</span>,                           <span style="color: green">// URL with parameters
            </span><span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Home"</span>, action = <span style="color: #a31515">"Index"</span>, id = <span style="color: #a31515">"" </span>}  <span style="color: green">// Parameter defaults
        </span>);
    }
    <span style="color: blue">public void </span>Detach(<span style="color: #2b91af">ExtensibleHttpApplication </span>owner)
    {
        <span style="color: green">//nothing
    </span>}
}</pre>
<div><a href="http://11011.net/software/vspaste"></a>同样如果要在HttpApplication中启动Workflow，可以再针对Workflow定义一个扩展对象，如下示例代码所示：</div><pre class=code><span style="color: blue">public class </span><span style="color: #2b91af">WorkflowHttpApplication </span>: <span style="color: #2b91af">IExtension</span>&lt;<span style="color: #2b91af">ExtensibleHttpApplication</span>&gt;
{
    <span style="color: blue">private </span><span style="color: #2b91af">WorkflowRuntime </span>workflowRuntime;
    <span style="color: blue">public void </span>Attach(<span style="color: #2b91af">ExtensibleHttpApplication </span>owner)
    {
        workflowRuntime = <span style="color: blue">new </span><span style="color: #2b91af">WorkflowRuntime</span>(<span style="color: #a31515">"workflowServicesConfig"</span>);
        <span style="color: #2b91af">ExternalDataExchangeService </span>externalDataExchangeService = <span style="color: blue">new </span><span style="color: #2b91af">ExternalDataExchangeService</span>();
        workflowRuntime.AddService(externalDataExchangeService);
        workflowRuntime.StartRuntime();
    }
    <span style="color: blue">public void </span>Detach(<span style="color: #2b91af">ExtensibleHttpApplication </span>owner)
    {
        workflowRuntime.StopRuntime();
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>我们已经定义好了相应的扩展对象，只需要在相应的HttpApplication把扩展对象附加到ExtensibleHttpApplication上即可，修改Global.asax中的代码如下所示：</div><pre class=code><span style="color: blue">public class </span><span style="color: #2b91af">MvcApplication </span>: <span style="color: #2b91af">ExtensibleHttpApplication
</span>{
    <span style="color: blue">protected void </span>Application_Start()
    {
        <span style="color: blue">this</span>.Extensions.Add(<span style="color: blue">new </span><span style="color: #2b91af">MvcHttpApplication</span>());
        <span style="color: blue">this</span>.Extensions.Add(<span style="color: blue">new </span><span style="color: #2b91af">WorkflowHttpApplication</span>());
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>现在代码是不是看起来优雅多了？现在如果要在Application_Start中，添加另外一些执行代码，只需要编写相应的扩展对象，并将其添加到Extension集合中即可。也许有朋友会问，这样每添加一些新的代码，还是要修改Application_Start中的代码啊？别忘了，可以通过配置可以解决这个问题，WCF中的扩展不也是可以采用配置方式实现，不是吗？同样，如果我们需要在Application_End事件中释放某些对象，可以直接从扩展集合中移除它，此时将会调用它的Detach方法。</div>
<h2>总结</h2>
<div>本文介绍了如何使用WCF中提供的可扩展对象模式扩展HttpApplication，事实上可扩展对象模式的作用远不在此，它可以扩展.NET类库中任何我们想对其进行扩展的对象，或者是一个自定义的类型，都可以使用可扩展对象模式对其进行扩展。</div>
<div>特别鸣谢：<a href="http://www.cnblogs.com/jessequ"><font color="#ff6600">Jesse Qu</font></a></div>
<div>注1：由于TerryLee最近一段时间忙于别的事务，无暇顾及Blog，所以有大量的评论和E-mail都没能回复，请大家见谅。</div>
<div>注2：由TerryLee撰写的《Silverlight 2完美征程》一书，即将于本月底上市，敬请期待，详情大家可以访问本书官方网站<a href="http://www.dotneteye.cn/silverlight"><font color="#ff6600">[url]http://www.dotneteye.cn/silverlight[/url]</font></a>了解。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151985]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[.Net]]></category>
 <pubdate><![CDATA[Mon, 20 Apr 2009 02:28:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[不得不为LINQ说几句话，驳“LINQ已死”论 ]]></title>
 <description><![CDATA[<h2>起因</h2>
<div>近日不断看到有关“LINQ已死”，“LINQ玩完了吧”的言论，甚至于更有牛人说出“程序开发最终会回到本机代码上”，暂不说这些言论是否正确，且先来看看各位的惊人言论，下面仅摘录部分：</div>
<div><strong>言论1</strong></div>
<div class=code>
<div>我看园子里还有蛮多人学习和用Linq to SQL 还写了一系列文章 <br />哎~~ 程序员的悲哀呢 <br />被他们牵着鼻子走</div></div>
<div><strong>言论2</strong></div>
<div class=code>
<div>玩LINQ的人傻了吧</div></div>
<div><strong>言论3</strong></div>
<div class=code>
<div>又是一次证明跟着微软是浪费青春的,小心C#喔,各位, <br />我发现程序开发最终会回到本机代码上来,而不是托管的</div></div>
<div><strong>言论4</strong></div>
<div class=code>
<div>Linq 是 Anders 最失败的一个作品， 看来当年的牛人真的老了。 <br />linq将程序的复杂性提高了一个数量级，强迫程序员在两个语法体系间跳跃，却本质性提高开发效率 <br />linq is dead!</div></div>
<div><strong>言论5</strong></div>
<div class=code>
<div>废弃了好 这样的垃圾不该存活，搞得程序员劳命伤财的学习！ <br />垃圾啊！ <br />幸亏我拒绝LINQ</div></div>
<div>以上言论，我仅摘取了部分，其实通过这些，我只想说几个问题：</div>
<h2>请认清事实真相</h2>
<div>首先根本没有“LINQ已死”的说法，也没有“LINQ to SQL已死”的说法，关于“LINQ已死”的言论完全来自于社区，而起因则是ADO.NET团队的一篇《<a href="http://blogs.msdn.com/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx"><font color="#ff6600">Update on LINQ to SQL and LINQ to Entities Roadmap</font></a>》，文章最后说到</div>
<div class=code>
<div>作为.NET 4.0的一部分，实体框架是我们推荐的在关系场景中针对LINQ的数据访问解决方案，我们聆听了客户关于LINQ to SQL的反馈，并将整合在社区收到的反馈，继续开发和改善该产品。</div></div>
<div>于是社区中就猜测微软将会放弃LINQ to SQL，请注意，ADO.NET团队只是说推荐使用ADO.NET Entity Framework，将会加大对它的投入，而并没有没有什么“废弃”言论，“已死”更无从谈起！退一步讲，就算微软不再开发LINQ to SQL，这跟LINQ又有何关系呢？LINQ to SQL只是LINQ家族中众多Providers中的一个而已，没了LINQ to SQL，不是还有LINQ to Object、LINQ to XML、LINQ to Entities的吗？况且LINQ to SQL还没死，它也不会死，作为一个轻量级的ORM框架，LINQ to SQL在中小项目以及快速开发中的优势还是非常明显的，这一点，如果你没有用过LINQ to SQL，就不要再说它是多么多么的垃圾！</div>
<div>投入小不等于放弃，就算微软不再开发LINQ to SQL，LINQ to SQL现在的功能已经能够大部分开发的需要，再加上它灵活的可扩展性，完全可以通过自定义一些扩展来满足自己开发的需要。</div>
<div>再强调一遍：请停止“LINQ已死”或者“LINQ to SQL已死”的荒谬言论吧！</div>
<h2>请区分清概念</h2>
<div>作为“专业的开发人员”，请在了解了某个技术之后，再对其发表见解吧，最起码你得知道这个技术是怎么回事吧？如别人说“LINQ to SQL已死”，然后就有人跟着说“幸好我没用LINQ”，这又关LINQ啥事了。博客园老赵曾经在6月份写过一篇文章《<a href="http://www.cnblogs.com/JeffreyZhao/archive/2008/06/04/ajax-linq-lambda-expression.html"><font color="#ff6600">觉得有必要来澄清几组重要概念</font></a>》，其中介绍了LINQ以及LINQ to SQL的区别，但是很遗憾，社区中不能正确区分LINQ和LINQ to SQL的朋友太多了，看到这些言论，让我们为老赵这篇文章默哀一分钟吧。</div>
<div>再强调一遍：LINQ to SQL只是LINQ家族中众多Providers中的一个而已，这是真的，请不要怀疑，不要把LINQ等同于LINQ to SQL，如果觉的LINQ to SQL字母太多了，可以使用L2S来代替，但请不要使用LINQ来代替LINQ to SQL。</div>
<h2>请收起LINQ无用论</h2>
<div>“LINQ很垃圾”，“拒绝LINQ”，看到这些，真的有些悲哀，LINQ仅仅是一个语言特性，它能够让我们在编写代码时使用内置的查询语法对于数据集合进行操作，提高我们的开发效率，仅此而已。当然如果你的数据集合来源不同，会对应不同的Providers。既然拒绝LINQ，为何不干脆连泛型、数组以及.NET Framework中内置的基础类库等等一起拒绝，甚至于拒绝C#语言，而回到所谓的“本机代码”上去呢，直接编写二进制的“01101100”程序是不是比C#语言更方便，更快速？如果是，请原谅，我错了，我道歉。</div>
<div>再强调一遍：LINQ仅仅是一个语言特性而已，请收起LINQ无用论。</div>
<h2>后记</h2>
<div>写下本篇文章，其实不是想针对某个人，只是看到大家都在误解LINQ，甚至有些初学者因为看到“LINQ已死”的谬论，都不敢去学习，去使用了。所以忍不住站出来说几句话，如有得罪您的地方，请见谅！</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151982]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Mon, 05 Jan 2009 01:31:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[2008年第四季度开发者Top 100 Blogs]]></title>
 <description><![CDATA[<div>在10月份<a href="http://www.cnblogs.com/anytao/archive/2008/10/14/recommand_top100_blogs.html"><font color="#ff6600">Anytao同学推荐</font></a>了<a href="http://nooperation.typepad.com/about.html"><font color="#ff6600">Jurgen Appelo</font></a>整理的Top 100 Blogs 第三季度版本，现在<a href="http://nooperation.typepad.com/about.html"><font color="#ff6600">Jurgen Appelo</font></a>又整理出了第四季度开发者的Top 100 Blogs，其中有些Blogger的排名发生了变化，退出了前100名，而又很多新的Blogger当选，再次推荐给大家。</div>
<table cellspacing="0" cellpadding="2" border="0">
<tbody>
<tr style="height: 12.75pt" height="17">
<td align="middle" width="100"><strong>TT</strong></td>
<td align="middle" width="100"><strong>LT</strong></td>
<td><strong>Blog</strong></td>
<td><strong>Author</strong></td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>1</strong></td>
<td align="middle">1</td>
<td><a href="http://www.joelonsoftware.com/"><font color="#ff6600">Joel on Software</font></a></td>
<td>Joel Spolsky</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>2</strong></td>
<td align="middle">4</td>
<td><a href="http://www.paulgraham.com/"><font color="#ff6600">Paul Graham: Essays</font></a></td>
<td>Paul Graham</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>3</strong></td>
<td align="middle">2</td>
<td><a href="http://www.codinghorror.com/"><font color="#ff6600">Coding Horror</font></a></td>
<td>Jeff Atwood</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>4</strong></td>
<td align="middle">6</td>
<td><a href="http://www.roughtype.com/"><font color="#ff6600">Rough Type</font></a></td>
<td>Nicholas Carr</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>5</strong></td>
<td align="middle">7</td>
<td><a href="http://www.hanselman.com/blog/"><font color="#ff6600">Scott Hanselman's Computer Zen</font></a></td>
<td>Scott Hanselman</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>6</strong></td>
<td align="middle">8</td>
<td><a href="http://martinfowler.com/bliki/"><font color="#ff6600">Martin Fowler's Bliki</font></a></td>
<td>Martin Fowler</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>7</strong></td>
<td align="middle">11</td>
<td><a href="http://bokardo.com/"><font color="#ff6600">Bokardo: Social Design</font></a></td>
<td>Joshua Porter</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>8</strong></td>
<td align="middle">10</td>
<td><a href="http://steve-yegge.blogspot.com/"><font color="#ff6600">Stevey's Blog Rants</font></a></td>
<td>Steve Yegge</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>9</strong></td>
<td align="middle">13</td>
<td><a href="http://lambda-the-ultimate.org/"><font color="#ff6600">Lambda the Ultimate</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>10</strong></td>
<td align="middle">9</td>
<td><a href="http://www.randsinrepose.com/"><font color="#ff6600">Rands in Repose</font></a></td>
<td>Michael Lopp</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>11</strong></td>
<td align="middle">--</td>
<td><a href="http://thedailywtf.com/"><font color="#ff6600">The Daily WTF</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>12</strong></td>
<td align="middle">12</td>
<td><a href="http://www.ericsink.com/"><font color="#ff6600">Eric.Weblog()</font></a></td>
<td>Eric Sink</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>13</strong></td>
<td align="middle">--</td>
<td><a href="http://raibledesigns.com/"><font color="#ff6600">Raible Designs</font></a></td>
<td>Matt Raible</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>14</strong></td>
<td align="middle">--</td>
<td><a href="http://www.25hoursaday.com/weblog/"><font color="#ff6600">Dare Obasanjo aka Carnage4Life</font></a></td>
<td>Dare Obasanjo</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>15</strong></td>
<td align="middle">18</td>
<td><a href="http://www.uie.com/brainsparks/"><font color="#ff6600">UIE Brain Sparks</font></a></td>
<td>Jared Spool</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>16</strong></td>
<td align="middle">15</td>
<td><a href="http://pragdave.pragprog.com/"><font color="#ff6600">PragDave</font></a></td>
<td>Dave Thomas</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>17</strong></td>
<td align="middle">--</td>
<td><a href="http://blog.jonudell.net/"><font color="#ff6600">Jon Udell</font></a></td>
<td>Jon Udell</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>18</strong></td>
<td align="middle">17</td>
<td><a href="http://www.scottberkun.com/blog/"><font color="#ff6600">The Berkun Blog</font></a></td>
<td>Scott Berkun</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>19</strong></td>
<td align="middle">21</td>
<td><a href="http://blog.stackoverflow.com/"><font color="#ff6600">Stack Overflow</font></a></td>
<td>Jeff Atwood</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>20</strong></td>
<td align="middle">34</td>
<td><a href="http://www.artima.com/weblogs/"><font color="#ff6600">Artima Weblogs</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>21</strong></td>
<td align="middle">14</td>
<td><a href="http://beust.com/weblog/"><font color="#ff6600">Otaku, Cedric's Weblog</font></a></td>
<td>Cedric</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>22</strong></td>
<td align="middle">20</td>
<td><a href="http://blogs.msdn.com/jmeier/"><font color="#ff6600">J.D. Meier's Blog</font></a></td>
<td>J.D. Meier</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>23</strong></td>
<td align="middle">--</td>
<td><a href="http://blogs.thoughtworks.com/"><font color="#ff6600">ThoughtBlogs</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>24</strong></td>
<td align="middle">--</td>
<td><a href="http://www.shahine.com/omar/"><font color="#ff6600">Shanine.com / omar /</font></a></td>
<td>Omar Shanine</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>25</strong></td>
<td align="middle">16</td>
<td><a href="http://highscalability.com/"><font color="#ff6600">High Scalability</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>26</strong></td>
<td align="middle">77</td>
<td><a href="http://forums.construx.com/blogs/stevemcc/default.aspx"><font color="#ff6600">10x Software Development</font></a></td>
<td>Steve McConnell</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>27</strong></td>
<td align="middle">24</td>
<td><a href="http://codebetter.com/"><font color="#ff6600">CodeBetter.Com</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>28</strong></td>
<td align="middle">28</td>
<td><a href="http://blog.objectmentor.com/"><font color="#ff6600">Object Mentor Blog</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>29</strong></td>
<td align="middle">23</td>
<td><a href="http://secretgeek.net/"><font color="#ff6600">secretGeek</font></a></td>
<td>Leon Bambrick</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>30</strong></td>
<td align="middle">37</td>
<td><a href="http://dobbscodetalk.com/"><font color="#ff6600">Dr. Dobb's CodeTalk</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>31</strong></td>
<td align="middle">--</td>
<td><a href="http://phpimpact.wordpress.com/"><font color="#ff6600">PHP::Impact ( [str Blog] )</font></a></td>
<td>Federico Cargnelutti</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>32</strong></td>
<td align="middle">41</td>
<td><a href="http://management.curiouscatblog.net/"><font color="#ff6600">Curious Cat</font></a></td>
<td>John Hunter</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>33</strong></td>
<td align="middle">31</td>
<td><a href="http://googletesting.blogspot.com/"><font color="#ff6600">Google Testing Blog</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>34</strong></td>
<td align="middle">--</td>
<td><a href="http://duckdown.blogspot.com/"><font color="#ff6600">Enterprise Architecture: From Incite comes Insight...</font></a></td>
<td>James McGovern</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>35</strong></td>
<td align="middle">26</td>
<td><a href="http://graysmatter.codivation.com/"><font color="#ff6600">Gray's Matter</font></a></td>
<td>Justice Gray</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>36</strong></td>
<td align="middle">32</td>
<td><a href="http://alistair.cockburn.us/Blog"><font color="#ff6600">Alistair Cockburn</font></a></td>
<td>Alistair Cockburn</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>37</strong></td>
<td align="middle">65</td>
<td><a href="http://www.noop.nl/"><font color="#ff6600">NOOP.NL: Managing Software Development</font></a></td>
<td>Jurgen Appelo</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>38</strong></td>
<td align="middle">--</td>
<td><a href="http://www.catonmat.net/"><font color="#ff6600">Good coders code, great reuse</font></a></td>
<td>Peteris Krumins</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>39</strong></td>
<td align="middle">30</td>
<td><a href="http://jrothman.com/blog/mpd/"><font color="#ff6600">Managing Product Development</font></a></td>
<td>Johanna Rothman</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>40</strong></td>
<td align="middle">35</td>
<td><a href="http://stuffthathappens.com/blog/"><font color="#ff6600">It's Just a Bunch of Stuff That Happens</font></a></td>
<td>Eric Burke</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>41</strong></td>
<td align="middle">--</td>
<td><a href="http://regulargeek.com/"><font color="#ff6600">Regular Geek</font></a></td>
<td>Rob Diana</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>42</strong></td>
<td align="middle">46</td>
<td><a href="http://jeffsutherland.com/"><font color="#ff6600">Object Technology</font></a></td>
<td>Jeff Sutherland</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>43</strong></td>
<td align="middle">57</td>
<td><a href="http://blog.softwareprojects.org/"><font color="#ff6600">Project Shrink</font></a></td>
<td>Bas de Baar</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>44</strong></td>
<td align="middle">25</td>
<td><a href="http://blogs.tedneward.com/"><font color="#ff6600">Interoperability Happens</font></a></td>
<td>Ted Neward</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>45</strong></td>
<td align="middle">--</td>
<td><a href="http://stevenharman.net/blog/"><font color="#ff6600">StevenHarman.net</font></a></td>
<td>Steven Harman</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>46</strong></td>
<td align="middle">45</td>
<td><a href="http://jamesshore.com/Blog/"><font color="#ff6600">James Shore: The Art of Agile</font></a></td>
<td>James Shore</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>47</strong></td>
<td align="middle">27</td>
<td><a href="http://blog.mountaingoatsoftware.com/"><font color="#ff6600">Mike Cohn's Blog: Succeeding with Agile</font></a></td>
<td>Mike Cohn</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>48</strong></td>
<td align="middle">52</td>
<td><a href="http://tech.puredanger.com/"><font color="#ff6600">Pure Danger Tech</font></a></td>
<td>Alex Miller</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>49</strong></td>
<td align="middle">--</td>
<td><a href="http://www.reformingprojectmanagement.com/"><font color="#ff6600">Reforming Project Management</font></a></td>
<td>Hal Macomber</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>50</strong></td>
<td align="middle">47</td>
<td><a href="http://www.betterprojects.net/"><font color="#ff6600">Better Projects</font></a></td>
<td>Craig Brown</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>51</strong></td>
<td align="middle">39</td>
<td><a href="http://www.codesqueeze.com/"><font color="#ff6600">{Codesqueeze}</font></a></td>
<td>Max Pool</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>52</strong></td>
<td align="middle">43</td>
<td><a href="http://www.agilemanagement.net/Articles/Weblog/blog.html"><font color="#ff6600">Agile Management Blog</font></a></td>
<td>David Anderson</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>53</strong></td>
<td align="middle">55</td>
<td><a href="http://blogs.msdn.com/micahel/"><font color="#ff6600">The Braidy Tester</font></a></td>
<td>Micahel</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>54</strong></td>
<td align="middle">36</td>
<td><a href="http://onestepback.org/"><font color="#ff6600">{ |one, step, back| }</font></a></td>
<td>Jim Weirich</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>55</strong></td>
<td align="middle">74</td>
<td><a href="http://www.implementingscrum.com/"><font color="#ff6600">Implementing Scrum</font></a></td>
<td>Mike Vizdos</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>56</strong></td>
<td align="middle">33</td>
<td><a href="http://tynerblain.com/blog/"><font color="#ff6600">Tyner Blain</font></a></td>
<td>Scott Sehlhorst</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>57</strong></td>
<td align="middle">--</td>
<td><a href="http://agiletesting.blogspot.com/"><font color="#ff6600">Agile Testing</font></a></td>
<td>Grig Gheorghiu</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>58</strong></td>
<td align="middle">--</td>
<td><a href="http://www.codingthearchitecture.com/"><font color="#ff6600">Coding the Architecture</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>59</strong></td>
<td align="middle">42</td>
<td><a href="http://www.knowing.net/"><font color="#ff6600">Knowing.NET</font></a></td>
<td>Larry O'Brien</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>60</strong></td>
<td align="middle">38</td>
<td><a href="http://www.charlespetzold.com/blog/blog.xml"><font color="#ff6600">Petzold Book Blog</font></a></td>
<td>Charles Petzold</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>61</strong></td>
<td align="middle">29</td>
<td><a href="http://www.satisfice.com/blog/"><font color="#ff6600">James Bach’s Blog</font></a></td>
<td>James Bach</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>62</strong></td>
<td align="middle">73</td>
<td><a href="http://pyre.third-bit.com/blog/"><font color="#ff6600">The Third Bit</font></a></td>
<td>Esan</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>63</strong></td>
<td align="middle">59</td>
<td><a href="http://www.agileadvice.com/"><font color="#ff6600">Agile Advice</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>64</strong></td>
<td align="middle">53</td>
<td><a href="http://elegantcode.com/"><font color="#ff6600">Elegant Code</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>65</strong></td>
<td align="middle">48</td>
<td><a href="http://ourfounder.typepad.com/"><font color="#ff6600">Evolving Web</font></a></td>
<td>Jim Benson</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>66</strong></td>
<td align="middle">--</td>
<td><a href="http://www.softwarebyrob.com/"><font color="#ff6600">Software by Rob</font></a></td>
<td>Rob Walling</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>67</strong></td>
<td align="middle">40</td>
<td><a href="http://blogcabin.37signals.com/"><font color="#ff6600">Signal vs. Noise</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>68</strong></td>
<td align="middle">44</td>
<td><a href="http://blog.toolshed.com/"><font color="#ff6600">/\ndy</font></a></td>
<td>Andy Hunt</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>69</strong></td>
<td align="middle">81</td>
<td><a href="http://www.agile-software-development.com/"><font color="#ff6600">All About Agile</font></a></td>
<td>Kelly Waters</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>70</strong></td>
<td align="middle">--</td>
<td><a href="http://crazeegeekchick.com/"><font color="#ff6600">Crazeegeekchick.com</font></a></td>
<td>Dana Coffey</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>71</strong></td>
<td align="middle">49</td>
<td><a href="http://memeagora.blogspot.com/"><font color="#ff6600">Meme Agora</font></a></td>
<td>Neal Ford</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>72</strong></td>
<td align="middle">70</td>
<td><a href="http://herdingcats.typepad.com/"><font color="#ff6600">Herding Cats</font></a></td>
<td>Glen Alleman</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>73</strong></td>
<td align="middle">--</td>
<td><a href="http://www.codeodor.com/"><font color="#ff6600">My Secret Life as a Spaghetti Coder</font></a></td>
<td>Sammy Larbi</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>74</strong></td>
<td align="middle">--</td>
<td><a href="http://jeffreypalermo.com/"><font color="#ff6600">Jeffrey Palermo (.com)</font></a></td>
<td>Jeffrey Palermo</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>75</strong></td>
<td align="middle">68</td>
<td><a href="http://leansoftwareengineering.com/"><font color="#ff6600">Lean Software Engineering</font></a></td>
<td>Corey Ladas</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>76</strong></td>
<td align="middle">50</td>
<td><a href="http://www.ibm.com/developerworks/blogs/page/ambler"><font color="#ff6600">Agility@Scale</font></a></td>
<td>Scott W. Ambler</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>77</strong></td>
<td align="middle">87</td>
<td><a href="http://agilesoftwaredevelopment.com/"><font color="#ff6600">Agile Software Development</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>78</strong></td>
<td align="middle">--</td>
<td><a href="http://debasishg.blogspot.com/"><font color="#ff6600">Ruminations of a Programmer</font></a></td>
<td>Debasish Ghosh</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>79</strong></td>
<td align="middle">51</td>
<td><a href="http://blog.davidchelimsky.net/"><font color="#ff6600">David Chelimsky</font></a></td>
<td>David Chelimsky</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>80</strong></td>
<td align="middle">--</td>
<td><a href="http://www.pmthink.com/"><font color="#ff6600">PMThink!</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>81</strong></td>
<td align="middle">60</td>
<td><a href="http://leadinganswers.typepad.com/"><font color="#ff6600">LeadingAnswers</font></a></td>
<td>Mike Griffiths</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>82</strong></td>
<td align="middle">86</td>
<td><a href="http://ericbrown.com/"><font color="#ff6600">Aligning Technology, Strategy, People &amp; Projects</font></a></td>
<td>Eric Brown</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>83</strong></td>
<td align="middle">92</td>
<td><a href="http://www.focusedperformance.com/blogger.html"><font color="#ff6600">Focused Performance</font></a></td>
<td>Frank Patrick</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>84</strong></td>
<td align="middle">85</td>
<td><a href="http://www.chrisspagnuolo.com/"><font color="#ff6600">Chris Spagnuolo's EdgeHopper</font></a></td>
<td>Chris Spagnuolo</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>85</strong></td>
<td align="middle">63</td>
<td><a href="http://wordaligned.org/"><font color="#ff6600">Word Aligned</font></a></td>
<td>Thomas Guest</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>86</strong></td>
<td align="middle">84</td>
<td><a href="http://blog.cutter.com/"><font color="#ff6600">The Cutter Blog</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>87</strong></td>
<td align="middle">72</td>
<td><a href="http://www.agiledeveloper.com/blog/"><font color="#ff6600">Agile Developer Venkat's Blog</font></a></td>
<td>Venkat Subramaniam</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>88</strong></td>
<td align="middle">75</td>
<td><a href="http://www.kohl.ca/blog/"><font color="#ff6600">Collaborative Software Testing</font></a></td>
<td>Jonathan Kohl</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>89</strong></td>
<td align="middle">64</td>
<td><a href="http://www.io.com/~wazmo/blog/"><font color="#ff6600">Testing Hotlist Update</font></a></td>
<td>Bret Pettichord</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>90</strong></td>
<td align="middle">--</td>
<td><a href="http://agileproductdesign.com/blog/"><font color="#ff6600">Jeff Patton's Holistic Product Design &amp; Development</font></a></td>
<td>Jeff Patton</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>91</strong></td>
<td align="middle">83</td>
<td><a href="http://agilecommons.org/pages/home"><font color="#ff6600">Agile Commons</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>92</strong></td>
<td align="middle">88</td>
<td><a href="http://www.clarkeching.com/"><font color="#ff6600">Clarke Ching - More Chilli Please</font></a></td>
<td>Clarke Ching</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>93</strong></td>
<td align="middle">76</td>
<td><a href="http://testobsessed.com/"><font color="#ff6600">Test Obsessed</font></a></td>
<td>Elisabeth Hendrickson</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>94</strong></td>
<td align="middle">--</td>
<td><a href="http://littletutorials.com/"><font color="#ff6600">Little Tutorials</font></a></td>
<td>Daniel Pietraru</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>95</strong></td>
<td align="middle">79</td>
<td><a href="http://xndev.blogspot.com/"><font color="#ff6600">Creative Chaos</font></a></td>
<td>Matthew Heusser</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>96</strong></td>
<td align="middle">62</td>
<td><a href="http://bit-player.org/"><font color="#ff6600">Bit-Player</font></a></td>
<td>Brian Hayes</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>97</strong></td>
<td align="middle">69</td>
<td><a href="http://www.exampler.com/blog/"><font color="#ff6600">Exploration Through Example</font></a></td>
<td>Brian Marick</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>98</strong></td>
<td align="middle">--</td>
<td><a href="http://www.ytechie.com/"><font color="#ff6600">Ytechie</font></a></td>
<td>Jason Young</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>99</strong></td>
<td align="middle">91</td>
<td><a href="http://silkandspinach.net/"><font color="#ff6600">Silk and Spinach</font></a></td>
<td>Kevin Rutherford</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><strong>100</strong></td>
<td align="middle">82</td>
<td><a href="http://www.wrike.com/projectmanagement.htm"><font color="#ff6600">Project Management 2.0</font></a></td>
<td>Andrew Filev</td></tr>
<tr style="height: 12.75pt" height="17">
<td style="text-align: left" colSpan=4>
<div><strong>Legend <br />TT =</strong>&nbsp; 本次排名(Q4 2008)<strong> <br />LT =</strong> 上次排名 (Q3 2008) <br /><strong>--</strong> = 新入选 <br />除此之外，作者还给出了另外25个值的一读的Blog：</div></td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.notesfromatooluser.com/"><font color="#ff6600">Notes from a Tool User</font></a></td>
<td>Mark Levison</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://mendicantbug.com/"><font color="#ff6600">The Mendicant Bug</font></a></td>
<td>Jason Adams</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.ravensbrain.com/"><font color="#ff6600">Raven's Brain</font></a></td>
<td>Raven Young</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.htmlist.com/"><font color="#ff6600">HTMList.com</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.caffeinatedcoder.com/"><font color="#ff6600">Caffeinated Coder</font></a></td>
<td>Russell Ball</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://testertested.blogspot.com/"><font color="#ff6600">Tester Tested!</font></a></td>
<td>Pradeep Soundararajan</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://jchyip.blogspot.com/"><font color="#ff6600">You'd think with all my video game experience...</font></a></td>
<td>Jason Yip</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://dnicolet1.tripod.com/agile/"><font color="#ff6600">Effective Software Development</font></a></td>
<td>Dave Nicolette</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://blog.versionone.net/"><font color="#ff6600">Agile Chronicles</font></a></td>
<td>(various)</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.agilecmmi.com/"><font color="#ff6600">Agile CMMI Blog</font></a></td>
<td>Hillel Glazer</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://agilethinking.net/blog/"><font color="#ff6600">Agile Thoughts</font></a></td>
<td>Tobias Mayer</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.estherderby.com/weblog/blogger.html"><font color="#ff6600">Insights You Can Use</font></a></td>
<td>Esther Derby</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://stephan.reposita.org/"><font color="#ff6600">Stephans Blog</font></a></td>
<td>Stephan Schmidt</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://edgibbs.com/"><font color="#ff6600">Musings of a Software Development Manager</font></a></td>
<td>Ed Gibbs</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.leadingagile.com/"><font color="#ff6600">Leading Agile</font></a></td>
<td>Mike Cottmeyer</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.danappleman.com/"><font color="#ff6600">Kibitzing and Commentary</font></a></td>
<td>Dan Appleman</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://blog.brodzinski.com/"><font color="#ff6600">Software Project Management</font></a></td>
<td>Pawel Brodzinski</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://enterprisearchitect.typepad.com/ea/"><font color="#ff6600">Technology Architecture &amp; Projects</font></a></td>
<td>Robert McIlree</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://swizec.com/"><font color="#ff6600">Cthulhu and Other Crazies</font></a></td>
<td>Swizec</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://aspadvice.com/blogs/elandes/default.aspx"><font color="#ff6600">Corporate Coder</font></a></td>
<td>Eric Landes</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://www.yuwantitwhen.com/"><font color="#ff6600">You Want IT When?</font></a></td>
<td>Bill Miller</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://scalingsoftwareagility.wordpress.com/"><font color="#ff6600">Scaling Software Agility</font></a></td>
<td>Dean Leffingwell</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://pierg.wordpress.com/"><font color="#ff6600">PierG</font></a></td>
<td>Piergiorgio Grossi</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://availagility.wordpress.com/"><font color="#ff6600">AvailAgility</font></a></td>
<td>Karl Scotland</td></tr>
<tr style="height: 12.75pt" height="17">
<td align="middle"><br /></td>
<td align="middle">&nbsp;</td>
<td><a href="http://adam.goucher.ca/"><font color="#ff6600">Quality through Innovation</font></a></td>
<td>Adam Goucher</td></tr></tbody></table><br />
<div>大家可以从这里<a href="http://nooperation.typepad.com/files/top100developmentblogsq42008.xml"><font color="#ff6600">下载OPML文件</font></a>，直接导入自己的RSS阅读器。</div>
<div>原文链接：<a href="http://www.noop.nl/2008/12/top-100-blogs-for-developers-q4-2008.html"><font color="#ff6600">Top 100 Blogs for Developers (Q4 2008)</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151988]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[IT管理]]></category>
 <pubdate><![CDATA[Mon, 22 Dec 2008 19:15:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[应用程序架构指导袖珍版 ]]></title>
 <description><![CDATA[<div>微软模式与实践小组最近发布了应用程序架构指导袖珍版本，总共有6本，分别介绍了不同类型应用程序的架构指导，包括敏捷架构方法、Mobile应用程序、RIA应用程序、富客户端应用程序、Web应用程序以及Service架构等，非常值得一看。</div>
<h2>1. 敏捷架构方法</h2>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="195" alt="App_Guide_Agile" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/edfad4bab8ac_14753/App_Guide_Agile_3.png" width="150" border="0" /> </div>
<div><a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19797"><font color="#ff6600">下载指导</font></a></div>
<h2>2. Web引用架构</h2>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="195" alt="App_Guide_Web" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/edfad4bab8ac_14753/App_Guide_Web_3.png" width="150" border="0" /> </div>
<div><a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19802"><font color="#ff6600">下载指导</font></a></div>
<h2>3. 移动应用架构</h2>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="194" alt="App_Guide_Mobile" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/edfad4bab8ac_14753/App_Guide_Mobile_3.png" width="150" border="0" /> </div>
<div><a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19798"><font color="#ff6600">下载指导</font></a></div>
<h2>4. RIA架构</h2>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="194" alt="App_Guide_RIA" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/edfad4bab8ac_14753/App_Guide_RIA_3.png" width="150" border="0" /> </div>
<div><a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19799"><font color="#ff6600">下载指导</font></a></div>
<h2>5. 富客户端架构</h2>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="195" alt="App_Guide_RCA" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/edfad4bab8ac_14753/App_Guide_RCA_3.png" width="150" border="0" /> </div>
<div><a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19800"><font color="#ff6600">下载指导</font></a></div>
<h2>6. 服务架构</h2>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="194" alt="App_Guide_Service" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/edfad4bab8ac_14753/App_Guide_Service_3.png" width="150" border="0" /> </div>
<div><a href="http://www.codeplex.com/AppArch/Release/ProjectReleases.aspx?ReleaseId=19801"><font color="#ff6600">下载指导</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151994]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[IT管理]]></category>
 <pubdate><![CDATA[Mon, 08 Dec 2008 00:33:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[使用微软分布式缓存服务Velocity Part 3 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>Velocity是微软推出的分布式缓存解决方案，为开发可扩展性，可用的，高性能的应用程提供支持，可以缓存各种类型的数据，如CLR对象、XML、二进制数据等，并且支持集群模式的缓存服务器。Velocity也将集成在.NET Framework 4.0中，本文将介绍Velocity中的悲观锁定，缓存项版本、日志记录、客户端缓存以及路由表等知识。 
<h2>悲观锁定</h2>
<div>在Velocity提供了一套悲观锁定模型，即在某个缓存项数据处理过程中，数据将处于锁定状态，来自于其它客户端应用程序将无法对该缓存项进行处理。提供悲观锁定的方法主要三个，如下代码所示： 
<div><b>GetAndLock()</b>：获取缓存项并对数据加锁； 
<div><b>PutAndUnlock()</b>：更新加锁的数据并释放锁； 
<div><b>Unlock()</b>：释放锁定。 
<div>先来看GetAndLock()方法，在获取缓存项时并加锁，此时如果其它客户端试图获取该数据并加锁（即调用GetAndLock方法）将会失败，而不会阻塞；但客户端如果只想获取数据（即调用Get方法），则会返回相应数据，可以用图1形象的来表示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="247" alt="Velocity_003" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart3_13D31/Velocity_003_3.png" width="570" border="0" /> 
<div>图 1 
<div>可以看到，ClientA获取数据成功并加锁；ClientB再次想获取数据并加锁时，将会失败；ClientC能够获取数据。 
<div>使用GetAndLock()方式可以指定锁过期时间，并且会有输出参数LockHandle，该参数将会在PutAndUnlock()方法或Unlock()中来释放锁，如下代码所示：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: #2b91af">LockHandle </span>handle = <span style="color: blue">new </span><span style="color: #2b91af">LockHandle</span>();
<span style="color: #2b91af">Customer </span>item = (<span style="color: #2b91af">Customer</span>)cache.GetAndLock(<span style="color: #a31515">"C20081117005"</span>,
         <span style="color: blue">new </span><span style="color: #2b91af">TimeSpan</span>(0, 30, 0), <span style="color: blue">out </span>handle);
<span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117005"</span>,
    FirstName = <span style="color: #a31515">"Terry"</span>,
    LastName = <span style="color: #a31515">"Lee"</span>,
    Age = 25,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
cache.PutAndUnlock(customer.ID, customer, handle, <span style="color: blue">null</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<h2>日志记录</h2>
<div>Velocity中同样提供了日志记录的功能，我们可以在应用程序配置文件中进行设置，它支持基于控制台、基于文件以及Windows事件跟踪三种方式的记录，在配置文件中首先添加配置区：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">section </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">fabric</span>" <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Fabric.Common.ConfigFile, FabricCommon</span>"
         <span style="color: red">allowLocation</span><span style="color: blue">=</span>"<span style="color: blue">true</span>" <span style="color: red">allowDefinition</span><span style="color: blue">=</span>"<span style="color: blue">Everywhere</span>"<span style="color: blue">/&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>然后可以进行配置，如设置日志记录级别等：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">fabric</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">section </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">logging</span>" <span style="color: red">path</span><span style="color: blue">=</span>""<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">collection </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">sinks</span>" <span style="color: red">collectionType</span><span style="color: blue">=</span>"<span style="color: blue">list</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">customType </span><span style="color: red">className</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Fabric.Common.EventLogger,FabricCommon</span>"
                  <span style="color: red">sinkName</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Fabric.Common.ConsoleSink,FabricCommon</span>"
                  <span style="color: red">sinkParam</span><span style="color: blue">=</span>"" <span style="color: red">defaultLevel</span><span style="color: blue">=</span>"<span style="color: blue">-1</span>"<span style="color: blue">/&gt;
      &lt;</span><span style="color: #a31515">customType </span><span style="color: red">className</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Fabric.Common.EventLogger,FabricCommon</span>"
                  <span style="color: red">sinkName</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Fabric.Common.FileEventSink,FabricCommon</span>"
                  <span style="color: red">sinkParam</span><span style="color: blue">=</span>"<span style="color: blue">CacheClientLog</span>" <span style="color: red">defaultLevel</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">/&gt;
      &lt;</span><span style="color: #a31515">customType </span><span style="color: red">className</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Fabric.Common.EventLogger,FabricCommon</span>"
                  <span style="color: red">sinkName</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Caching.ETWSink, CacheBaseLibrary</span>"
                  <span style="color: red">sinkParam</span><span style="color: blue">=</span>"" <span style="color: red">defaultLevel</span><span style="color: blue">=</span>"<span style="color: blue">-1</span>" <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">collection</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">section</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">fabric</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>同样也可以在代码中设置，调用CacheFactory的两个静态方法CreateLogSinks和DisableLogSinks，如下代码所示：<pre class=code><span style="color: blue">private </span><span style="color: #2b91af">Cache </span>GetCurrentCache()
{
    <span style="color: #2b91af">List</span>&lt;<span style="color: #2b91af">LogSink</span>&gt; sinklist = <span style="color: blue">new </span><span style="color: #2b91af">List</span>&lt;<span style="color: #2b91af">LogSink</span>&gt;(2);
    <span style="color: #2b91af">LogSink </span>fileBasedSink = <span style="color: blue">new </span><span style="color: #2b91af">LogSink</span>(<span style="color: #2b91af">SinkType</span>.FILE,
        <span style="color: #2b91af">TraceLevel</span>.Warning, <span style="color: #a31515">"DCache/dd-hh-mm"</span>);
    <span style="color: #2b91af">LogSink </span>consoleBasedSink = <span style="color: blue">new </span><span style="color: #2b91af">LogSink</span>(<span style="color: #2b91af">SinkType</span>.CONSOLE,
        <span style="color: #2b91af">TraceLevel</span>.Warning);
    sinklist.Add(fileBasedSink);
    sinklist.Add(consoleBasedSink);
    <span style="color: green">// 启用
    </span><span style="color: #2b91af">CacheFactory</span>.CreateLogSinks(sinklist);
    <span style="color: green">// 禁用
    </span><span style="color: #2b91af">CacheFactory</span>.DisableLogSinks();
    <span style="color: #2b91af">Cache </span>dCache;
    <span style="color: #2b91af">ServerEndPoint</span>[] servers = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>[1];
    servers[0] = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>(<span style="color: #a31515">"localhost"</span>, 22233, <span style="color: #a31515">"DistributedCacheService"</span>);
    <span style="color: blue">bool </span>routingClient = <span style="color: blue">true</span>;
    <span style="color: blue">bool </span>localCache = <span style="color: blue">false</span>;
    <span style="color: blue">var </span>factory = <span style="color: blue">new </span><span style="color: #2b91af">CacheFactory</span>(servers, routingClient, localCache);
    dCache = factory.GetCache(<span style="color: #a31515">"default"</span>);
    <span style="color: blue">return </span>dCache;
}</pre><a href="http://11011.net/software/vspaste"></a>
<h2>缓存项版本</h2>
<div>在Velocity中提供了一种基于版本的更新功能，当使用GetCacheItem()方法时将返回一个缓存项，并携带有版本信息，当每次对缓存项做更新时，在内部都会对它的版本增加。如下面的示例，有两个客户应用程序，它们同时获取了同一个缓存项： 
<div><strong>ClientA</strong><pre class=code><span style="color: #2b91af">CacheItem </span>item = cache.GetCacheItem(<span style="color: #a31515">"Customers"</span>, <span style="color: #a31515">"C2008"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div><strong>ClientB</strong><pre class=code><span style="color: #2b91af">CacheItem </span>item = cache.GetCacheItem(<span style="color: #a31515">"Customers"</span>, <span style="color: #a31515">"C2008"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div>并且同时对缓存项做修改： 
<div><strong>ClientA</strong><pre class=code>((<span style="color: #2b91af">Customer</span>)item.CacheObject).FirstName = <span style="color: #a31515">"Huijun"</span>;</pre><a href="http://11011.net/software/vspaste"></a>
<div><strong>ClientB</strong><pre class=code>((<span style="color: #2b91af">Customer</span>)item.CacheObject).FirstName = <span style="color: #a31515">"Terry"</span>;</pre><a href="http://11011.net/software/vspaste"></a>
<div>如果ClientA首先提交更改，在提交更改时携带版本信息，由于版本信息与内部的版本一致，所以提交成功： 
<div><strong>ClientA</strong><pre class=code>cache.Put(<span style="color: #a31515">"Customers"</span>, <span style="color: #a31515">"C2008"</span>, item.CacheObject, item.Version);</pre><a href="http://11011.net/software/vspaste"></a>
<div>此时内部版本将会增加，现在ClientB如果再提交更改，将会失败，因为版本无法匹配，如图2表示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="456" alt="Velocity_004" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart3_13D31/Velocity_004_3.png" width="509" border="0" /> 
<div>图 2 
<h2>客户端缓存</h2>
<div>在Velocity中还支持客户端缓存，如果启用了客户端缓存后，在从缓存集群中取回数据时，将会放在客户端缓存中，这样下次取数据时将会直接从客户端缓存中取出，能够极大的提高效率，有点像是缓存的缓存。当集群中的数据发生变化时，Velocity将会使用事件通知机制通知客户端缓存刷新数据，如图3所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="344" alt="Velocity_005" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart3_13D31/Velocity_005_3.png" width="577" border="0" /> 
<div>图 3 
<div>要启用客户端缓存，一是使用配置文件，设置IsEnabled属性为True，如下代码所示：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">dcacheClient </span><span style="color: red">deployment</span><span style="color: blue">=</span>"<span style="color: blue">routing</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">localCache </span><strong><span style="color: red">isEnabled</span><span style="color: blue">=</span>"<span style="color: blue">true</span>"</strong> <span style="color: red">sync</span><span style="color: blue">=</span>"<span style="color: blue">TTLBased</span>" <span style="color: red">ttlValue</span><span style="color: blue">=</span>"<span style="color: blue">300</span>" <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">host </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">localhost</span>" <span style="color: red">cachePort</span><span style="color: blue">=</span>"<span style="color: blue">22233</span>" 
          <span style="color: red">cacheHostName</span><span style="color: blue">=</span>"<span style="color: blue">DistributedCacheService</span>"<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">dcacheClient</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>直接指定启用客户端缓存即可，另外也可以在创建CacheFactory时指定，如下代码所示：<pre class=code><span style="color: #2b91af">Cache </span>dCache;
<span style="color: #2b91af">ServerEndPoint</span>[] servers = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>[1];
servers[0] = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>(<span style="color: #a31515">"localhost"</span>, 22233, <span style="color: #a31515">"DistributedCacheService"</span>);
<span style="color: blue">bool </span>routingClient = <span style="color: blue">true</span>;
<strong><span style="color: blue">bool </span>localCache = <span style="color: blue">false</span>;</strong>
<span style="color: blue">var </span>factory = <span style="color: blue">new </span><span style="color: #2b91af">CacheFactory</span>(servers, routingClient, localCache);
dCache = factory.GetCache(<span style="color: #a31515">"default"</span>);
<span style="color: blue">return </span>dCache;</pre><a href="http://11011.net/software/vspaste"></a>
<h2>路由客户端</h2>
<div>Velocity中在缓存客户端，提供了一种路由客户端Routing Client，它能够提供比简单客户端Simple Client更好的性能，在Routing Client中会有一个路由表Routing Table，它用来跟踪缓存对象，它是全局缓存中的分区映射的一个子集，同时分发缓存操作（Put、Get等）到确定的缓存宿主。路由客户端使用此路由表来优化性能，因为该表可以跟踪缓存对象，所以当有请求到缓存宿主时，可以进行物理上的定位。如图4所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="367" alt="Velocity_007" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart3_13D31/Velocity_007_3.png" width="580" border="0" /> 
<div>图4 
<div>是否在应用程序中启用路由客户端，可以由开发者来确定，如在配置中启用路由客户端，这里可以通过指示deployment来设定是路由客户端（routing）还是简单客户端（simple）：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">dcacheClient </span><span style="color: red">deployment</span><span style="color: blue">=</span>"<span style="color: blue">routing</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">localCache </span><span style="color: red">isEnabled</span><span style="color: blue">=</span>"<span style="color: blue">true</span>" <span style="color: red">sync</span><span style="color: blue">=</span>"<span style="color: blue">TTLBased</span>" <span style="color: red">ttlValue</span><span style="color: blue">=</span>"<span style="color: blue">300</span>" <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">host </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">localhost</span>" <span style="color: red">cachePort</span><span style="color: blue">=</span>"<span style="color: blue">22233</span>" 
          <span style="color: red">cacheHostName</span><span style="color: blue">=</span>"<span style="color: blue">DistributedCacheService</span>"<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">dcacheClient</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>另外还可以通过代码来设置，如下面的代码，在创建CacheFactory时指定构造函数参数：<pre class=code><span style="color: #2b91af">Cache </span>dCache;
<span style="color: #2b91af">ServerEndPoint</span>[] servers = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>[1];
servers[0] = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>(<span style="color: #a31515">"localhost"</span>, 22233, <span style="color: #a31515">"DistributedCacheService"</span>);
<span style="color: blue">bool </span>routingClient = <span style="color: blue">true</span>;
<span style="color: blue">bool </span>localCache = <span style="color: blue">false</span>;
<span style="color: blue">var </span>factory = <span style="color: blue">new </span><span style="color: #2b91af">CacheFactory</span>(servers, routingClient, localCache);
dCache = factory.GetCache(<span style="color: #a31515">"default"</span>);
<span style="color: blue">return </span>dCache;</pre><a href="http://11011.net/software/vspaste"></a>
<h2>Velocity组成</h2>
<div>最后我们再看一幅图，来了解一下Velocity的组成部分，可以看到它可以分为客户端缓存、服务端缓存以及管理工具三部分，如图5所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="423" alt="Velocity_006" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart3_13D31/Velocity_006_3.png" width="580" border="0" /> 
<div>图 5 
<h2>总结</h2>
<div>本文介绍了Velocity中的悲观锁定，缓存项版本、日志记录、客户端缓存以及路由表等知识，希望对大家有用。至此，关于微软的分布式缓存服务Velocity就用短短的三篇文章介绍到这里，期待在.NET Framework 4.0中Velocity能够为我们带来更多的惊喜。 
<div>相关文章： 
<div>1. <a href="http://www.cnblogs.com/Terrylee/archive/2008/11/20/Microsoft-Distributed-Cache-Velocity-Part1.html"><font color="#ff6600">使用微软分布式缓存服务Velocity Part 1</font></a> 
<div>2. <a href="http://www.cnblogs.com/Terrylee/archive/2008/11/21/Microsoft-Distributed-Cache-Velocity-Part2.html"><font color="#ff6600">使用微软分布式缓存服务Velocity Part 2</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151996]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[.Net]]></category>
 <pubdate><![CDATA[Sun, 07 Dec 2008 22:42:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[写在WinHEC开幕之际：沿着Windows我们一路走来 ]]></title>
 <description><![CDATA[<div>微软 2008 Windows 硬件工程大会（Windows Hardware Engineering Conference 2008，简称WinHEC 2008 China）即将于 2008年12月3-4日在北京万豪酒店盛大开幕，今年是微软第一次在中国独立举办WinHEC大会，以至于<a href="http://www.cnblogs.com/jessequ/"><font color="#ff6600">JesseQu</font></a>用<a href="http://www.cnblogs.com/jessequ/archive/2008/11/23/1339327.html"><font color="#ff6600">WinHEC终于来了</font></a>一文回忆了自己近18年软件开发工作中对驱动、内核层次开发工作的情愫感慨。在WinHEC 2008开幕之际，让我们一起来回顾一下Windows的发展历史，寻找那些曾经熟悉的符号。</div>
<div>MS-Dos 1.0发布，不知道有多少人还记得这个界面，MS-DOS是Microsoft Disk Operating System的简称，意即由美国微软公司(Microsoft)提供的磁盘操作系统。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="362" alt="windows_001" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_001_3.png" width="391" border="0" /> </div>
<div>1985年11月，Microsoft Windows 1.0 发布，Microsoft Windows 1.0是微软第一次对个人电脑操作平台进行用户图形界面的尝试。Windows 1.0本质上宣告了MS-DOS操作系统的终结。 </div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="302" alt="windows_002" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_002_3.png" width="470" border="0" /> </div>
<div>1987年12月9日，Windows 2.0发布</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="302" alt="windows_003" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_003_3.png" width="470" border="0" /> </div>
<div>1990年5月22日，Windows 3.0正式发布，由于在界面/人性化/内存管理多方面的巨大改进，终于获得用户的认同。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="358" alt="windows_004" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_004_3.png" width="470" border="0" /> </div>
<div>1994年，windows 3.2的中文版本发布，相信国内有不少windows的先驱用户就是从这个版本开始接触windows系统的；由于消除了语言障碍，降低了学习门槛，因此很快在国内流行了起来。在这之前，微软还曾经发布了Windows 3.1版本。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="427" alt="windows_005" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_005_3.png" width="470" border="0" /> </div>
<div>1995年8月24日注定要被微软写入历史，因为这一天微软发布了Windows 95，并且取得了空前的成功，据说当年好多没有电脑的用户都在排队买Windows 95，因此Windows 95也成为微软Windows发展史的一个里程碑。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="338" alt="windows_011" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_011_3.png" width="456" border="0" /> </div>
<div>1996年8月，Windows NT 4.0发布，增加了许多对应管理方面的特性，稳定性也相当不错。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="311" alt="windows_006" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_006_3.png" width="470" border="0" /> </div>
<div>1998年6月25日，Windows 98发布，并且集成了Internet Explorer。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="356" alt="windows_007" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_007_3.png" width="470" border="0" /> </div>
<div>Windows ME（Windows Millennium Edition）是一个16位/32位混合的Windows系统，由微软公司发行于2000年9月14日。 Windows Me是最后一个基于DOS的混合16位/32位的Windows 9X系列的Windows，其版本号为4.9。其名字有两个意思，一是纪念2000年，Me是千年的意思，另外是指个人运用版，Me是英文中自己的意思。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="398" alt="windows_008" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_008_3.png" width="470" border="0" /> </div>
<div>在千禧年的钟声后，迎来了Windows NT 5.0，为了纪念特别的新千年，这个操作系统也被命名为Windows 2000。Windows 2000包含新的NTFS文件系统、EFS文件加密、增强硬件支持等新特性，向一直被unix系统垄断的服务器市场发起了强有力的冲击。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="358" alt="windows_009" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_009_3.png" width="470" border="0" /> </div>
<div>2001年10月25日，Windows XP发布。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="311" alt="windows_010" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_010_3.png" width="470" border="0" /> </div>
<div>2003年3月28日，Windows Server 2003发布；对活动目录、组策略操作和管理、磁盘管理等面向服务器的功能作了较大改进，对.net技术的完善支持进一步扩展了服务器的应用范围，一开始，该产品叫作“Windows .NET Server”，改成“Windows .NET Server 2003”，后最终被改成“Windows Server 2003”。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="358" alt="windows_013" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_013_3.png" width="470" border="0" /> </div>
<div>2006年微软发布了Windows Vista，而最先它的开发代号为“Longhorn”，微软确定Vista名称的时间是：2005年7月22日太平洋标准时间早晨6点。</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="320" alt="windows_012" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Windows_F982/windows_012_3.png" width="420" border="0" />&nbsp;</div>
<div>微软下一代 Windows 操作系统Windows 7将在 WinHEC 2008 China 的舞台上首次揭秘，期待Windows 7能够给我们带来更多的惊喜，除此之外，本次WinHEC 2008还将带来其他微软最新技术如 Windows Home Server , Microsoft Response Point , .NET Micro Framework , Surface 和中国新一代的标准包括数字高清 DMB-TH 与移动宽带。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151963]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[IT管理]]></category>
 <pubdate><![CDATA[Sun, 23 Nov 2008 18:59:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[使用微软分布式缓存服务Velocity Part 2 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>Velocity是微软推出的分布式缓存解决方案，为开发可扩展性，可用的，高性能的应用程提供支持，可以缓存各种类型的数据，如CLR对象、XML、二进制数据等，并且支持集群模式的缓存服务器。Velocity也将集成在.NET Framework 4.0中，本文将介绍Velocity中的配置模型、缓存复杂数据和创建分区、使用标签以及ASP.NET SessionState提供者。 
<h2>配置模型</h2>
<div>在本文开始之前，先简单介绍一下Velocity中的配置模型，主要包括三方面的配置，缓存集群的配置，缓存宿主服务器配置以及应用程序的配置，如下图所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="309" alt="Velocity_001" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart2_14B47/Velocity_001_3.png" width="580" border="0" /> 
<div>缓存集群的配置，可以基于XML、SQL Server CE或者SQL Server数据库来进行存储，包括各个服务器以及所有的命名缓存、是否过期等配置，当我们使用Windows PowerShell管理工具进行配置时，将会修改该配置文件，如下代码所示：<pre class=code><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>"<span style="color: blue">1.0</span>" <span style="color: red">encoding</span><span style="color: blue">=</span>"<span style="color: blue">utf-8</span>"<span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">configSections</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">section </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">dcache</span>" <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Caching.DCacheSection, 
             CacheBaseLibrary, Version=1.0.0.0, Culture=neutral,
             PublicKeyToken=89845dcd8080cc91</span>" <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">configSections</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">dcache </span><span style="color: red">cluster</span><span style="color: blue">=</span>"<span style="color: blue">localhost</span>" <span style="color: red">size</span><span style="color: blue">=</span>"<span style="color: blue">Small</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">caches</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">cache </span><span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">partitioned</span>" <span style="color: red">consistency</span><span style="color: blue">=</span>"<span style="color: blue">strong</span>" <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">default</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">policy</span><span style="color: blue">&gt;
          &lt;</span><span style="color: #a31515">eviction </span><span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">lru</span>" <span style="color: blue">/&gt;
          &lt;</span><span style="color: #a31515">expiration </span><span style="color: red">defaultTTL</span><span style="color: blue">=</span>"<span style="color: blue">10</span>" <span style="color: red">isExpirable</span><span style="color: blue">=</span>"<span style="color: blue">true</span>" <span style="color: blue">/&gt;
        &lt;/</span><span style="color: #a31515">policy</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">cache</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">cache </span><span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">partitioned</span>" <span style="color: red">consistency</span><span style="color: blue">=</span>"<span style="color: blue">strong</span>" <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">other</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">policy</span><span style="color: blue">&gt;
          &lt;</span><span style="color: #a31515">eviction </span><span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">lru</span>" <span style="color: blue">/&gt;
          &lt;</span><span style="color: #a31515">expiration </span><span style="color: red">defaultTTL</span><span style="color: blue">=</span>"<span style="color: blue">10</span>" <span style="color: red">isExpirable</span><span style="color: blue">=</span>"<span style="color: blue">true</span>" <span style="color: blue">/&gt;
        &lt;/</span><span style="color: #a31515">policy</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">cache</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">caches</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">host </span><span style="color: red">clusterPort</span><span style="color: blue">=</span>"<span style="color: blue">22234</span>" <span style="color: red">hostId</span><span style="color: blue">=</span>"<span style="color: blue">1319514812</span>" <span style="color: red">size</span><span style="color: blue">=</span>"<span style="color: blue">1024</span>" <span style="color: red">quorumHost</span><span style="color: blue">=</span>"<span style="color: blue">true</span>"
          <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TERRYLEE-PC</span>" <span style="color: red">cacheHostName</span><span style="color: blue">=</span>"<span style="color: blue">DistributedCacheService</span>"
          <span style="color: red">cachePort</span><span style="color: blue">=</span>"<span style="color: blue">22233</span>" <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">advancedProperties</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">partitionStoreConnectionSettings </span><span style="color: red">providerName</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.SqlServerCe.3.5</span>"
          <span style="color: red">connectionString</span><span style="color: blue">=</span>"<span style="color: blue">D:\CacheShare\ConfigStore.sdf</span>" <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">advancedProperties</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">dcache</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<div>在上一篇的示例中，并没有使用应用程序配置文件，事实上使用配置文件是更好的编程实践，首先需要添加一个配置区：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">section </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">dcacheClient</span>"
<span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Caching.DCacheSection, 
      CacheBaseLibrary, Version=1.0.0.0, 
      Culture=neutral, PublicKeyToken=89845dcd8080cc91</span>"<span style="color: blue">/&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>配置信息包括部署方式，是否启用本地缓存以及缓存宿主等，如下代码所示：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">dcacheClient</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">localCache </span><span style="color: red">isEnabled</span><span style="color: blue">=</span>"<span style="color: blue">true</span>" <span style="color: red">sync</span><span style="color: blue">=</span>"<span style="color: blue">TTLBased</span>" <span style="color: red">ttlValue</span><span style="color: blue">=</span>"<span style="color: blue">300</span>" <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">host </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">localhost</span>" <span style="color: red">cachePort</span><span style="color: blue">=</span>"<span style="color: blue">22233</span>" 
          <span style="color: red">cacheHostName</span><span style="color: blue">=</span>"<span style="color: blue">DistributedCacheService</span>"<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">dcacheClient</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<div>现在Velocity CTP2对于应用程序使用配置的支持似乎有些问题。缓存宿主的配置放在DistributedCache.exe.config文件中，可以在Velocity安装目录下找到。 
<h2>缓存复杂数据类型</h2>
<div>在Velocity中，可以缓存任何类型的数据，如CLR对象、XML或者二进制数据等。现在看一个简单的示例，如何缓存复杂类型数据，定义一个如下的Customer类，注意要能够序列化：<pre class=code>[<span style="color: #2b91af">Serializable</span>]
<span style="color: blue">public class </span><span style="color: #2b91af">Customer
</span>{
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>ID { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>FirstName { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>LastName { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public int </span>Age { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>Email { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>对应用程序做配置，参考本文的配置模型部分，使用方法与简单数据类型的基本一致，如添加缓存项，使用Customer主键作为缓存键，其中GetCurrentCache()方法的实现请参考上一篇文章：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117002"</span>,
    FirstName = <span style="color: #a31515">"Terry"</span>,
    LastName = <span style="color: #a31515">"Lee"</span>,
    Age = 25,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
cache.Add(customer.ID, customer);</pre><a href="http://11011.net/software/vspaste"></a>
<div>获取缓存项：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: #2b91af">Customer </span>customer = cache.Get(<span style="color: #a31515">"C20081117002"</span>) <span style="color: blue">as </span><span style="color: #2b91af">Customer</span>;</pre><a href="http://11011.net/software/vspaste"></a>
<div>移除缓存项：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
cache.Remove(<span style="color: #a31515">"C20081117002"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div>更新缓存中数据，可以有两种方法，一是直接使用缓存索引，如果确保缓存键存在：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117002"</span>,
    FirstName = <span style="color: #a31515">"Huijui"</span>,
    LastName = <span style="color: #a31515">"Li"</span>,
    Age = 26,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
cache[<span style="color: #a31515">"C20081117002"</span>] = customer;</pre><a href="http://11011.net/software/vspaste"></a>
<div>另外一种是使用Put方法，如果缓存键不存在，它将会新增到缓存中，否则会进行覆盖，如下代码所示：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117002"</span>,
    FirstName = <span style="color: #a31515">"Huijui"</span>,
    LastName = <span style="color: #a31515">"Li"</span>,
    Age = 26,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
cache.Put(customer.ID, customer);</pre><a href="http://11011.net/software/vspaste"></a>
<h2>使用分区</h2>
<div>在实际部署中，经常会出现多个应用程序共享同一个缓存集群，这不可避免的会出现缓存键冲突，如上面的示例中使用CustomerID作为缓存键，此时可以使用Velocity中的分区功能，它会在逻辑上把各个命名缓存再进行分区，这样可以完全保持数据隔离，如下图所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="387" alt="TerryLee_0216" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart2_14B47/TerryLee_0216_3.png" width="519" border="0" /> 
<div>图中共有三个命名缓存，其中在缓存Catalog中又分区为Sports和Arts。在Velocity中对于分区的操作提供了如下三个方法，可以用于创建分区，删除分区以及清空分区中所有的对象：<pre class=code><span style="color: blue">public void </span>ClearRegion(<span style="color: blue">string </span>region);
<span style="color: blue">public bool </span>CreateRegion(<span style="color: blue">string </span>region, <span style="color: blue">bool </span>evictable);
<span style="color: blue">public bool </span>RemoveRegion(<span style="color: blue">string </span>region);</pre><a href="http://11011.net/software/vspaste"></a>
<div>如下代码所示，创建了一个名为“Customers”的分区，在调用Add方法时可以指定数据将会缓存到哪个分区：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: blue">string </span>regionName = <span style="color: #a31515">"Customers"</span>;
cache.CreateRegion(regionName, <span style="color: blue">false</span>);
<span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117003"</span>,
    FirstName = <span style="color: #a31515">"Terry"</span>,
    LastName = <span style="color: #a31515">"Lee"</span>,
    Age = 25,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
cache.Add(regionName, customer.ID, customer);</pre><a href="http://11011.net/software/vspaste"></a>
<div>可以使用Get-CacheRegion命令在Windows PowerShell中来查看一下当前缓存集群中所有的分区信息，如下图所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="222" alt="Velocity_002" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart2_14B47/Velocity_002_3.png" width="580" border="0" /> 
<div>同样在检索缓存数据时，仍然可以使用分区名进行检索。 
<h2>使用标签</h2>
<div>在Velocity还允许对加入到缓存中的缓存项设置Tag，可以是一个或者多个，使用了Tag，就可以从多个方面对缓存项进行描述，这样在检索数据时，就可以根据Tag来一次检索多个缓存项。为缓存项设置Tag，如下代码所示：<pre class=code><span style="color: #2b91af">Cache </span>cache = GetCurrentCache();
<span style="color: blue">string </span>regionName = <span style="color: #a31515">"Customers"</span>;
<span style="color: #2b91af">Customer </span>customer1 = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117004"</span>,
    FirstName = <span style="color: #a31515">"Terry"</span>,
    LastName = <span style="color: #a31515">"Lee"</span>,
    Age = 25,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
<span style="color: #2b91af">Customer </span>customer2 = <span style="color: blue">new </span><span style="color: #2b91af">Customer</span>()
{
    ID = <span style="color: #a31515">"C20081117005"</span>,
    FirstName = <span style="color: #a31515">"Terry"</span>,
    LastName = <span style="color: #a31515">"Lee"</span>,
    Age = 25,
    Email = <span style="color: #a31515">"lhj_cauc[#AT#]163.com"
</span>};
<span style="color: #2b91af">Tag </span>tag1 = <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>(<span style="color: #a31515">"Beijing"</span>);
<span style="color: #2b91af">Tag </span>tag2 = <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>(<span style="color: #a31515">"Tianjin"</span>);
cache.Add(regionName, customer1.ID, customer1, <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>[] { tag1, tag2 });
cache.Add(regionName, customer2.ID, customer2, <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>[] { tag2 });</pre><a href="http://11011.net/software/vspaste"></a>
<div>这样就可以对设置了Tag的缓存项进行检索，根据实际需求选择使用如下三个方法之一：<pre class=code>GetAllMatchingTags(<span style="color: blue">string </span>region, <span style="color: #2b91af">Tag</span>[] tags)
GetAnyMatchingTag(<span style="color: blue">string </span>region, <span style="color: #2b91af">Tag</span>[] tags)
GetByTag(<span style="color: blue">string </span>region, <span style="color: #2b91af">Tag </span>tag)</pre><a href="http://11011.net/software/vspaste"></a>
<div>第一个检索匹配所有Tag的数据，第二个检索匹配所有Tag中的任意一个即可，最后只使用一个Tag，如下代码所示：<pre class=code><span style="color: blue">string </span>regionName = <span style="color: #a31515">"Customers"</span>;
<span style="color: #2b91af">Tag</span>[] tags = <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>[] { <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>(<span style="color: #a31515">"Beijing"</span>), 
           <span style="color: blue">new </span><span style="color: #2b91af">Tag</span>(<span style="color: #a31515">"Tianjin"</span>)};
<span style="color: #2b91af">List</span>&lt;<span style="color: #2b91af">KeyValuePair</span>&lt;<span style="color: blue">string</span>, <span style="color: blue">object</span>&gt;&gt; result
    = cache.GetAllMatchingTags(regionName, tags);</pre><a href="http://11011.net/software/vspaste"></a>
<div>使用Tag功能对于检索缓存项提供了极大的灵活性，对于任何一个数据，都可以使用多个Tag从很多方面去描述它。 
<h2>ASP.NET SessionState提供者</h2>
<div>Velocity还提供了对于ASP.NET SessionState提供者的支持，可以通过配置把Session信息缓存到缓存集群中，添加Velocity配置区：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">section </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">dcacheClient</span>"
         <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Caching.DCacheSection, 
         CacheBaseLibrary, Version=1.0.0.0, 
         Culture=neutral, PublicKeyToken=89845dcd8080cc91</span>"<span style="color: blue">/&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>配置缓存客户端信息：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">dcacheClient</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">localCache </span><span style="color: red">isEnabled</span><span style="color: blue">=</span>"<span style="color: blue">true</span>" <span style="color: red">sync</span><span style="color: blue">=</span>"<span style="color: blue">TTLBased</span>" <span style="color: red">ttlValue</span><span style="color: blue">=</span>"<span style="color: blue">300</span>" <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">host </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">localhost</span>" <span style="color: red">cachePort</span><span style="color: blue">=</span>"<span style="color: blue">22233</span>" 
          <span style="color: red">cacheHostName</span><span style="color: blue">=</span>"<span style="color: blue">DistributedCacheService</span>"<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">hosts</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">dcacheClient</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<div>配置SessionState信息：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">sessionState </span><span style="color: red">mode</span><span style="color: blue">=</span>"<span style="color: blue">Custom</span>" <span style="color: red">customProvider</span><span style="color: blue">=</span>"<span style="color: blue">Velocity</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">providers</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">Velocity</span>" 
         <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">System.Data.Caching.SessionStoreProvider,ClientLibrary</span>"
         <span style="color: red">cacheName</span><span style="color: blue">=</span>"<span style="color: blue">default</span>"<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">providers</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">sessionState</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>需要指定使用哪个命名缓存，但是该功能似乎到目前还存在问题，无法测试通过L 
<h2>总结</h2>
<div>本文简单介绍了Velocity的配置模型，以及如何缓存复杂数据类型，对命名缓存分区，为缓存项设置Tag，以及对于ASP.NET SessionState的支持，希望对大家有用。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151964]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Fri, 21 Nov 2008 00:00:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[使用微软分布式缓存服务Velocity Part 1 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>Velocity是微软推出的分布式缓存解决方案，为开发可扩展性，可用的，高性能的应用程提供支持，可以缓存各种类型的数据，如CLR对象、XML、二进制数据等，并且支持集群模式的缓存服务器。Velocity也将集成在.NET Framework 4.0中，本文将介绍Velocity的一些预备知识、安装配置以及开发一个简单的示例。 
<h2>简介</h2>
<div>既然是分布式的缓存平台，客户端应用程序能够与缓存服务器集群中的任何一台服务器通信，并且执行缓存操作，如新增缓存项，移除缓存项等。在Velocity中，提供了一套统一的API，开发者可以使用任何一种.NET语言来访问这些API，如图1所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="384" alt="TerryLee_0212" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0212_3.png" width="580" border="0" /> 
<div>图 1 
<h2>物理模型</h2>
<div>在整个Velocity分布式缓存解决方案中，从物理模型上来看，主要涉及到如下几个元素：缓存宿主，缓存集群，Velocity提供的基于Windows PowerShell的管理工具，对于服务器集群配置的存储。缓存宿主是指一个或者多个以Windows服务形式运行的服务器，每台服务器都可以运行缓存宿主服务；缓存集群是一个或者多个缓存宿主实例的集合；当缓存集群启动时，它将从集群配置存储位置处来获取配置信息，Velocity提供了多种方式的集群配置信息存储，可以基于XML文件、SQL Server数据库或者SQL Server CE等；基于PowerShell的管理工具后面会详细讲到。 如图2所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="365" alt="TerryLee_0213" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0213_3.png" width="564" border="0" />&nbsp; 
<div>图 2 
<h2>逻辑模型</h2>
<div>从逻辑模型上来看，在Velocity中主要有命名缓存，在命名缓存中我们还可以继续分区，命名缓存，可以理解为内存中的一个独立的存储结构单元，它们之间完全互相隔离，互不干扰，当有多个应用程序共享同一个缓存集群时，可以为每个应用程序分别建立命名缓存；在同一个命名缓存中，还可以对命名缓存进行分区，这样即可以解决数据冲突的问题，再配合Velocity中的“标签”功能，可以极大的提高检索效率。如图3所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="387" alt="TerryLee_0216" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0216_3.png" width="519" border="0" />&nbsp;&nbsp; 
<div>图 3 
<h2>安装</h2>
<div>Velocity当前最新的版本是CTP 2，大家可以到微软官方站点下载，由于Velocity中提供了一套基于Windows PowerShell的管理工具，所以在安装之前需要首先安装Windows PowerShell。在安装过程中，其中有一步需要进行服务器集群的配置，如图4所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="415" alt="TerryLee_0214" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0214_3.png" width="544" border="0" /> 
<div>图 4 
<div>需要设置服务及集群端口号，集群配置的存储位置，集群配置存储的Provider，可以基于XML存储或者基于SQL Server CE存储等。另外可以访问如下站点获得一些资源： 
<div>团队博客：<a href="http://blogs.msdn.com/velocity/"><font color="#ff6600">[url]http://blogs.msdn.com/velocity/[/url]</font></a>&nbsp; 
<div>示例代码：<a href="http://code.msdn.microsoft.com/velocity"><font color="#ff6600">[url]http://code.msdn.microsoft.com/velocity[/url]</font></a> 
<div>安装完成后，请在Windows Service中启动Microsoft project code named "Velocity"服务。 
<h2>管理工具</h2>
<div>Velocity提供了基于Windows PowerShell的管理工具，对于Windows PowerShell不熟悉的可以参考《<b><a href="http://www.cnblogs.com/Terrylee/archive/2008/11/09/Windows-PowerShell-Overview.html"><font color="#ff6600">回归Dos操作的快感，进入PowerShell世界</font></a></b>》这篇文章。使用Windows PowerShell可以非常方便的对Velocity缓存集群、缓存宿主等进行管理。使用如下命令金额图对启动、停止、重启服务器集群： <pre class=code>Start-CacheCluster 
Stop-CacheCluster 
Restart-CacheCluster </pre><a href="http://11011.net/software/vspaste"></a>
<div>使用如下命令可以启动、停止缓存宿主、获取命名缓存、获取缓存分区等： <pre class=code>Get-CacheHost 
Get-CacheConfig 
Set-CacheConfig 
Start-CacheHost 
Stop-CacheHost 
Get-CacheStatistics 
Get-Cache 
Get-CacheRegion </pre><a href="http://11011.net/software/vspaste"></a>
<div>如使用Get-CacheHost命令获取缓存宿主的信息，如图5所示，可以看到宿主对应的服务名以及服务状态等： 
<div><img height="273" alt="TerryLee_0217" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0217_3.png" width="580" border="0" /> 
<div>图 5 
<div>使用Get-Cache命名查看所有的命名缓存，如图6所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="273" alt="TerryLee_0218" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0218_3.png" width="580" border="0" /> 
<div>图 6 
<div>使用该管理工具还可以创建、移除命名缓存等，这里不再叙述。 
<h2>简单示例</h2>
<div>经过前面一大堆的理论介绍，现在来看一个最简单的示例。首先要把CacheBaseLibrary和ClientLibrary这两个程序集添加到应用程中，在Velocity安装目录下可以找到，并且引入命名空间： <pre class=code><span style="color: blue">using </span>System.Data.Caching;</pre><a href="http://11011.net/software/vspaste"></a>
<div>在使用Velocity缓存数据时，首先需要创建一个命名缓存，它可以通过CacheFactory来创建，如下代码所示： <pre class=code><span style="color: blue">private </span><span style="color: #2b91af">Cache </span>GetCurrentCache()
{
    <span style="color: #2b91af">Cache </span>dCache;
    <span style="color: #2b91af">ServerEndPoint</span>[] servers = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>[1];
    servers[0] = <span style="color: blue">new </span><span style="color: #2b91af">ServerEndPoint</span>(<span style="color: #a31515">"localhost"</span>, 22233, <span style="color: #a31515">"DistributedCacheService"</span>);
    <span style="color: blue">bool </span>routingClient = <span style="color: blue">true</span>;
    <span style="color: blue">bool </span>localCache = <span style="color: blue">false</span>;
    <span style="color: blue">var </span>factory = <span style="color: blue">new </span><span style="color: #2b91af">CacheFactory</span>(servers, routingClient, localCache);
    dCache = factory.GetCache(<span style="color: #a31515">"default"</span>);
    <span style="color: blue">return </span>dCache;
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>此处首先指定了所有的服务器信息，当然这些都可以放在应用程序配置文件中，将会在下篇中介绍，有了Cache对象，其它的使用就非常方便了，如我们可以使用Add、Put、Remove、Get等方法来对缓存项进行操作， 
<div>添加缓存项： <pre class=code><span style="color: #2b91af">Cache </span>dCache = GetCurrentCache();
<span style="color: #2b91af">String </span>key = keyTextbox.Text;
<span style="color: #2b91af">String </span>val = valueTxtBox.Text;
<span style="color: blue">if </span>(key == <span style="color: #a31515">"" </span>|| val == <span style="color: #a31515">""</span>) <span style="color: blue">return</span>;
dCache.Add(key, val);
statusLabel.Text =
    <span style="color: #2b91af">String</span>.Format(<span style="color: #a31515">"Successfully added key {0} to cache."</span>, key);</pre><a href="http://11011.net/software/vspaste"></a>
<div>获取缓存项： <pre class=code><span style="color: #2b91af">Cache </span>dCache = GetCurrentCache();
<span style="color: #2b91af">String </span>key = keyTextbox.Text;
<span style="color: blue">if </span>(key == <span style="color: #a31515">""</span>) <span style="color: blue">return</span>;
<span style="color: #2b91af">String </span>val = dCache.Get(key).ToString();
valueTxtBox.Text = val;
statusLabel.Text =
    <span style="color: #2b91af">String</span>.Format(<span style="color: #a31515">"Successfully did Get of key {0} from cache"</span>, key);</pre><a href="http://11011.net/software/vspaste"></a>
<div>运行程序可以测试，数据被正确的缓存，如图7所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="334" alt="TerryLee_0219" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/VelocityPart1_149E6/TerryLee_0219_3.png" width="472" border="0" /> 
<div>图 7 
<h2>总结</h2>
<div>本文简单介绍了微软的分布式缓存解决方案Velocity的一些概念以及开发了一个简单的示例，希望对大家有用。在下篇文章中，我们将会更深入学习缓存复杂数据类型以及Velocity的编程模型和配置模型。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151965]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Thu, 20 Nov 2008 00:01:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[Silverlight 3一瞥]]></title>
 <description><![CDATA[<div>今天<a href="http://weblogs.asp.net/scottgu/default.aspx"><font color="#ff6600">ScottGu</font></a>在自己的Blog上对目前正在开发中的Silverlight 3版本的新特性做了一些透露，Silverlight 3的新特性包括视频方面的增强，包括支持H.264 video；图形方面的增强包括3D支持和GPU硬件加速；开发方面的增强包括更加丰富的数据绑定支持和更多的控件。另外，从Silverlight 3起在开发工具方面也会有较大的改进，将会完全支持在Visual Studio或者Visual Web Developer Express中进行Silverlight应用程序的编写和交互设计（这点也是Silverlight 2在Visual Studio 2008中开发最为开发者诟病的一点），另外还会为数据绑定提供可视化工具，类似于ASP.NET中的数据绑定一样，如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="418" alt="TerryLee_0211" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/Silverlight3_14F3D/TerryLee_0211_3.png" width="580" border="0" />&nbsp;</div>
<div>原文请参考：<a href="http://weblogs.asp.net/scottgu/archive/2008/11/16/update-on-silverlight-2-and-a-glimpse-of-silverlight-3.aspx"><font color="#ff6600">Update on Silverlight 2 - and a glimpse of Silverlight 3</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151967]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Tue, 18 Nov 2008 00:01:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（10）：消息处理功能核心]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>WCF是一个通信框架，同时也可以将它看成是一个消息处理或者传递的基础框架，它可以接收消息、对消息做处理，或者根据客户端给定的数据构造消息并将消息发送到目标端点，在这个过程中，一切都是围绕“消息”而展开的。WCF在消息处理体系结构提供统一编程模型的同时，还允许灵活的表示数据和传递消息，本文将介绍如何配置消息支持各个SOAP和WS-Addressing版本或者不用任何SOAP和WS-Addressing，以及如何控制消息状态等。 
<h2>消息契约</h2>
<div>在大多数情况下，开发者只关心数据契约而不必考虑携带这些数据的消息，然而某些特殊情况下，需要完全控制SOAP消息的结构，如提供户操作性，或者控制消息的某一部分的安全性，此时可以使用WCF中提供的编程模型消息契约，它使用一种可直接序列化为所需精确SOAP消息的类型。如果为某一个数据类型定义了消息契约，我们可以完全控制该类型和SOAP消息之间的映射，如下面的代码：<pre class=code>[<span style="color: #2b91af">MessageContract</span>]
<span style="color: blue">public class </span><span style="color: #2b91af">CustomerMessage
</span>{
    [<span style="color: #2b91af">MessageHeader</span>]
    <span style="color: blue">public </span><span style="color: #2b91af">Guid </span>Id { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    [<span style="color: #2b91af">MessageBodyMember</span>]
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>Name { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    [<span style="color: #2b91af">MessageBodyMember</span>]
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>Email { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>此处使用MessageContract特性指定CustomerMessage类型为消息契约，并用MessageHeader指定Id属性在SOAP消息的标头，用MessageBodyMember指定Name、Email作为SOAP消息的正文，如果拦截到SOAP消息，可以看到如下所示：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">s:Envelope </span><span style="color: red">xmlns:s</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.xmlsoap.org/soap/envelope/[/url]</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Action </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"
      <span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.microsoft.com/ws/2005/05/addressing/none[/url]</span>"<span style="color: blue">&gt;
      </span>[url]http://tempuri.org/ICustomerContract/GetCustomerResponse[/url]
    <span style="color: blue">&lt;/</span><span style="color: #a31515">Action</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">h:Id </span><span style="color: red">xmlns:h</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://tempuri.org/[/url]</span>"<span style="color: blue">&gt;
      </span>38097c1d-366d-4c58-84a5-93525766630c
    <span style="color: blue">&lt;/</span><span style="color: #a31515">h:Id</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CustomerMessage </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://tempuri.org/[/url]</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;</span>lhj_cauc[@@AT@@]163.com<span style="color: blue">&lt;/</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;</span>TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">CustomerMessage</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">s:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>当然，还可以在消息契约中使用数组，对消息的部分进行签名和加密等操作以及指定标头和正文部分的命名空间，这些不是本文的重点，将不再阐述。可以看到，消息契约为开发者完全控制SOAP消息和自定义类型之间的映射，提供了一种非常方便的途径。 
<h2>认识Message类型</h2>
<div>绝大多数情况下，我们都不会直接去使用Message类，而是仅仅使用WCF服务编程模型中的数据契约、消息契约来描述输入或者输出消息。但在某些高级应用中，我们需要对Message类进行编程，如需要从别处创建输出消息的内容，而不是序列化.NET Framework类型，如可能从磁盘上的某个文件来创建输出消息，在这种情况下，简单的使用WCF中服务编程模型已经不能满足需要，而需要针对Message类进行编程。 
<div>简单来说，Message类是一个通用的数据容器，在本质上它完全模拟SOAP消息正文以及消息标头和属性的集合，另外Message类中提供了一系列的方法用来创建消息、读写消息正文以及标头和属性的集合。它的定义如下所示：<pre class=code><span style="color: blue">public abstract class </span><span style="color: #2b91af">Message </span>: <span style="color: #2b91af">IDisposable
</span>{
    <span style="color: green">// 标头集合
    </span><span style="color: blue">public abstract </span><span style="color: #2b91af">MessageHeaders </span>Headers { <span style="color: blue">get</span>; }
    <span style="color: blue">protected bool </span>IsDisposed { <span style="color: blue">get</span>; }
    <span style="color: blue">public virtual bool </span>IsEmpty { <span style="color: blue">get</span>; }
    <span style="color: blue">public virtual bool </span>IsFault { <span style="color: blue">get</span>; }
    <span style="color: green">// 属性集合
    </span><span style="color: blue">public abstract </span><span style="color: #2b91af">MessageProperties </span>Properties { <span style="color: blue">get</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">MessageState </span>State { <span style="color: blue">get</span>; }
    <span style="color: green">// 消息版本
    </span><span style="color: blue">public abstract </span><span style="color: #2b91af">MessageVersion </span>Version { <span style="color: blue">get</span>; }
    <span style="color: blue">public void </span>Close();
    <span style="color: blue">public </span><span style="color: #2b91af">MessageBuffer </span>CreateBufferedCopy(<span style="color: blue">int </span>maxBufferSize);
    <span style="color: blue">public static </span><span style="color: #2b91af">Message </span>CreateMessage(<span style="color: #2b91af">MessageVersion </span>version, <span style="color: blue">string </span>action);
    <span style="color: green">// 获取正文
    </span><span style="color: blue">public </span>T GetBody&lt;T&gt;();
    <span style="color: blue">public void </span>WriteBody(XmlWriter writer);
    <span style="color: blue">public void </span>WriteMessage(XmlWriter writer);
    <span style="color: blue">public void </span>WriteStartBody(XmlWriter writer);
    <span style="color: blue">public void </span>WriteStartEnvelope(XmlDictionaryWriter writer);
    <span style="color: green">// 更多成员
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<h2>消息版本</h2>
<div>在创建消息时，一个很重要的部分就是指定消息版本，消息版本标识了消息在传输中使用SOAP和WS-Addressing的版本，即每个消息版本都会由两部分组成，SOAP版本和WS-Addressing版本。在WCF中，支持的SOAP信封版本用EnvelopeVersion类来表示，如下代码：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">EnvelopeVersion
</span>{
    <span style="color: blue">public static </span><span style="color: #2b91af">EnvelopeVersion </span>None { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">EnvelopeVersion </span>Soap11 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">EnvelopeVersion </span>Soap12 { <span style="color: blue">get</span>; }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>None表示在传输中不适用SOAP，即使用传统的XML消息传递方案；Soap11和Soap12分别表示在传输中使用SOAP 1.1版本和SOAP 1.2版本。 
<div>同样，在WCF中支持的WS-Addressing版本用AddressingVersion类来表示，如下代码：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">AddressingVersion
</span>{
    <span style="color: blue">public static </span><span style="color: #2b91af">AddressingVersion </span>None { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">AddressingVersion </span>WSAddressing10 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">AddressingVersion </span>WSAddressingAugust2004 { <span style="color: blue">get</span>; }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>WSAddressingAugust2004表示2004年8月开始提交的WS-Addressing W3C提案，目前得到广泛支持。而WSAddressing10表示最终的WS-Addressing 1.0 W3C推荐标准。 
<div>在创建消息时，我们需要指定消息版本，这个消息版本包括所使用的SOAP和WS-Addressing规范的版本，如下代码所示：<pre class=code><span style="color: #2b91af">MessageVersion </span>version = <span style="color: #2b91af">MessageVersion</span>.CreateVersion
    (<span style="color: #2b91af">EnvelopeVersion</span>.Soap11, <span style="color: #2b91af">AddressingVersion</span>.WSAddressing10);</pre><a href="http://11011.net/software/vspaste"></a>
<div>此外，在MessageVersion中，已经提供了对这两者之间的常见组合，这样我们可以使用而不用考虑两者之间的兼容性等问题，如下代码所示：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">MessageVersion
</span>{
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Default { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>None { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Soap11 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Soap11WSAddressing10 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Soap11WSAddressingAugust2004 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Soap12 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Soap12WSAddressing10 { <span style="color: blue">get</span>; }
    <span style="color: blue">public static </span><span style="color: #2b91af">MessageVersion </span>Soap12WSAddressingAugust2004 { <span style="color: blue">get</span>; }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>我们看看在SOAP消息中，SOAP版本和WS-Addressing版本是如何体现的，创建一个简单的消息，使用的消息版本为Soap11WSAddressing10：<pre class=code><span style="color: blue">public </span><span style="color: #2b91af">Message </span>GetCustomer()
{
    <span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer
    </span>{
        Id = <span style="color: #2b91af">Guid</span>.NewGuid(),
        Name = <span style="color: #a31515">"TerryLee"</span>,
        Email = <span style="color: #a31515">"lhj_cauc[@@AT@@]163.com"
    </span>};
    <span style="color: #2b91af">Message </span>message = <span style="color: #2b91af">Message</span>.CreateMessage(
        <span style="color: #2b91af">MessageVersion</span>.Soap11WSAddressing10,
        <span style="color: #a31515">"http://localhost/CustomerService/GetCustomer"</span>,
        customer);
    <span style="color: blue">return </span>message;
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>可以看到SOAP消息包为如下所示，从命名空间上可以看到使用的SOAP版本为1.1而WS-Addressing为1.0。<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">s:Envelope </span><strong><span style="color: red">xmlns:a</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.w3.org/2005/08/addressing[/url]</span></strong>"
            <strong><span style="color: red">xmlns:s</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.xmlsoap.org/soap/envelope/[/url]</span></strong>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">a:Action </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;
      </span>[url]http://localhost/CustomerService/GetCustomer[/url]
    <span style="color: blue">&lt;/</span><span style="color: #a31515">a:Action</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Customer </span><span style="color: red">xmlns:i</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.w3.org/2001/XMLSchema-instance[/url]</span>"
              <span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.datacontract.org/2004/07/[/url] Data</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;</span>lhj_cauc[@@AT@@]163.com<span style="color: blue">&lt;/</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Id</span><span style="color: blue">&gt;</span>d297aa45-2d9e-4f89-aa41-491507db2a21<span style="color: blue">&lt;/</span><span style="color: #a31515">Id</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;</span>TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Customer</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">s:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>如果修改消息的版本为Soap12WSAddressingAugust2004，可以看到它们命名空间发生的变化：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">s:Envelope </span><span style="color: red">xmlns:a</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.xmlsoap.org/ws/2004/08/addressing[/url]</span>"
            <span style="color: red">xmlns:s</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.w3.org/2003/05/soap-envelope[/url]</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">a:Action </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;
      </span>[url]http://localhost/CustomerService/GetCustomer[/url]
    <span style="color: blue">&lt;/</span><span style="color: #a31515">a:Action</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Customer </span><span style="color: red">xmlns:i</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.w3.org/2001/XMLSchema-instance[/url]</span>"
              <span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.datacontract.org/2004/07/[/url] Data</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;</span>lhj_cauc[@@AT@@]163.com<span style="color: blue">&lt;/</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Id</span><span style="color: blue">&gt;</span>e13bef92-bba2-47c2-954c-ba7bfe472cc2<span style="color: blue">&lt;/</span><span style="color: #a31515">Id</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;</span>TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Customer</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">s:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<h2>终结点配置与消息</h2>
<div>大家都知道终结点的配置由契约、地址和绑定组成，其中契约定义了消息和方法之间的映射，而地址则指定了服务在何处，在绑定中描述了所要使用的传输，消息采用的编码方法以及支持WS-*系列协议，同时还有消息版本，对于每个绑定来说，它所使用的消息编码器和消息版本不尽相同，关于消息编码器将会在后面详细讲述，先来看一下消息版本，如在服务端有如下配置：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>""
          <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">basicHttpBinding</span>"
          <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.MessageHandling.Contract.ICustomerContract</span>"
          <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">defaultBinding</span>"<span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">Other</span>"
          <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
          <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.MessageHandling.Contract.ICustomerContract</span>"
          <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">otherBinding</span>"<span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>我们在宿主端分别输出一下它们所采用的消息版本：<pre class=code><span style="color: blue">foreach </span>(<span style="color: #2b91af">ServiceEndpoint </span>endpoint <span style="color: blue">in </span>host.Description.Endpoints)
{
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Binding:{0}"</span>, endpoint.Binding.Name);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"AddressingVersion:{0}"</span>, 
        endpoint.Binding.MessageVersion.Addressing.ToString());
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"EnvelopeVersion:{0}"</span>,
        endpoint.Binding.MessageVersion.Envelope.ToString());
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"----------------------------\n"</span>);
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>最后结果如下：<pre class=code>Binding:BasicHttpBinding
AddressingVersion:AddressingNone ([url]http://schemas.microsoft.com/ws/2005/05/addres[/url]
sing/none)
EnvelopeVersion:Soap11 ([url]http://schemas.xmlsoap.org/soap/envelope/[/url])
----------------------------
Binding:WSHttpBinding
AddressingVersion:Addressing10 ([url]http://www.w3.org/2005/08/addressing[/url])
EnvelopeVersion:Soap12 ([url]http://www.w3.org/2003/05/soap-envelope[/url])
----------------------------</pre><a href="http://11011.net/software/vspaste"></a>
<div>可以看到，对于BasicHttpBinding来说，它的Addressing版本为None，SOAP版本为Soap11，即MessageVersion为Soap11；而对于WSHttpBinding来说，它的Addressing版本为Addressing10，SOAP版本为Soap12，即MessageVersion为Soap12WSAddressing10。 
<h2>操作消息</h2>
<div>在创建消息时，可以从其它文件写入消息正文，或者把自定义类型序列化到消息正文中。同样我们还可以控制消息的标头和属性，标头将会在SOAP消息中进行传输，所以当中介在检查标头时，必须支持标头使用的协议的基础版本；而属性提供一种与版本更加无关的方式来批注消息。如下面的代码：<pre class=code><span style="color: blue">public </span><span style="color: #2b91af">Message </span>GetCustomer()
{
    <span style="color: #2b91af">Customer </span>customer = <span style="color: blue">new </span><span style="color: #2b91af">Customer
    </span>{
        Name = <span style="color: #a31515">"TerryLee"</span>,
        Email = <span style="color: #a31515">"lhj_cauc[@@AT@@]163.com"
    </span>};
    <span style="color: #2b91af">Message </span>message = <span style="color: #2b91af">Message</span>.CreateMessage(
        <span style="color: #2b91af">MessageVersion</span>.Soap12WSAddressingAugust2004,
        <span style="color: #a31515">"http://localhost/CustomerService/GetCustomer"</span>,
        customer);
    message.Headers.Add(<span style="color: #2b91af">MessageHeader</span>.CreateHeader(
        <span style="color: #a31515">"CustomerID"</span>,
        <span style="color: #a31515">"http://www.cnblogs.com/terrylee"</span>,
        <span style="color: #2b91af">Guid</span>.NewGuid()
        ));
    <span style="color: blue">return </span>message;
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>SOAP消息如下所示，可以看到CustomerID放在SOAP消息标头中：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">s:Envelope </span><span style="color: red">xmlns:a</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.xmlsoap.org/ws/2004/08/addressing[/url]</span>"
            <span style="color: red">xmlns:s</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.w3.org/2003/05/soap-envelope[/url]</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">a:Action </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;
      </span>[url]http://localhost/CustomerService/GetCustomer[/url]
    <span style="color: blue">&lt;/</span><span style="color: #a31515">a:Action</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">CustomerID </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.cnblogs.com/terrylee[/url]</span>"<span style="color: blue">&gt;
      </span>c2f34dd3-d71a-42fa-b3f2-6f58c553c8ee
    <span style="color: blue">&lt;/</span><span style="color: #a31515">CustomerID</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Customer </span><span style="color: red">xmlns:i</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://www.w3.org/2001/XMLSchema-instance[/url]</span>"
              <span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.datacontract.org/2004/07/Data[/url]</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;</span>lhj_cauc[@@AT@@]163.com<span style="color: blue">&lt;/</span><span style="color: #a31515">Email</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Id</span><span style="color: blue">&gt;</span>00000000-0000-0000-0000-000000000000<span style="color: blue">&lt;/</span><span style="color: #a31515">Id</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;</span>TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Name</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Customer</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">s:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<h2>消息状态控制</h2>
<div>在WCF中，Message类的正文对象已经设计为支持流处理，这意味着在Message的生命周期内只能被处理一次。这是通过保持Message对象的当前状态来强制实施的。当Message对象处于Created状态时，可读取/写入/复制该对象，其他状态为 Read、Written 和 Copied，这意味着相应的操作已经执行过一次。Message对象的五种状态定义如下：<pre class=code><span style="color: blue">public enum </span><span style="color: #2b91af">MessageState
</span>{
    Created,
    Read,
    Written,
    Copied,
    Closed,
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>Message对象在开始时处于Created状态，该状态是处理正文的唯一有效状态。处理正文有以下几种不同的方式：可以对其进行读取、写入或复制。调用GetReaderAtBodyContents或 GetBody&lt;T&gt; 可将状态更改为Read。调用WriteMessage或WriteBody可将状态更改为Written。调用 CreateBufferedCopy可将状态更改为Copied，如下图所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="325" alt="TerryLee_WCF_34" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF10_14A77/TerryLee_WCF_34_3.png" width="478" border="0" /> 
<div>如下面的代码：<pre class=code><span style="color: #2b91af">Customer </span>c =  <span style="color: blue">new </span><span style="color: #2b91af">Customer </span>{ 
    Name = <span style="color: #a31515">"TerryLee"</span>,
    Email = <span style="color: #a31515">"lhj_cauc[@@AT@@]163.com"
</span>};
<span style="color: #2b91af">Message </span>message = <span style="color: #2b91af">Message</span>.CreateMessage(
    <span style="color: #2b91af">MessageVersion</span>.Soap12WSAddressingAugust2004,
    <span style="color: #a31515">"http://localhost/CustomerService/GetCustomer"</span>,
    c);
<span style="color: #2b91af">Console</span>.WriteLine(message.State);
<span style="color: #2b91af">Customer </span>c = message.GetBody&lt;<span style="color: #2b91af">Customer</span>&gt;();
<span style="color: #2b91af">Console</span>.WriteLine(message.State);
message.Close();
<span style="color: #2b91af">Console</span>.WriteLine(message.State);</pre><a href="http://11011.net/software/vspaste"></a>
<div>输出的Message状态分别为：<pre class=code>Created
Read
Closed
</pre><a href="http://11011.net/software/vspaste"></a>
<h2>小结</h2>
<div>WCF在消息处理体系结构提供统一编程模型的同时，还允许灵活的表示数据和传递消息。从本文可以看出，它可以配置消息支持各个SOAP和WS-Addressing版本或者不适用任何SOAP和WS-Addressing，这将提供极大的灵活性。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151968]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Mon, 17 Nov 2008 23:46:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（9）：深度通道编程模型Part 2—实例篇 ]]></title>
 <description><![CDATA[<h2>引言</h2>
<div>从本质上说，WCF是一个通信服务框架，它允许我们使用不同的传输协议，使用不同的消息编码形式，跟不同的WS-*系列规范交互，而所有这些细节都是由通道堆栈来处理的。在《<a href="http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html"><font color="#ff6600">WCF专题系列（8）：深度通道编程模型Part 1—设计篇</font></a>》中，对于WCF中的通道模型有了深入的认识，本文中，我将通过实例来说明在通道模型中，服务端是如何接收消息，客户端是如何发送消息的。 
<h2>服务端通道</h2>
<div>本文将不使用WCF的编程模型，而直接利用通道模型来进行通信，这样有助于我们更进一步加深对服务端处理消息的认识，在服务端侦听并接收消息的第一步需要创建绑定，我们既可以使用WCF中内置的绑定或者使用自定义的绑定，如下代码所示，创建一个CustomBinding：<pre class=code><span style="color: green">// 创建自定义绑定
</span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
<span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);</pre><a href="http://11011.net/software/vspaste"></a>
<div>此处添加了HttpTransportBindingElement，所以生成的通道堆栈具有HTTP传输通道，另外采用了文本消息编码器。接下来调用刚才创建的CustomBinding的BuildChannelListener方法来构造通道侦听器，需要指定侦听基地址以及绑定参数，另外调用Open()方法打开通道监听器，相信大家一定还记得Open()方法是在接口ICommunicationObject中定义的，如下代码所示：<pre class=code><span style="color: green">// 使用自定义绑定创建通道侦听器         
</span><span style="color: #2b91af">IChannelListener</span>&lt;<span style="color: #2b91af">IReplyChannel</span>&gt; listener =
      binding.BuildChannelListener&lt;<span style="color: #2b91af">IReplyChannel</span>&gt;(
         <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>),
         <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
<span style="color: green">// 监听消息
</span>listener.Open();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Listening for incoming channel connections"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div>现在侦听传入的消息，由于我们使用请求了响应消息交换模式，此处侦听器返回一个实现了IReplyChannel的通道，为了在此通道上接收消息，我们首先对其调用Open()方法（该方法仍然是在ICommunicationObject中定义），以便将其置于一个准备进行通信的状态。 然后，我们调用ReceiveRequest()方法，它会处于阻止状态，直到消息达到，如下代码所示：<pre class=code><span style="color: green">// 创建Reply通道
</span><span style="color: #2b91af">IReplyChannel </span>channel = listener.AcceptChannel();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel accepted. Listening for messages"</span>);
channel.Open();
<span style="color: #2b91af">RequestContext </span>request = channel.ReceiveRequest();</pre><a href="http://11011.net/software/vspaste"></a>
<div>当ReceiveRequest()方法返回一个RequestContext时，再使用其RequestMessage属性获取接收到的消息。输出消息的操作（Action）和内容。为了发送答复，在此例中创建一个新的答复消息，它会将我们在请求中接收到的字符串数据，添加一段字符后再传递回去。然后，调用Reply()方法以发送答复消息，如下代码所示：<pre class=code><span style="color: green">// 读取请求的消息
</span><span style="color: #2b91af">Message </span>message = request.RequestMessage;
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Received"</span>);
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Action: {0}"</span>, message.Headers.Action);
<span style="color: blue">string </span>body = message.GetBody&lt;<span style="color: blue">string</span>&gt;();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Content: {0}"</span>, body);
<span style="color: green">// 发送响应消息
</span><span style="color: #2b91af">Message </span>replymessage = <span style="color: #2b91af">Message</span>.CreateMessage(
    binding.MessageVersion,
    <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
     <span style="color: #a31515">"Hello : " </span>+ body);
request.Reply(replymessage);</pre><a href="http://11011.net/software/vspaste"></a>
<div>最后别忘了做资源释放工作，关闭通道侦听器、通道、请求消息、请求上下文等，如下代码所示：<pre class=code><span style="color: green">// 释放对象
</span>message.Close();
request.Close();
channel.Close();
listener.Close();</pre><a href="http://11011.net/software/vspaste"></a>
<div>完整的代码如下所示：<pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author:TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url:[url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">static void </span>Main()
{
    <span style="color: green">// 创建自定义绑定
    </span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
    bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
    bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
    <span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);
    <span style="color: green">// 使用自定义绑定创建通道侦听器         
    </span><span style="color: #2b91af">IChannelListener</span>&lt;<span style="color: #2b91af">IReplyChannel</span>&gt; listener =
          binding.BuildChannelListener&lt;<span style="color: #2b91af">IReplyChannel</span>&gt;(
             <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>),
             <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
    <span style="color: green">// 监听消息
    </span>listener.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Listening for incoming channel connections"</span>);
    <span style="color: green">// 创建Reply通道
    </span><span style="color: #2b91af">IReplyChannel </span>channel = listener.AcceptChannel();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel accepted. Listening for messages"</span>);
    channel.Open();
    <span style="color: #2b91af">RequestContext </span>request = channel.ReceiveRequest();
    <span style="color: green">// 读取请求的消息
    </span><span style="color: #2b91af">Message </span>message = request.RequestMessage;
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Received"</span>);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Action: {0}"</span>, message.Headers.Action);
    <span style="color: blue">string </span>body = message.GetBody&lt;<span style="color: blue">string</span>&gt;();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Content: {0}"</span>, body);
    <span style="color: green">// 发送响应消息
    </span><span style="color: #2b91af">Message </span>replymessage = <span style="color: #2b91af">Message</span>.CreateMessage(
        binding.MessageVersion,
        <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
         <span style="color: #a31515">"Hello : " </span>+ body);
    request.Reply(replymessage);
    <span style="color: green">// 释放对象
    </span>message.Close();
    request.Close();
    channel.Close();
    listener.Close();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Press Enter to exit"</span>);
    <span style="color: #2b91af">Console</span>.ReadLine();
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>现在运行服务端如图1所示，由于没有消息到达，所以ReceiveRequest()方法会阻塞： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="236" alt="TerryLee_WCF_31" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_31_3.png" width="561" border="0" /> 
<div>图 1 
<h2>客户端通道</h2>
<div>前面完成了服务端的工作，接下来我们看看如何在客户端直接使用通道模型进行通信。与服务端一致，请求消息的第一步是创建绑定，因为双方需要通过绑定就通信的细节达成一致。创建自定义绑定与服务端一致，如下代码所示：<pre class=code><span style="color: green">// 创建绑定
</span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
<span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);</pre><a href="http://11011.net/software/vspaste"></a>
<div>接下来需要使用刚才创建的绑定来构造通道工厂，在上一篇中我们提到，消息的接收方使用通道侦听器，而消息的请求方使用通道工厂，这次使用BuildChannelFactory()方法构造通道工厂并打开，如下代码所示：<pre class=code><span style="color: green">// 使用绑定创建通道工厂
</span><span style="color: #2b91af">IChannelFactory</span>&lt;<span style="color: #2b91af">IRequestChannel</span>&gt; factory =
binding.BuildChannelFactory&lt;<span style="color: #2b91af">IRequestChannel</span>&gt;(
                 <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
<span style="color: green">// 打开通道工厂
</span>factory.Open();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel factory opened"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div>现在使用通道工厂的CreateChannel()方法来创建IRequestChannel，得到通道后，调用它的Open()方法以使其处于通信就绪状态，如下代码所示：<pre class=code><span style="color: green">// 创建Request通道
</span><span style="color: #2b91af">IRequestChannel </span>channel = factory.CreateChannel(
   <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>));
channel.Open();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Request channel opened"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div>打开通道之后，就可以创建消息并使用通道的 Request()方法发送请求并等待响应，这里我们发送的消息内容是“TerryLee”，当此方法返回时，我们将能够得到回复消息，可以读取该消息以发现终结点回复的内容，如下代码所示：<pre class=code><span style="color: green">// 创建请求消息
</span><span style="color: #2b91af">Message </span>requestmessage = <span style="color: #2b91af">Message</span>.CreateMessage(
    binding.MessageVersion,
    <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
     <span style="color: #a31515">"TerryLee"</span>);
<span style="color: green">// 发送请求消息并接收响应消息
</span><span style="color: #2b91af">Message </span>replymessage = channel.Request(requestmessage);
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply message received"</span>);
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply action: {0}"</span>,
                      replymessage.Headers.Action);
<span style="color: blue">string </span>data = replymessage.GetBody&lt;<span style="color: blue">string</span>&gt;();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply content: {0}"</span>, data);</pre><a href="http://11011.net/software/vspaste"></a>
<div>最后仍然是资源释放工作，关闭通道工厂、通道以及请求消息，如下代码所示：<pre class=code>replymessage.Close();
channel.Close();
factory.Close();</pre><a href="http://11011.net/software/vspaste"></a>
<div>完整的客户端代码为：<pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author:TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url:[url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public static void </span>Main()
{
    <span style="color: green">// 创建绑定
    </span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
    bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
    bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
    <span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);
    <span style="color: green">// 使用绑定创建通道工厂
    </span><span style="color: #2b91af">IChannelFactory</span>&lt;<span style="color: #2b91af">IRequestChannel</span>&gt; factory =
    binding.BuildChannelFactory&lt;<span style="color: #2b91af">IRequestChannel</span>&gt;(
                     <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
    <span style="color: green">// 打开通道工厂
    </span>factory.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel factory opened"</span>);
    <span style="color: green">// 创建Request通道
    </span><span style="color: #2b91af">IRequestChannel </span>channel = factory.CreateChannel(
       <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>));
    channel.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Request channel opened"</span>);
    <span style="color: green">// 创建请求消息
    </span><span style="color: #2b91af">Message </span>requestmessage = <span style="color: #2b91af">Message</span>.CreateMessage(
        binding.MessageVersion,
        <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
         <span style="color: #a31515">"TerryLee"</span>);
    <span style="color: green">// 发送请求消息并接收响应消息
    </span><span style="color: #2b91af">Message </span>replymessage = channel.Request(requestmessage);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply message received"</span>);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply action: {0}"</span>,
                          replymessage.Headers.Action);
    <span style="color: blue">string </span>data = replymessage.GetBody&lt;<span style="color: blue">string</span>&gt;();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply content: {0}"</span>, data);
    replymessage.Close();
    channel.Close();
    factory.Close();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Press Enter to exit"</span>);
    <span style="color: #2b91af">Console</span>.ReadLine();
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>最后运行时服务端如图2所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="266" alt="TerryLee_WCF_33" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_33_3.png" width="580" border="0" />&nbsp; 
<div>图 2 
<div>客户端如图3所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="280" alt="TerryLee_WCF_32" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_32_3.png" width="580" border="0" /> 
<div>图 3 
<h2>温故知新</h2>
<div>现在我们再回顾一下<a href="http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html"><font color="#ff6600">上一篇</font></a>中所讲的知识，通道对象模型是实现通道、通道侦听器和通道工厂所必需的一组核心接口。还提供一些基类以辅助自定义实现。可以看到通道模型中最重要的有三组接口：通道、通道侦听器和通道工厂。每个通道均实现一个或多个接口，称为通道形状接口或通道形状；通道侦听器负责侦听传入消息，即在消息的接收端，然后通过由通道侦听器创建的通道将这些消息传送到上面的层；通道工厂负责创建通道用于发送消息，即在消息的发送方，并在通道工厂关闭时，关闭通道工厂创建的所有通道。如图4所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="381" alt="TerryLee_WCF_24" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_24_3.png" width="494" border="0" /> 
<div>图 4 
<div>对照本文的示例代码，相信大家对于图4能够有更深的认识。 </div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151969]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Fri, 14 Nov 2008 00:22:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（8）：深度通道编程模型Part 1—设计篇 ]]></title>
 <description><![CDATA[<h2>引言</h2>
<div>从本质上说，WCF是一个通信服务框架，它允许我们使用不同的传输协议，使用不同的消息编码形式，跟不同的WS-*系列规范交互，而所有这些细节都是由通道堆栈来处理的。为了简化这些处理，在WCF中提供了两种模型，一是针对开发者的应用程序编程模型；二是用来通信的通道模型，这样对于开发者来说，只要了解应用程序编程模型就足够了，而不会涉及到通道模型，然而，对于通道模型进行必要的学习，可以让我们真正理解WCF中“通信”概念，了解WCF的 整个架构体系，从而构建出更加健壮的WCF服务或者对WCF框架进行扩展。在本文中，我们将进行深度了解WCF中的通道模型是如何设计的。 
<h2>通道模型概述</h2>
<div>在WCF中，提供了一系列的接口和其它类型模型，它们为消息的发送和接收提供了一个底层的编程模型，该模型称之为WCF通道模型。在通道模型中，一个很重要的概念是通道堆栈，它是具有一个或多个消息处理通道的分层的通信堆栈，堆栈中放置了各种类型的通道，用来对象进行处理，如在通道堆栈的最底层放置了传输通道，它负责使通道堆栈适应基础传输，如图1所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="418" alt="TerryLee_WCF_23" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_23_3.png" width="570" border="0" /> 
<div>图1 
<div>在通道堆栈中，不仅仅提供消息的传输方式，还提供了其它诸如对消息的内容或者消息头进行处理的功能，这些功能同样是以通道的方式放置在通道堆栈中，甚至于我们可以编写自己的通道，加入到通道堆栈中。 
<div>消息在通道堆栈中传输时，将作为Message对象流过通信堆栈，如传输通道负责在发送方和接收方之间转换消息，之后消息将通过传输通道继续往上流，依次经过通道堆栈中的各个通道，这些通道各自负责提供一种通信功能，如在消息头中添加信息，对消息的正文进行加密等等。 
<h2>通道对象模型</h2>
<div>通道对象模型是实现通道、通道侦听器和通道工厂所必需的一组核心接口。还提供一些基类以辅助自定义实现。可以看到通道模型中最重要的有三组接口：通道、通道侦听器和通道工厂。每个通道均实现一个或多个接口，称为通道形状接口或通道形状；通道侦听器负责侦听传入消息，即在消息的接收端，然后通过由通道侦听器创建的通道将这些消息传送到上面的层；通道工厂负责创建通道用于发送消息，即在消息的发送方，并在通道工厂关闭时，关闭通道工厂创建的所有通道。 
<div>在通道模型中，最重要的一个接口是ICommunicationObject，它定义了所有通信对象实现的基本状态机的核心接口，自定义通道通信对象可以直接实现ICommunicationObject，如图2所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="381" alt="TerryLee_WCF_24" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_24_3.png" width="494" border="0" /> 
<div>图2 
<div>只有图2中的这些接口，才属于WCF的通道模型，在WCF中同样提供了一些基类如CommunicationObject、ChannelFactoryBase等，在实现自定义的通道通信对象时，也可以直接继承于这些基类，但要注意，这些基类仅仅是为实现自定义通道通信对象提供了方便，它们本身并不属于通道模型的一部分。 
<div>ICommunicationObject接口为WCF中所有面向通信的对象提供了契约，除了通道、通道侦听器、通道工厂外，还有调度程序和服务主机，定义了基本状态的协定。它包括一组用于启动状态转换的打开、关闭和中止方法，打开和关闭方法的异步版本，一组提供状态转换通知的事件和一个个用于检查对象状态的公开State属性，它的定义如下所示：<pre class=code><span style="color: blue">public interface </span><span style="color: #2b91af">ICommunicationObject
</span>{
    <span style="color: green">// 状态属性
    </span><span style="color: #2b91af">CommunicationState </span>State { <span style="color: blue">get</span>; }
    <span style="color: green">// 事件
    </span><span style="color: blue">event </span><span style="color: #2b91af">EventHandler </span>Closed;
    <span style="color: blue">event </span><span style="color: #2b91af">EventHandler </span>Closing;
    <span style="color: blue">event </span><span style="color: #2b91af">EventHandler </span>Faulted;
    <span style="color: blue">event </span><span style="color: #2b91af">EventHandler </span>Opened;
    <span style="color: blue">event </span><span style="color: #2b91af">EventHandler </span>Opening;
    <span style="color: green">// 方法
    </span><span style="color: blue">void </span>Abort();
    <span style="color: blue">void </span>Close();
    <span style="color: blue">void </span>Close(<span style="color: #2b91af">TimeSpan </span>timeout);
    <span style="color: blue">void </span>Open();
    <span style="color: blue">void </span>Open(<span style="color: #2b91af">TimeSpan </span>timeout);
    <span style="color: green">// 异步方法
    </span><span style="color: #2b91af">IAsyncResult </span>BeginClose(<span style="color: #2b91af">AsyncCallback </span>callback, <span style="color: blue">object </span>state);
    <span style="color: #2b91af">IAsyncResult </span>BeginClose(<span style="color: #2b91af">TimeSpan </span>timeout, <span style="color: #2b91af">AsyncCallback </span>callback, <span style="color: blue">object </span>state);
    <span style="color: #2b91af">IAsyncResult </span>BeginOpen(<span style="color: #2b91af">AsyncCallback </span>callback, <span style="color: blue">object </span>state);
    <span style="color: #2b91af">IAsyncResult </span>BeginOpen(<span style="color: #2b91af">TimeSpan </span>timeout, <span style="color: #2b91af">AsyncCallback </span>callback, <span style="color: blue">object </span>state);
    <span style="color: blue">void </span>EndClose(<span style="color: #2b91af">IAsyncResult </span>result);
    <span style="color: blue">void </span>EndOpen(<span style="color: #2b91af">IAsyncResult </span>result);
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>ICommunicationObject 的初始状态是“已创建”，此时可以配置它的各种属性。 一旦处于“已打开”状态，对象就可用于发送和接收消息，但它的属性将视为不可变。 一旦处在“正在关闭”状态，对象就不能再处理新的发送或接收请求，但在到达“关闭”超时前有可能完成现有的请求。 如果发生不可恢复的错误，则对象将转换到“出错”状态，此时可以检查该对象以获取有关错误的信息，该对象最终将关闭。 处于“已关闭”状态时，该对象实质上已到达状态机的终点。 对象一旦从一个状态转换到下一个状态，它将不会返回至前一状态，整个过程图3所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="455" alt="TerryLee_WCF_30" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_30_3.png" width="438" border="0" /> </div>
<div>图 3</div>
<h2>通道形状</h2>
<div>每个通道均实现一个或多个接口，称为通道形状接口或通道形状。通道形状的最底层是 IChannel 接口，该接口提供一个 GetProperty&lt;T&gt; 方法，用作访问由通道堆栈中的通道公开的任意功能的分层机制。扩展 IChannel 的五种通道形状为： 
<div>1.IInputChannel：用于接收消息 
<div>2.IOutputChannel：用于发送消息 
<div>3.IRequestChannel：用于发送请求 
<div>4.IReplyChannel：用于发送回复 
<div>5.IDuplexChannel：用于双向消息传递 
<div>它们之间的关系如图4所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="362" alt="TerryLee_WCF_25" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_25_3.png" width="580" border="0" /> 
<div>图 4 
<div>其实可以看出，IDuplexChannel接口是IInputChannel和IOutputChannel接口的联合，所有的通道形状都同时扩展了ICommunicationObject和IChannel。这5种通道模型分别对应于不同的消息交换模式，在使用数据报模式时，消息发送方通道实现了IOutputChannel接口，而消息接收方通道实现了IInputChannel接口；在请求响应模式中，客户端通道实现IRequestChannel接口，而服务通道实现IReplyChannel接口；在双工通信模式中，由于双方都能发送和接收消息，客户端和服务通道实现了IDuplexChannel接口，如图5所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="285" alt="TerryLee_WCF_29" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_29_3.png" width="580" border="0" /> 
<div>图 5 
<h2>服务端通道</h2>
<div>在通道对象模型中，除了IChannel接口，另外一个接口IChannelListener用于消息的接收端，通过绑定来生成通道侦听器（在绑定中有关于协议、编码和传输的信息，关于绑定可以参考<a href="http://www.cnblogs.com/Terrylee/archive/2008/11/05/WCF-Binding-Overview.html"><font color="#ff6600">WCF专题系列（6）：消息如何传递之绑定Part 1</font></a>），用于侦听传入的消息。通道侦听器负责创建通道并从下面的层或者从网络接收消息，收到的消息将借助于通道侦听器所创建的通道传送到上面的层中。整个过程如图6所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="604" alt="TerryLee_WCF_26" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_26_3.png" width="400" border="0" /> 
<div>图 6 
<div>在WCF的内部，对于消息的每一个处理（即通道堆栈中的通道），都会对应一个内部的通道侦听器，如针对事务处理的TransactionChannelListener和使用TCP传输的TcpChannelListener，分别用于创建各自对应的通道。 
<h2>客户端通道</h2>
<div>在WCF的客户端，通道的创建使用通道工厂，创建的这些通道负责获取来自上一层的消息，对消息进行必要的处理，然后将消息发送到下一层，如图7所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="380" alt="TerryLee_WCF_27" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF8Part1_14687/TerryLee_WCF_27_3.png" width="570" border="0" /> 
<div>图 7 
<div>在WCF内部，同样对于消息的每一个处理，都会有相应的通道工厂，如使用TCP传输的TcpChannelFactory，用于创建对应的通道。 
<h2>总结</h2>
<div>本文详细介绍了WCF中的通道编程模型以及关于通道、通道监听器和通道工厂等，大多数都是纯理论的知识，在下一篇文章中，将会通过一个示例来加深对于本文所讲知识的认识。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151970]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Tue, 11 Nov 2008 22:36:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[回归Dos操作的快感，进入PowerShell世界 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>写下本篇文章源于参加Tech.Ed的一场关于Window PowerShell的课程。虽然之前也经常关注，但从没有亲自体验过。Windows PowerShell 是一种新的命令行外壳和脚本语言，用于进行系统管理和自动化任务，它建立在 .NET Framework 的基础上，可使 IT 专业人员和开发人员控制和自动完成Windows 和应用程序的管理。更为强大之处在于它可以调用.NET Framework中的类库，可以与COM、ADO、XML等交互。在本文中让我们一起来体会一下回归Doc操作的快感，进入强大无比的Windows PowerShell世界。</div>
<div>在Windows PowerShell中包括了：</div>
<div>1. 129 个命令行工具（称为“cmdlet”），用于执行常见系统管理任务，如管理服务、进程、事件日志、证书、注册表以及使用 Windows Management Instrumentation (WMI)。</div>
<div>2. 采用标准命名约定和通用参数的命令行工具，易于掌握和使用；以及用于对数据和对象进行排序、筛选以及格式设置的简便工具。</div>
<div>3. 对现有脚本语言、现有命令行工具以及多种 Windows 版本的支持，其中包括 Windows XP、Windows Server 2003、Windows Vista 以及 Windows Server 2008。</div>
<div>4. 方便的功能，使用户能够浏览数据存储（如注册表和证书存储），就像面对文件系统一样。</div>
<div>5. 用于管理位于不同存储中以及采用不同格式的 Windows 数据的标准实用程序，这些数据包括 Active Directory (ADSI)、Windows Management Instrumentation (WMI)、组件对象模型 (COM) 对象、ActiveX 数据对象 (ADO)、HTML 和 XML。</div>
<div>6. 在命令行进行的高级表达式分析和 .NET 对象处理，其中包括对对象进行流水线处理以帮助提高 IT 专业人员的工作效率。</div>
<div>7. 可扩展的接口，使独立软件供应商和企业开发人员能够构建自定义 cmdlet 以满足特有的应用程序和系统管理要求。</div>
<h2>简单示例</h2>
<div>在开始之前，先来看一个简单的示例，在.NET中获取当前系统所有进程的一段代码：</div><pre class=code><span style="color: blue">static void </span>Main(<span style="color: blue">string</span>[] args)
{
    <span style="color: #2b91af">Process</span>[] proceses = <span style="color: #2b91af">Process</span>.GetProcesses();
    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>item <span style="color: blue">in </span>proceses)
    {
        <span style="color: #2b91af">Console</span>.WriteLine(item.ProcessName);
    }
    <span style="color: #2b91af">Console</span>.ReadLine();
}</pre>
<div><a href="http://11011.net/software/vspaste"></a>非常简单的一段代码，直接获取所有进程并显示出它们的名称，如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="235" alt="TerryLee_0203" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0203_3.png" width="576" border="0" /> </div>
<div>在安装完Windows PowerShell之后，可以看到它的界面与常用的命令行界面非常相似。现在再使用Windows PowerShell来获取一下当前系统所有的进程，只有一个命令就可以完成：</div><pre class=code>Get-Process</pre><a href="http://11011.net/software/vspaste"></a>
<div>输出如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="334" alt="TerryLee_0204" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0204_3.png" width="580" border="0" />&nbsp; </div>
<h2>PowerShell命令</h2>
<div>在Windows PowerShell中，内置了129个命令供我们使用，这些命令称之为“Cmdlet”。除了很多在Dos中的命令继续可以使用之外，还有PowerShell内置的一些命令。每个命令由两部分组成，前半部分表示动作，后半部分表示动作的标的，如Get-Help、Get-Command、Write-Host等。在Windows PowerShell中输入命令时，不需要输入全部名称，可以只输入其中几个关键字，PowerShell会自动匹配，如只输入get-he，然后按下“Tab”键，屏幕上就可以出现完整的Get-Help命令。</div>
<div>Get-Help、Get-Command是PowerShell中非常重要的两个命令，可以获取帮助和获取所有的命令列表，如输入：</div><pre class=code>Get-Command</pre><a href="http://11011.net/software/vspaste"></a>
<div>结果如下图所示，列出了所有的命令：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="302" alt="TerryLee_0209" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0209_3.png" width="580" border="0" /> </div>
<h2>与.NET Framework交互</h2>
<div>Windows PowerShell更强大的地方在于它可以访问.NET Framework的类库，我们可以使用New-Object命令来创建一个.NET&nbsp; Framework中的类实例，并保存在变量中，如下面的命令：</div><pre class=code>$d = New-Object -TypeName System.DateTime</pre><a href="http://11011.net/software/vspaste"></a>
<div>这里使用New-Object来创建一个DateTime对象，使用-TypeName指定类型名称，创建的对象保存在$d变量中，输出结果如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="246" alt="TerryLee_0205" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0205_3.png" width="580" border="0" /> </div>
<div>除此之外，还可以使用-ArgumentList来指定参数，如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="220" alt="TerryLee_0206" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0206_3.png" width="580" border="0" />&nbsp;</div>
<h2>与COM交互</h2>
<div>使用Windows PowerShell还可以完全与COM交互，这使的Windows PowerShell的功能更加强大，有了上面前面提到的访问WMI、与.NET Framework交互，再加上与COM交互，可以说Windows PowerShell几乎无所不能。如下面看一个例子，使用PowerShell来访问IE，可以使用如下命令来创建一个IE的对象，并让它导航到博客园首页：</div><pre class=code>$ie = New-Object -ComObject InternetExplorer.Application
$ie.Visible = $<span style="color: blue">true
</span>$ie.Navigate(<span style="color: #a31515">"http://www.cnblogs.com"</span>)
$ie.Quit()</pre>
<div><a href="http://11011.net/software/vspaste"></a>简单解释一下这段代码，首先创建一个IE的COM对象，并让它显示，然后导航到博客园首页，最后程序退出。如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="246" alt="TerryLee_0207" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0207_6.png" width="580" border="0" />&nbsp; </div>
<div>在这个过程中，大家会看到系统打开了一个IE窗口，并且导航到了博客园。</div>
<h2>访问注册表</h2>
<div>除此之外，Windows PowerShell还可以实现对注册表的完全控制，包括查询所有的Entry，或者修改、删除键值等，可以说是一切皆可控制，如使用下面的命令：</div><pre class=code>Get-ChildItem -Path hkcu:\</pre><a href="http://11011.net/software/vspaste"></a>
<div>输出如下图所示，列出了HKEY_CURRENT_USER下面的信息：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="302" alt="TerryLee_0208" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0208_3.png" width="580" border="0" /> </div>
<h2>创建别名</h2>
<div>在Windows PowerShell中，还允许为命令创建自己熟悉的别名，这样对于某些太长的命令名可以使用自己的缩写来表示，或者对于某些不太容易记忆的命令，使用自己喜欢的名字来表示。</div><pre class=code>Set-Alias gh Get-Help</pre>
<div><a href="http://11011.net/software/vspaste"></a>这里设置gh为Get-Help命令的别名，这样在后面的操作中，当输入gh后，执行的命名就是Get-Help，如下图所示：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="302" alt="TerryLee_0210" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/DosWindowsPowerShell_13DDB/TerryLee_0210_3.png" width="580" border="0" />&nbsp;</div>
<h2>输出文件</h2>
<div>在Windows PowerShell中，我们还可以把操作的结果输出到一个文件中，可以使用Out-File命令，另外可以使用-FilePath来指定输出的路径和文件名，如下命令所示：</div><pre class=code>Get-Process | Out-File -FilePath C:\temp.txt</pre>
<div>现在打开C盘的temp.txt文件，可以看到输出的结果如下所示：</div><pre class=code>Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName 
-------  ------    -----      ----- -----   ------     -- ----------- 
    126       4    13272      10220    47            1204 audiodg
     73       4     2936       8080    61     1.05   3580 conime
    512       5     2188       4112    59     2.06    532 csrss
    511       7     5704      19744   182    93.44    588 csrss
   1249     109   127144     157128   561    44.67   6648 devenv 
    188       8    47088      73332   164 2,020.61   2508 dwm 
   2261      48    75040      72600   416   341.38   2548 explorer
      0       0        0         24     0               0 Idle  
    664      28    36696      49076   173    14.78   3384 iexplore
    969      35    74868      87576   328    43.92   7480 iexplore
    404      10     7280        640    96     6.23   2812 kavstart 
     65       3     1368       3360    46     0.09    316 kissvc
     80       5     6592       1012    62     1.28    496 kmailmon</pre><a href="http://11011.net/software/vspaste"></a>
<div>以上所介绍只是Windows PowerShell强大功能的冰山之一角，除此之外，还可以与WMI交互，访问机器设备，对于输出结果格式化等等，这里不再介绍。</div>
<h2>总结</h2>
<div>本文中简单介绍了一下Windows PowerShell，相信通过这些介绍大家已经看到了Windows PowerShell的强大之处，而且在微软以后的产品中，都会支持使用PowerShell进行管理。 </div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151972]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[网络技术]]></category>
 <pubdate><![CDATA[Sun, 09 Nov 2008 01:23:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（7）：消息如何传递之绑定Part 2 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>每个服务终结点都包含一个地址Address、一个绑定Binding 和一个契约Contract。契约指定可用的操作，绑定指定如何与服务进行通信，而地址指定查找服务的位置，在WCF专题系列前5篇中，深入了解了WCF中寻址的细节。本文为消息如何传递之绑定第二部分，将详细介绍WCF内置的各种绑定元素，绑定元素之间的顺序以及如何创建一个自定义的绑定元素。 
<div>在<a href="http://www.cnblogs.com/Terrylee/archive/2008/11/05/WCF-Binding-Overview.html"><font color="#ff6600">WCF专题系列（6）：消息如何传递之绑定Part 1</font></a>一文中，我提到绑定由绑定元素组成，每个绑定元素用来描述终结点与客户端通信方式中的某个方面，在发送或接收消息时，每个绑定元素都表示一个处理步骤；运行时，绑定元素会创建必要的通道和侦听器，用以生成传出和传入通道堆栈，其中三种主要的绑定元素是协议绑定元素，编码绑定元素以及传输绑定元素，下面再对它们重新认识一下。 
<h2>协议绑定元素</h2>
<div>这些元素表示对消息执行的更高级别的处理步骤，如可靠性、安全性、事务等处理，由这些绑定元素创建的通道和侦听器可以添加、移除或修改消息内容，以符合WS-*系列规范，给定的绑定可以具有0或多个协议绑定元素，WCF中内置的几种协议绑定元素，其中包括： 
<div><b>1.ReliableSessionBindingElement</b>：该绑定元素会在堆栈中提供一个可选层，该可选层可在终结点之间建立可靠会话并配置此会话的行为。所谓的可靠性，是指SOAP消息可以在不可靠的网络上（如HTTP）进行可靠的传递，保证消息无重复的、消息次序正确的进行交换，它的原理是：为一组消息设定相同的ID，根据消息号将消息编组，并根据顺序号进行排序，大家可以参考WS-Reliability和WS-ReliableMessaging协议。它的定义如下所示：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">ReliableSessionBindingElement
    </span>: <span style="color: #2b91af">BindingElement</span>, <span style="color: #2b91af">IPolicyExportExtension
</span>{
    <span style="color: blue">public bool </span>Ordered { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">ReliableMessagingVersion </span>ReliableMessagingVersion { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: green">// 更多成员
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<div>WCF中内置的几个绑定已经包含了ReliableSessionBindingElement，如果要添加该元素到其它绑定上，可以使用如下配置：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">customBinding</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">binding </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">reliabilityhttp</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">reliableSession</span><span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">binding</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">customBinding</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div><b>2.SecurityBindingElement</b>：该绑定元素为WCF中SOAP消息安全绑定元素的基类，它有三种具体的实现：支持对称加密通道安全的SymmetricSecurityBindingElement、支持不对称加密通道安全的AsymmetricSecurityBindingElement 和 支持混合模式通道安全的TransportSecurityBindingElement，如下图所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="287" alt="TerryLee_WCF_21" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF7Part2_14EC1/TerryLee_WCF_21_3.png" width="578" border="0" /> 
<div>这些实现为在WS-Security Policy规范中定义的绑定建模，在创建自定义绑定中，我们需要提供SecurityBindingElement的某一个具体的实现，或者自定义一个类从SecurityBindingElement继承。 
<div><b>3. </b><b>TransactionFlowBindingElement</b>：该绑定元素允许在终结点绑定设置中启用或禁用传入事务流，并允许指定传入事务所需的协议格式。它的定义如下所示：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">TransactionFlowBindingElement
    </span>: <span style="color: #2b91af">BindingElement</span>, <span style="color: #2b91af">IPolicyExportExtension
</span>{
    <span style="color: blue">public </span><span style="color: #2b91af">TransactionProtocol </span>TransactionProtocol { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: green">// 更多成员
</span>}
</pre><a href="http://11011.net/software/vspaste"></a>
<div>在补充的Web服务规范中，有一系列的关于事务处理的规范，如WS-AtomicTransactions、WS-Coordination等等。 
<h2>编码绑定元素</h2>
<div>所谓的编码是将消息转换为一个字节序列的过程，而解码是相反的过程。编码绑定元素表示消息与准备用于网络传输的编码之间的转换，典型的WCF绑定正好包括一个编码绑定元素。WCF内置的编码绑定元素包括 MtomMessageEncodingBindingElement、BinaryMessageEncodingBindingElement 和 TextMessageEncodingBindingElement。 如果未对绑定指定编码绑定元素，则使用默认的编码。当传输协议是HTTP时，默认编码为文本，对于其他传输协议，默认编码为二进制。如下图所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="295" alt="TerryLee_WCF_22" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF7Part2_14EC1/TerryLee_WCF_22_3.png" width="580" border="0" /> 
<div><b>1. </b><b>TextMessageEncodingBindingElement</b>：表示文本方式编码的XML消息编码器，它的优点是互操作性最强，缺点是效率最低。WCF服务或者客户端通常可以理解文本XML。但是，将大型二进制数据块作为文本传输不是有效的传输方式，它的定义如下所示：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">TextMessageEncodingBindingElement
    </span>: <span style="color: #2b91af">MessageEncodingBindingElement</span>, <span style="color: #2b91af">IWsdlExportExtension</span>, <span style="color: #2b91af">IPolicyExportExtension
</span>{
    <span style="color: blue">public int </span>MaxReadPoolSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public int </span>MaxWritePoolSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public override </span><span style="color: #2b91af">MessageVersion </span>MessageVersion { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">Encoding </span>WriteEncoding { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public override </span><span style="color: #2b91af">MessageEncoderFactory </span>CreateMessageEncoderFactory();
    <span style="color: green">// 更多成员
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<div><b>2.BinaryMessageEncodingBindingElement</b><b>：</b>是指定在编码消息时应该使用二进制XML格式的绑定元素，它包含用于指定要使用何种字符编码以及SOAP消息与 WS-Addressing版本的选项。二进制编码的优点是效率最高，缺点是互操作性最低，它的定义如下所示：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">BinaryMessageEncodingBindingElement
    </span>: <span style="color: #2b91af">MessageEncodingBindingElement</span>,
    <span style="color: #2b91af">IWsdlExportExtension</span>, <span style="color: #2b91af">IPolicyExportExtension
</span>{
    <span style="color: blue">public int </span>MaxReadPoolSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public int </span>MaxSessionSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public int </span>MaxWritePoolSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public override </span><span style="color: #2b91af">MessageVersion </span>MessageVersion { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public override </span><span style="color: #2b91af">MessageEncoderFactory </span>CreateMessageEncoderFactory();
    <span style="color: green">// 更多成员
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<div><b>3.MtomMessageEncodingBindingElement</b><b>：</b>表示指定使用消息传输优化机制 (MTOM) 编码的消息所用的字符编码和消息版本管理以及其他设置的绑定元素。(MTOM) 是WCF消息中传输二进制数据的有效技术。MTOM 编码器会尝试在效率和互操作性之间建立平衡。MTOM 编码以文本形式传输大多数 XML，但通过按原样传输来优化大型二进制数据块的传输，无需将其转换为base64编码格式。它的定义如下所示：<pre class=code><span style="color: blue">public sealed class </span><span style="color: #2b91af">MtomMessageEncodingBindingElement
    </span>: <span style="color: #2b91af">MessageEncodingBindingElement</span>,
    <span style="color: #2b91af">IWsdlExportExtension</span>, <span style="color: #2b91af">IPolicyExportExtension
</span>{
    <span style="color: blue">public int </span>MaxBufferSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public int </span>MaxReadPoolSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public int </span>MaxWritePoolSize { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public override </span><span style="color: #2b91af">MessageVersion </span>MessageVersion { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public </span><span style="color: #2b91af">Encoding </span>WriteEncoding { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    <span style="color: blue">public override </span><span style="color: #2b91af">MessageEncoderFactory </span>CreateMessageEncoderFactory();
    <span style="color: green">// 更多成员
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<div>如果以上编码不能满足实际的开发需求，我们还可以定义自己的消息编码器，在后面的文章中，我将会详细介绍。 
<h2>传输绑定元素</h2>
<div>这些元素表示传输协议上编码消息的传输。典型的WCF绑定正好包括一个从 TransportBindingElement 继承的传输绑定元素。WCF中内置的传输绑定元素有如下几种：<pre class=code>TcpTransportBindingElement 
HttpTransportBindingElement 
HttpsTransportBindingElement 
NamedPipeTransportBindingElement 
PeerTransportBindingElement 
MsmqTransportBindingElement 
MsmqIntegrationBindingElement 
ConnectionOrientedTransportBindingElement</pre><a href="http://11011.net/software/vspaste"></a>
<div>除此之外，还可以用户自定义的传输绑定元素。 
<h2>绑定元素顺序</h2>
<div>在创建绑定时，向绑定中添加绑定元素的顺序非常重要，必须按照如下顺序进行： 
<div>1.最顶层是一个允许流事务的TransactionFlowBindingElement元素，可选； 
<div>2.接下来是一个可靠性支持的ReliableSessionBindingElement元素，可选； 
<div>3.接下来是一个安全性支持的SecurityBindingElement元素，可选； 
<div>4.在接下来是消息编码绑定元素，可以是系统内置的三种消息编码器之一或者自定义的消息编码器，必须具有，但是如果不添加，系统会根据传输不同默认添加一个消息编码器； 
<div>5.最底层是一个传输绑定元素，可以是系统内置的几种传输绑定元素之一或者自定义的传输绑定元素。 
<div>6.如果是自定义的绑定元素，根据绑定元素的功能可以放在以上几层任意层之间。 
<div>如下面的示例代码，创建一个自定义的绑定，并向其中添加三个绑定元素：<pre class=code><span style="color: green">// 可靠性支持
</span><span style="color: #2b91af">ReliableSessionBindingElement </span>reliable =
    <span style="color: blue">new </span><span style="color: #2b91af">ReliableSessionBindingElement</span>();
reliable.Ordered = <span style="color: blue">false</span>;
<span style="color: green">// 编码元素
</span><span style="color: #2b91af">TextMessageEncodingBindingElement </span>text =
    <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
text.MessageVersion = <span style="color: #2b91af">MessageVersion</span>.Soap11WSAddressingAugust2004;
<span style="color: green">// 传输元素
</span><span style="color: #2b91af">HttpTransportBindingElement </span>http = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
http.TransferMode = <span style="color: #2b91af">TransferMode</span>.Streamed;
http.UseDefaultWebProxy = <span style="color: blue">true</span>;
<span style="color: green">// 自定义绑定
</span><span style="color: #2b91af">CustomBinding </span>httpBinding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>();
httpBinding.Name = <span style="color: #a31515">"httpBinding"</span>;
httpBinding.Elements.Add(reliable);
httpBinding.Elements.Add(text);
httpBinding.Elements.Add(http);
host.AddServiceEndpoint(<span style="color: blue">typeof</span>(<span style="color: #2b91af">ICalculator</span>), httpBinding,
    <span style="color: #a31515">"http://localhost:8887/Calculator"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<h2>自定义绑定元素</h2>
<div>当在构造一个新的绑定时，如果系统内置的绑定元素无法满足需要，可以开发一个自定义的绑定元素，如自定义的消息绑定元素、自定义的传输绑定元素或者任意一个绑定元素。关于消息绑定元素的自定义，我将在后面消息编码器一文中进行介绍，而自定义传输绑定元素，也是一个相当负责工作，需要创建相应的自定义通道组件，所以将会放在介绍完WCF中通道模型之后再详细讲解。总的来说，实现一个自定义的绑定元素，需要继承于抽象的基类BindingElement，如下面的代码片段：<pre class=code><span style="color: blue">public class </span><span style="color: #2b91af">LoggingBindingElement </span>: <span style="color: #2b91af">BindingElement
</span>{
    <span style="color: blue">public </span>LoggingBindingElement()
    {
    }
    <span style="color: blue">public </span>LoggingBindingElement(<span style="color: #2b91af">LoggingBindingElement </span>other)
        : <span style="color: blue">base</span>(other)
    {
    }
    <span style="color: blue">public override </span><span style="color: #2b91af">BindingElement </span>Clone()
    {
        <span style="color: blue">return new </span><span style="color: #2b91af">LoggingBindingElement</span>(<span style="color: blue">this</span>);
    }
    <span style="color: blue">public override </span>T GetProperty&lt;T&gt;(<span style="color: #2b91af">BindingContext </span>context)
    {
        <span style="color: blue">if </span>(context == <span style="color: blue">null</span>)
        {
            <span style="color: blue">throw new </span><span style="color: #2b91af">ArgumentNullException</span>(<span style="color: #a31515">"context"</span>);
        }
        <span style="color: blue">return </span>context.GetInnerProperty&lt;T&gt;();
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>在后面的文章将会看到一个完整的自定义绑定元素的例子。 
<h2>总结</h2>
<div>本文为消息如何传递之绑定第二部分，详细介绍了WCF内置的各种绑定元素，绑定元素之间的顺序以及如何创建一个自定义的绑定元素。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151978]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Thu, 06 Nov 2008 23:56:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（6）：消息如何传递之绑定Part 1 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>每个服务终结点都包含一个地址Address、一个绑定Binding 和一个契约Contract。契约指定可用的操作，绑定指定如何与服务进行通信，而地址指定查找服务的位置，在WCF专题系列前5篇中，深入了解了WCF中寻址的细节；从本文开始，将深入了解经典“ABC”中的B，即绑定Binding，了解它的原理，如何使用绑定通信以及在元数据中如何公开 
<h2>什么是绑定</h2>
<div>从本质上说，WCF是一个通信服务框架，它允许我们使用不同的传输协议（如Http、Https、TCP、P2P、IPC和MSMQ等），使用不同的消息编码形式（文本、二进制和MTOM），跟不同的WS-*系列规范（如WS-Security、WS-Atomic Transaction等）交互。所有这些细节都是由通道堆栈来处理的，看一下Aaron Skonnard给出的这幅图： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="430" alt="TerryLee_WCF_19" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF6Part1_13DF0/TerryLee_WCF_19_3.png" width="482" border="0" /> 
<div>图1 
<div>最底层传输组件读入消息，消息编码器将传入字节读取为逻辑消息对象，之后消息通过通道堆栈中的各个消息，它们执行各自的处理。如果对这三者之间之间进行组合，至少可以得到上千种不同的通信方式，但是这些传输、编码以及协议之间有些是互斥的，有些相互约束，也就是说，对于开发人员来说，每构建一个服务，都要需要考虑这三者之间是否可以共存，是否是高效的通信方式，显然这个工作是非常复杂的，要求开发者必须了解所有的传输、编码以及协议等。 
<div>为了简化这三者之间的管理，WCF中引入了绑定的概念（Binding），每个绑定中都封装了传输协议、消息编码和多种协议的集合，这样在构建服务时，我们就可以直接选择一个适用的绑定，通过调整它们的属性来适应需求，如果系统内置的绑定通过调整属性仍然不能达到我们的要求，这时才会考虑自定义绑定。这样，通过绑定，就把应用程序编程模型与通道模型（后面会有专门的文章写到）关联了起来，对于开发者来说，就无需再考虑复杂的底层通道模型，直接使用应用程序编程模型。 
<h2>绑定元素</h2>
<div>在WCF中，绑定由绑定元素组成，每个绑定元素用来描述终结点与客户端通信方式中的某个方面，绑定元素继承于BindingElement，其中最重要的绑定元素有如下三种： 
<div>1.编码绑定元素（Encoding Binding Element）：如采用文本、二进制还是MTOM的方式； 
<div>2.传输绑定元素（Transport Binding Element）：使用Http、TCP或者MSMQ进行传输； 
<div>3.协议绑定元素（Protocol Binding Element）：指定可靠性、安全性、事务等。 
<div>每个绑定必须要有一个编码绑定元素和一个传输绑定元素，以及包括任意数目的其他协议绑定元素。 
<h2>通道模型中使用绑定</h2>
<div>在WCF中，提供了两个层面的模型，一是针对开发人员的应用程序编程模型；二是用于通信的通道模型（后面会专门讲到）。在通道模型编程中，服务端侦听并接收消息的第一步就是创建绑定，如下面的代码： <pre class=code><span style="color: green">// 创建自定义绑定
</span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
<span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);</pre><a href="http://11011.net/software/vspaste"></a>
<div>这里创建了一个自定义绑定，并在其中加入了两个必须的绑定元素，消息编码采用文本的方式，而传输绑定元素采用了内置的HttpTransportBindingElement。接下来就可以使用自定义的绑定来创建通道侦听器，并进行消息的侦听，如下代码所示： <pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author:TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url:[url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
/// &lt;param name="args"&gt;&lt;/param&gt;
</span><span style="color: blue">static void </span>Main(<span style="color: blue">string</span>[] args)
{
    <span style="color: green">// 创建自定义绑定
    </span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
    bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
    bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();
    <span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);
    <span style="color: green">// 使用自定义绑定创建通道侦听器         
    </span><span style="color: #2b91af">IChannelListener</span>&lt;<span style="color: #2b91af">IReplyChannel</span>&gt; listener =
          binding.BuildChannelListener&lt;<span style="color: #2b91af">IReplyChannel</span>&gt;(
             <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8080/ChannelApp"</span>),
             <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
    <span style="color: green">// 监听消息
    </span>listener.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Listening for incoming channel connections"</span>);
    <span style="color: #2b91af">IReplyChannel </span>channel = listener.AcceptChannel();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel accepted. Listening for messages"</span>);
    channel.Open();
    <span style="color: blue">while </span>(<span style="color: blue">true</span>)
    {
        <span style="color: #2b91af">RequestContext </span>request = channel.ReceiveRequest();
        <span style="color: green">// 读取请求的消息
        </span><span style="color: #2b91af">Message </span>message = request.RequestMessage;
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Received"</span>);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Action: {0}"</span>, message.Headers.Action);
        <span style="color: blue">string </span>body = message.GetBody&lt;<span style="color: blue">string</span>&gt;();
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Content: {0}"</span>, body);
        <span style="color: green">// 发送响应消息
        </span><span style="color: #2b91af">Message </span>replymessage = <span style="color: #2b91af">Message</span>.CreateMessage(
            binding.MessageVersion,
            <span style="color: #a31515">"http://www.cnblogs.com/terrylee"</span>,
             body);
        request.Reply(replymessage);
        <span style="color: green">// 释放对象
        </span>message.Close();
        request.Close();
        channel.Close();
        listener.Close();
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>其中的代码我们就不再解释，到关于WCF中通道编程模型一文中，还会进行详细的讲解。 
<h2>自定义系统绑定</h2>
<div>在WCF中，已经内置了大量的绑定供我们使用，但是如果这些绑定不能满足实际的开发需求，我们可以通过几种办法来对系统内置绑定进行自定义，一是通过配置文件进行绑定的配置，如下代码所示，配置BasicHttpBinding的消息编码为MTOM，而安全性为消息级别： <pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
           <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/Calculator[/url]</span>"<span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>""
              <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">basicHttpBinding</span>"
              <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"
              <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">defaultBinding</span>"
              <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">myBindingConfiguration</span>"<span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">basicHttpBinding</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">binding </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">myBindingConfiguration</span>"
             <span style="color: red">messageEncoding</span><span style="color: blue">=</span>"<span style="color: blue">Mtom</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">security </span><span style="color: red">mode</span><span style="color: blue">=</span>"<span style="color: blue">Message</span>"<span style="color: blue">&gt;&lt;/</span><span style="color: #a31515">security</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">binding</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">basicHttpBinding</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>二是可以通过编码的方式，如下代码所示： <pre class=code><span style="color: #2b91af">BasicHttpBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">BasicHttpBinding</span>();
binding.Security.Message.ClientCredentialType = 
    <span style="color: #2b91af">BasicHttpMessageCredentialType</span>.Certificate;
binding.Security.Mode = <span style="color: #2b91af">BasicHttpSecurityMode</span>.Message;
binding.MessageEncoding = <span style="color: #2b91af">WSMessageEncoding</span>.Mtom;</pre><a href="http://11011.net/software/vspaste"></a>
<div>考虑到程序部署之后的修改，还是推荐使用配置的方式。同时，我们完全可以利用系统内置绑定创建一个自定义的绑定，或者我们在自定义绑定过程中，可以直接通过已有的系统内置绑定来创建一个绑定元素集合，如下代码所示： <pre class=code><span style="color: #2b91af">BasicHttpBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">BasicHttpBinding</span>();
binding.Security.Message.ClientCredentialType = 
    <span style="color: #2b91af">BasicHttpMessageCredentialType</span>.Certificate;
binding.Security.Mode = <span style="color: #2b91af">BasicHttpSecurityMode</span>.Message;
binding.MessageEncoding = <span style="color: #2b91af">WSMessageEncoding</span>.Mtom;
<span style="color: #2b91af">CustomBinding </span>mybinding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(binding);
<span style="color: #2b91af">BindingElementCollection </span>myElements =
    binding.CreateBindingElements();</pre><a href="http://11011.net/software/vspaste"></a>
<div>在下篇文章中，我将会介绍如何完全重新进行自定义绑定。 
<h2>元数据中公开绑定</h2>
<div>在WCF中，通信的双方应该就通信的细节达成一致，既然绑定中封装了所有通信的细节，而服务端唯一公开这些细节的方式就是元数据，所以绑定的相关信息应该通过公开WSDL和 WS-Policy 形式的元数据，这样服务就可以和客户端共享绑定配置，以BasicHttpBinding为例，它所使用的传输是Http，而消息编码采用文本的方式，如有下面这样一端配置： <pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
           <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/Calculator[/url]</span>"<span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>"
              <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">basicHttpBinding</span>"
              <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"
              <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">defaultBinding</span>"
              <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">myBindingConfiguration</span>"<span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">basicHttpBinding</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">binding </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">myBindingConfiguration</span>"
             <span style="color: red">messageEncoding</span><span style="color: blue">=</span>"<span style="color: blue">Mtom</span>"<span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">binding</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">basicHttpBinding</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">bindings</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>通过绑定配置，设置BasicHttpBinding的消息编码为MTOM，在元数据中，可以看到采用Http进行传输： <pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">wsdl:binding </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">defaultBinding</span>" <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">tns:ICalculator</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsp:PolicyReference </span><span style="color: red">URI</span><span style="color: blue">=</span>"<span style="color: blue">#defaultBinding_policy</span>" <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">soap:binding </span><span style="color: red">transport</span><span style="color: blue">=</span>"<span style="color: blue"><strong>[url]http://schemas.xmlsoap.org/soap/http[/url]</strong></span>" <span style="color: blue">/&gt;
  &lt;</span><span style="color: #a31515">wsdl:operation </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">Add</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">soap:operation </span><span style="color: red">soapAction</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://tempuri.org/ICalculator/Add[/url]</span>"
                    <span style="color: red">style</span><span style="color: blue">=</span>"<span style="color: blue">document</span>" <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">wsdl:input</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">soap:body </span><span style="color: red">use</span><span style="color: blue">=</span>"<span style="color: blue">literal</span>" <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">wsdl:input</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">wsdl:output</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">soap:body </span><span style="color: red">use</span><span style="color: blue">=</span>"<span style="color: blue">literal</span>" <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">wsdl:output</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">wsdl:operation</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsdl:binding</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>对于消息编码MTOM，放在Policy的配置中，如下代码所示： <pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">wsp:Policy </span><span style="color: red">wsu:Id</span><span style="color: blue">=</span>"<span style="color: blue">defaultBinding_policy</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsp:ExactlyOne</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">wsp:All</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsoma:OptimizedMimeSerialization
        </span><span style="color: red">xmlns:wsoma</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization[/url]</span>" <span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">wsp:All</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">wsp:ExactlyOne</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsp:Policy</span><span style="color: blue">&gt;</span></pre>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151979]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Wed, 05 Nov 2008 22:44:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[.NET Framework 4.0海报 ]]></title>
 <description><![CDATA[<div>在PDC 2008大会上，微软发布了一款非常漂亮的.NET Framework 4.0海报，在海报中展示了.NET Framework 3.5 SP1和.NET Framework 4中新添加的功能。同时还使用Silverlight 2技术开发了一个Deep Zoom的版本，可以在线预览，另外也可以下载PDF版本收藏。 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="365" alt="TerryLee_0202" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/.NETFramework4.0_692/TerryLee_0202_3.png" width="541" border="0" /> 
<div><a href="http://tinyurl.com/DotNetFramework4PosterDeepZoom"><font color="#ff6600">Deep Zoom在线版</font></a> 
<div><a href="http://tinyurl.com/PDC2008-NETFX4PDF"><font color="#ff6600">下载PDF版本</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151952]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[.Net]]></category>
 <pubdate><![CDATA[Fri, 31 Oct 2008 00:44:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（5）：深入WCF寻址Part 5—逻辑地址和物理地址 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>在WCF中，每个服务终结点都与两个地址相关联，一个逻辑地址和一个物理地址，逻辑地址就是SOAP消息的目标地址，即前面不止一次提到的“To”地址，而物理地址是WCF侦听器真正监听的地址。在WCF中，逻辑地址称之为终结点地址Endpoint Address，而物理地址则称之为监听地址ListenUri。 
<div>本文将详细介绍WCF中的物理地址和逻辑地址，以及如何使用tcpTrace来进行SOAP消息的跟踪。 
<h2>两种地址</h2>
<div>WCF中，物理地址负责使用特定的传输协议在特定的位置接收传入的消息，除非特别指定，否则逻辑地址将被用来做物理地址，换句话说，在以前我们对于终结点所配置的EndpointAddress都是指定了逻辑地址，如我们的服务端配置如下：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService1[/url]</span>"
          <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
          <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService2[/url]</span>"
          <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">basicHttpBinding</span>"
          <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>现在我们输出一下，就可以看到两个地址是同样的值，如下代码所示：<pre class=code><span style="color: blue">using </span>(<span style="color: #2b91af">ServiceHost </span>calculatorServiceHost =
        <span style="color: blue">new </span><span style="color: #2b91af">ServiceHost</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">CalculatorService</span>)))
{
    calculatorServiceHost.Opened += <span style="color: blue">delegate
    </span>{
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Service begin to listen via the Address:{0}"</span>,
            calculatorServiceHost.BaseAddresses[0].ToString());
    };
    calculatorServiceHost.Open();
    <span style="color: blue">foreach </span>(<span style="color: #2b91af">ServiceEndpoint </span>se <span style="color: blue">in </span>calculatorServiceHost.Description.Endpoints)
    {
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Endpoint details:"</span>);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Logical address: \t{0}"</span>, se.Address);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Physical address: \t{0}"</span>, se.ListenUri);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Binding: \t{0}"</span>, se.Binding.Name);
        <span style="color: #2b91af">Console</span>.WriteLine();
    }
    <span style="color: #2b91af">Console</span>.Read();
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>输出结果如图1所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="276" alt="TerryLee_WCF_13" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF5WCFPart5_A/TerryLee_WCF_13_3.png" width="580" border="0" /> 
<div>图1 
<h2>设定物理地址</h2>
<div>前面我们输出的结果逻辑地址和物理地址是相同的，我们可以通过代码或者配置文件来设定终结点的物理地址。<pre class=code><span style="color: #2b91af">WSHttpBinding </span>wsbinding = <span style="color: blue">new </span><span style="color: #2b91af">WSHttpBinding</span>();
calculatorServiceHost.AddServiceEndpoint(
    <span style="color: blue">typeof</span>(<span style="color: #2b91af">ICalculator</span>),
    wsbinding,
    <span style="color: #a31515">"urn:calcservice"</span>,  <span style="color: green">// 逻辑地址
    </span><span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/CalculatorService"</span>)  <span style="color: green">// 物理地址
</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<div>又或者通过配置文件来设置ListenUri，如下代码所示：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">urn:calcservice</span>"
          <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
          <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"
          <span style="color: red">listenUri</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>"
          <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">securityBinding</span>"<span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>这里我们只需要注意的是在指定物理地址时，仍然可以使用相对地址，这一点与设置逻辑地址时是一样的。 
<h2>工作原理</h2>
<div>现在思考一个核心的问题，当我们定义了终结点后，在WSDL中包含的是每个终结点的逻辑地址，而非物理地址，如下代码片段：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">wsdl:service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">CalculatorService</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsdl:port </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">WSHttpBinding_ICalculator</span>" <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">tns:WSHttpBinding_ICalculator</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">soap12:address </span><span style="color: red">location</span><span style="color: blue">=</span>"<span style="color: blue">urn:calcservice</span>" <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;</span>urn:calcservice<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">wsdl:port</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsdl:service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>如果物理地址与逻辑地址相同的，就不会有任何问题，但是客户端如何与一个配置了不同物理地址的服务进行交互？因为客户端并不关心服务端是否配置了不同的物理地址，它只知道每个终结点有一个唯一的终结点地址，只需要跟该地址交互即可，该地址也将作为SOAP消息放在“To”标头中。 
<div>这时我们需要有一个特殊机制，来通知客户端要使用的物理地址，然后客户端通过物理地址传送外发消息，就如同它是路由器或者某种类型的中介一样，可以通过ClientViaBehavior来实现这一点，如下代码所示：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">urn:calcservice</span>"
              <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
              <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"
              <span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">defualtEndpoint</span>"
              <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorEndpointBehavior</span>"
              <span style="color: red">bindingConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">securityBinding</span>"<span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">behavior </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">calculatorEndpointBehavior</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">clientVia </span><span style="color: red">viaUri</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>" <span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">behavior</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>此时客户端将通过与服务终结点相同的物理地址（<a href="http://localhost:8887/CalculatorService"><font color="#ff6600">[url]http://localhost:8887/CalculatorService[/url]</font></a>）向外传送消息而不是通过“urn:calcservice”，但请注意，在SOAP消息“To”标头中包含的仍然是逻辑地址，如图2所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="220" alt="TerryLee_WCF_14" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF5WCFPart5_A/TerryLee_WCF_14_3.png" width="580" border="0" /> 
<div>图2 
<div>看到上面这幅图，可能大家还有一个疑问，逻辑地址起什么作用呢？别忘了我们前面讲到的消息筛选，当消息到达时，ChannelDispatcher 查询每个相关的 EndpointDispatcher 对象以确定终结点是否可以接受消息，以及将该消息传递到可以接受消息的终结点。当消息的目标地址（To标头中的地址）与 AddressFilter 属性相匹配并且消息操作与 ContractFilter 属性相匹配时，EndpointDispatcher 对象负责处理来自 ChannelDispatcher 的消息。 
<h2>物理地址模式</h2>
<div>了解了物理地址和逻辑地址之间的关系，我们再看一下在设置监听地址时的两种模式，通过ListenUriMode枚举来指定，它定义了两个枚举值： 
<div><b>Explicit</b>：完全原样使用 ListenUri，默认值。 
<div><b>Unique</b>：指定传输是否应使用特定传输机制，以确保 ListenUri 是唯一的 
<div>根据传输所采用的协议不同，WCF会采用不同的策略来保证ListenUri唯一，具体的策略如下所示： 
<div>1.非TCP传输，在ListenUri的末尾附加一个GUID。 
<div>2.对于独占模式下的 TCP（PortSharingEnabled 为 false），绑定到一个唯一可用端口号。 
<div>3.对于端口共享模式下的 TCP（PortSharingEnabled 为 true），在ListenUri的末尾附加一个GUID。 
<h2>TcpTrace消息截获</h2>
<div>前面讲了这么多物理地址和逻辑地址，它们最重要的使用地方就是做路由。我们常用tcpTrace来做SOAP消息跟踪，它正是利用这一点技术，在客户端配置ClientViaBehavior，指向tcpTrace的侦听地址，然后tcpTrace在对消息做记录后再转发到服务端，如在服务端的配置如下，它的物理地址和逻辑是相同的：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
         <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/Calculator[/url]</span>"<span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>客户端的配置，这里“[url]http://localhost:8887/CalculatorService[/url]”是真正的服务地址（逻辑地址），我们通过ClientViaBehavior告诉客户端物理地址是“[url]http://localhost:8080/CalculatorService[/url]”，事实上处于该物理地址的服务并不存在，该地址是tcpTrace的监听地址： <pre class=code><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>"<span style="color: blue">1.0</span>" <span style="color: red">encoding</span><span style="color: blue">=</span>"<span style="color: blue">utf-8</span>" <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>"
                <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
                <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"
                <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorEndpointBehavior</span>"<span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">behavior </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">calculatorEndpointBehavior</span>"<span style="color: blue">&gt;
          &lt;</span><span style="color: #a31515">clientVia </span><span style="color: red">viaUri</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8080/CalculatorService[/url]</span>" <span style="color: blue">/&gt;
        &lt;/</span><span style="color: #a31515">behavior</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>tcpTrace的配置如图3所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="223" alt="TerryLee_WCF_16" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF5WCFPart5_A/TerryLee_WCF_16_3.png" width="458" border="0" /> 
<div>图3 
<div>这里tcpTrace监听的端口号就是我们在客户端配置的物理地址端口号，而分发地址才是服务的真正地址，最终可以看到截获的消息，如图4所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="423" alt="TerryLee_WCF_17" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF5WCFPart5_A/TerryLee_WCF_17_3.png" width="580" border="0" /> 
<div>图4 
<div>如果不在客户端配置ClientViaBehavior，利用物理地址和逻辑地址的知识，我们还可以有另外一种方式使用tcpTrace。前面我说过，逻辑地址是包含在WSDL中，所以对于客户端来说知道的是逻辑地址，它会向该地址发送消息，这样我们可以配置终结点的逻辑地址为tcpTrace侦听的地址，而为服务端指定另外一个物理地址，并配置tcpTrace向该物理地址转发消息，如服务端的配置如下：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
         <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8080/Calculator[/url]</span>"<span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"
            <span style="color: red">listenUri</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8080/CalculatorService[/url]</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>而客户端则不用再配置ClientViaBehavior，如下代码所示：<pre class=code><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>"<span style="color: blue">1.0</span>" <span style="color: red">encoding</span><span style="color: blue">=</span>"<span style="color: blue">utf-8</span>" <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/CalculatorService[/url]</span>"
                <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
                <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">client</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>现在“[url]http://localhost:8887/CalculatorService[/url]”是逻辑地址，配置tcpTrace监听该地址，并向服务的物理地址“[url]http://localhost:8080/CalculatorService[/url]”转发消息，如图5所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="222" alt="TerryLee_WCF_18" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF5WCFPart5_A/TerryLee_WCF_18_3.png" width="460" border="0" /> 
<div>图5 
<div>可以看到，利用物理地址和逻辑地址的知识，可以轻松的实现路由，当然tcpTrace只是路由中非常简单的一种使用，后面我们还会讲到更加复杂的应用。 
<h2>结束语</h2>
<div>本文详细介绍了WCF中的物理地址和逻辑地址，它的相关原理以及如何使用tcpTrace来实现SOAP消息的跟踪。关于WCF寻址相关文章： 
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html"><font color="#ff6600">WCF专题系列（4）：深入WCF寻址Part 4—自定义消息筛选器</font></a> 
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html"><font color="#ff6600">WCF专题系列（3）：深入WCF寻址Part 3—消息过滤引擎</font></a> 
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/26/WCF-Addressing-part2.html"><font color="#ff6600">WCF专题系列（2）：深入WCF寻址Part 2—自定义寻址报头</font></a> 
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/25/WCF-addressing-part1.html"><font color="#ff6600">WCF专题系列（1）：深入WCF寻址Part 1—Web服务寻址规范</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151946]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Fri, 31 Oct 2008 00:16:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[WCF后传系列（4）：深入WCF寻址Part 4—自定义消息筛选器 ]]></title>
 <description><![CDATA[<h2>概述</h2>
<div>在<a href="http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html"><font color="#ff6600">WCF专题系列（3）：深入WCF寻址Part 3—消息过滤引擎</font></a>一文中，详细介绍了WCF中的消息筛选引擎，包括消息筛选器和筛选器表，每个EndpointDispatcher都包含了两个消息筛选器，默认的地址过滤器是EndpointAddressMessageFilter，默认的契约过滤器是ActionMessageFilter，这些是可以通过Behavior来改变的。本文我们将学习如何创建一个自定义的消息过滤器，并通过自定义Behavior来改变EndpointDispatcher的默认过滤器。 
<h2>自定义过滤器</h2>
<div>在默认情况下，默认情况下，仅当消息的“To”标头为终结点的 EndpointAddress 并且消息的动作与终结点操作的动作之一匹配时，终结点的消息筛选器才与此消息匹配。在本文中，我们将自定义一个消息过滤器，它不要求消息的“To”标头完全与EndpointAddress完全匹配，而只是检测SOAP消息中的“To”标头中是否包含某些特定的字符。所有的消息过滤器都从MessageFilter基类继承，如下代码所示：<pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author: TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url: [url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public class </span><span style="color: #2b91af">SpecialCharactersMessageFilter </span>: <span style="color: #2b91af">MessageFilter
</span>{
    <span style="color: blue">private </span><span style="color: #2b91af">String </span>_characters = <span style="color: #2b91af">String</span>.Empty;
    <span style="color: blue">public </span>SpecialCharactersMessageFilter(<span style="color: blue">string </span>characters)
    {
        <span style="color: blue">this</span>._characters = characters;
    }
    <span style="color: blue">public override bool </span>Match(<span style="color: #2b91af">Message </span>message)
    {
        <span style="color: #2b91af">Uri </span>to = message.Headers.To;
        <span style="color: blue">if </span>(to == <span style="color: blue">null</span>)
            <span style="color: blue">return false</span>;
        <span style="color: blue">return </span>to.AbsoluteUri.Contains(_characters);
    }
    <span style="color: blue">public override bool </span>Match(<span style="color: #2b91af">MessageBuffer </span>buffer)
    {
        <span style="color: blue">return </span>Match(buffer.CreateMessage());
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>SpecialCharactersMessageFilter的实现非常简单，仅仅是查找“To”标头是否包含某些特定字符，这些字符我们会在配置文件中进行配置。 
<h2>定义EndpointBehavior</h2>
<div>现在我们自定义一个EndpointBehavior，使用它来替换EndpointDispatcher上的地址过滤器和契约过滤器，它实现自IendpointBehavior接口，如下代码所示：<pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author: TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url: [url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public class </span><span style="color: #2b91af">FilteringEndpointBehavior </span>: <span style="color: #2b91af">IEndpointBehavior
</span>{
    <span style="color: #2b91af">MessageFilter </span>addressFilter;
    <span style="color: #2b91af">MessageFilter </span>contractFilter;
    <span style="color: blue">public </span>FilteringEndpointBehavior(<span style="color: #2b91af">MessageFilter </span>addressFilter, 
        <span style="color: #2b91af">MessageFilter </span>contractFilter)
    {
        <span style="color: blue">this</span>.addressFilter = addressFilter;
        <span style="color: blue">this</span>.contractFilter = contractFilter;
    }
    <span style="color: blue">public void </span>AddBindingParameters(<span style="color: #2b91af">ServiceEndpoint </span>endpoint, 
        <span style="color: #2b91af">BindingParameterCollection </span>bindingParameters)
    {
        
    }
    <span style="color: blue">public void </span>ApplyClientBehavior(<span style="color: #2b91af">ServiceEndpoint </span>endpoint, 
        <span style="color: #2b91af">ClientRuntime </span>clientRuntime)
    {
        <span style="color: blue">throw new </span><span style="color: #2b91af">InvalidOperationException</span>(
            <span style="color: #a31515">"This behavior should only be used on the server."</span>);
    }
    <span style="color: blue">public void </span>ApplyDispatchBehavior(<span style="color: #2b91af">ServiceEndpoint </span>endpoint, 
        <span style="color: #2b91af">EndpointDispatcher </span>endpointDispatcher)
    {
        endpointDispatcher.AddressFilter = <span style="color: blue">this</span>.addressFilter;
        endpointDispatcher.ContractFilter = <span style="color: blue">this</span>.contractFilter;
    }
    <span style="color: blue">public void </span>Validate(<span style="color: #2b91af">ServiceEndpoint </span>endpoint)
    {
        
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>这里只是实现了ApplyDispatchBehavior方法，其它方法暂时先不用考虑，另外，由于该Behavior只是用在服务端，所以在ApplyClientBehavior方法中抛出一个异常。 
<h2>定义行为扩展</h2>
<div>接下来定义一个行为扩展元素，这里定义了一个Characters的属性，用来在配置文件中指定消息过滤器中用到的特殊字符，如下代码所示：<pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author: TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url: [url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public class </span><span style="color: #2b91af">FilteringEndpointBehaviorExtension
    </span>: <span style="color: #2b91af">BehaviorExtensionElement
</span>{
    <span style="color: blue">protected override object </span>CreateBehavior()
    {
        <span style="color: #2b91af">MessageFilter </span>addressFilter = 
            <span style="color: blue">new </span><span style="color: #2b91af">SpecialCharactersMessageFilter</span>(Characters);
        <span style="color: #2b91af">MessageFilter </span>contractFilter = 
            <span style="color: blue">new </span><span style="color: #2b91af">MatchAllMessageFilter</span>();
        <span style="color: blue">return new </span><span style="color: #2b91af">FilteringEndpointBehavior</span>(addressFilter, contractFilter);
    }
    <span style="color: blue">public override </span><span style="color: #2b91af">Type </span>BehaviorType
    {
        <span style="color: blue">get 
        </span>{ 
            <span style="color: blue">return typeof</span>(<span style="color: #2b91af">FilteringEndpointBehavior</span>);
        }
    }
    [<span style="color: #2b91af">ConfigurationProperty</span>(<span style="color: #a31515">"characters"</span>, 
        DefaultValue = <span style="color: #a31515">"terrylee"</span>, IsRequired = <span style="color: blue">true</span>)]
    <span style="color: blue">public </span><span style="color: #2b91af">String </span>Characters
    {
        <span style="color: blue">get </span>{
            <span style="color: blue">return base</span>[<span style="color: #a31515">"characters"</span>].ToString(); 
        }
        <span style="color: blue">set </span>{ 
            <span style="color: blue">base</span>[<span style="color: #a31515">"characters"</span>] = <span style="color: blue">value</span>; 
        }
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<h2>配置服务</h2>
<div>定义一个简单的服务契约以及服务的实现，代码如下，不再多说：<pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author: TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url: [url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span>[<span style="color: #2b91af">ServiceContract</span>(Namespace = <span style="color: #a31515">"http://www.cnblogs.com/terrylee/"</span>)]
<span style="color: blue">public interface </span><span style="color: #2b91af">IEchoService
</span>{
    [<span style="color: #2b91af">OperationContract</span>]
    <span style="color: blue">string </span>Echo(<span style="color: blue">string </span>msg);
}
<span style="color: blue">public class </span><span style="color: #2b91af">EchoService </span>: <span style="color: #2b91af">IEchoService
</span>{
    <span style="color: blue">public string </span>Echo(<span style="color: blue">string </span>msg)
    {
        <span style="color: blue">return </span><span style="color: #a31515">"Hello:" </span>+ msg;
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>现在来看一下服务端的配置，除了必须的终结点配置之外，为服务注册一个新的Behavior，代码如下所示：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">extensions</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">behaviorExtensions</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">add </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">filteringEndpointBehavior</span>" 
         <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.CustomizeMessageFilter.Service.
         FilteringEndpointBehaviorExtension, Service, 
         Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</span>" <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">behaviorExtensions</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">extensions</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>创建EndpointBehavior配置：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">behavior </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">filterBehavior</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">filteringEndpointBehavior </span><span style="color: red">characters</span><span style="color: blue">=</span>"<span style="color: blue">terrylee</span>" <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">behavior</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>服务终结点使用behaviorConfiguration：<pre class=code><span style="color: blue">&lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>""
          <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
          <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.CustomizeMessageFilter.Service.IEchoService</span>"
          <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">filterBehavior</span>"<span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>最终完整的配置文件：<pre class=code><span style="color: blue">&lt;?</span><span style="color: #a31515">xml </span><span style="color: red">version</span><span style="color: blue">=</span>"<span style="color: blue">1.0</span>" <span style="color: red">encoding</span><span style="color: blue">=</span>"<span style="color: blue">utf-8</span>" <span style="color: blue">?&gt;
&lt;</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.CustomizeMessageFilter.Service.EchoService</span>"
               <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">echoBehavior</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
          &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">[url]http://localhost:8887/EchoService[/url]</span>"<span style="color: blue">/&gt;
          &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>""
                  <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
                  <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.CustomizeMessageFilter.Service.IEchoService</span>"
                  <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">filterBehavior</span>"<span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">services</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">extensions</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">behaviorExtensions</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">add </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">filteringEndpointBehavior</span>" 
             <span style="color: red">type</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.CustomizeMessageFilter.Service.
             FilteringEndpointBehaviorExtension, Service, 
             Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</span>" <span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">behaviorExtensions</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">extensions</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">serviceBehaviors</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">behavior </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">echoBehavior</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">serviceMetadata </span><span style="color: red">httpGetEnabled</span><span style="color: blue">=</span>"<span style="color: blue">true</span>"<span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">behavior</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">serviceBehaviors</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">behavior </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">filterBehavior</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">filteringEndpointBehavior </span><span style="color: red">characters</span><span style="color: blue">=</span>"<span style="color: blue">terrylee</span>" <span style="color: blue">/&gt;
      &lt;/</span><span style="color: #a31515">behavior</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">endpointBehaviors</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">behaviors</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">system.serviceModel</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">configuration</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<div>至此服务端配置完成，根据配置，只有SOAP消息“To”标头中包含有“terrylee”的字符时，此时终结点的消息过滤器才与此消息匹配。现在在控制台中输出一下，看看针对配置的终结点它所使用的地址过滤器和契约过滤器分别是什么，如图1所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="251" alt="TerryLee_WCF_10" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF4WCFPart4_14375/TerryLee_WCF_10_3.png" width="580" border="0" /> 
<div>图1 
<div>可以看到，终结点所用的地址过滤器不再是默认的EndpointAddressMessageFilter，而是我们自定义的SpecialCharactersMessageFilter。 
<h2>客户端测试</h2>
<div>通过上面的配置，我们知道，只有SOAP消息的“To”标头中带有“terrylee”字符，消息才会被分发到相应的终结点上。现在编写一个简单的测试客户端程序，如下代码所示： <pre class=code><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author: TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url: [url]http://www.cnblogs.com/terrylee[/url]
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">static void </span>Main()
{
    <span style="color: #2b91af">Uri </span>serviceVia = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/EchoService"</span>);
    <span style="color: #2b91af">WSHttpBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">WSHttpBinding</span>();
    <span style="color: #2b91af">ChannelFactory</span>&lt;<span style="color: #2b91af">IEchoService</span>&gt; factory = <span style="color: blue">new </span><span style="color: #2b91af">ChannelFactory</span>&lt;<span style="color: #2b91af">IEchoService</span>&gt;
        (binding, <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(serviceVia));
    <span style="color: #2b91af">String </span>address = <span style="color: #a31515">"http://localhost/terrylee"</span>;
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #2b91af">String</span>.Format(<span style="color: #a31515">"Sending message to {0}..."</span>, address));
    <span style="color: #2b91af">IEchoService </span>channel = factory.CreateChannel(
        <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(address), serviceVia);
    <span style="color: blue">try
    </span>{
        <span style="color: #2b91af">String </span>reply = channel.Echo(<span style="color: #a31515">"cnblogs"</span>);
        <span style="color: #2b91af">Console</span>.WriteLine(reply.ToString());
        ((<span style="color: #2b91af">IClientChannel</span>)channel).Close();
    }
    <span style="color: blue">catch </span>(<span style="color: #2b91af">CommunicationException </span>ce)
    {
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Exception: {0}"</span>, ce.Message);
        ((<span style="color: #2b91af">IClientChannel</span>)channel).Abort();
    }
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Press &lt;ENTER&gt; to terminate client."</span>);
    <span style="color: #2b91af">Console</span>.ReadLine();
}</pre><a href="http://11011.net/software/vspaste"></a>
<div>由于定义了终结点的逻辑地址为“[url]http://localhost/terrylee[/url]”，符合我们上面所讲的条件，可以看到输出结果如图2所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="230" alt="TerryLee_WCF_11" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF4WCFPart4_14375/TerryLee_WCF_11_3.png" width="580" border="0" />&nbsp;&nbsp; 
<div>图2 
<div>可以看到，服务正确的返回我们想要的消息，但是如果修改一下address为“[url]http://localhost/anytao[/url]”，由于没有包含特定的字符“terrylee”，服务端将返回错误的信息：<pre class=code><span style="color: #2b91af">String </span>address = "<span style="color: #a31515"><a href="http://localhost/anytao"><font color="#ff6600">[url]http://localhost/anytao[/url]</font></a>"</span>;</pre><a href="http://11011.net/software/vspaste"></a>
<div>输出结果如图3所示： 
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="225" alt="TerryLee_WCF_12" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/WCF4WCFPart4_14375/TerryLee_WCF_12_6.png" width="580" border="0" /> 
<div>图3 
<h2>结束语</h2>
<div>本文我介绍了如何自定义消息筛选器，以及如何通过Behavior来修改EndpointDispatcher的默认过滤器，消息过滤是消息分发过程中非常重要的一个环节，也是WCF寻址中一个重要的部分，希望对于大家有所帮助。 WCF相关文章：</div>
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html"><font color="#ff6600">WCF专题系列（5）：深入WCF寻址Part 5—逻辑地址和物理地址</font></a> </div>
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html"><font color="#ff6600">WCF专题系列（3）：深入WCF寻址Part 3—消息过滤引擎</font></a> </div>
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/26/WCF-Addressing-part2.html"><font color="#ff6600">WCF专题系列（2）：深入WCF寻址Part 2—自定义寻址报头</font></a> </div>
<div><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/25/WCF-addressing-part1.html"><font color="#ff6600">WCF专题系列（1）：深入WCF寻址Part 1—Web服务寻址规范</font></a></div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151945]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Thu, 30 Oct 2008 00:44:00 +0000]]></pubdate>
</item>
<item>
 <title><![CDATA[Silverlight Toolkit预览Part 1：介绍 ]]></title>
 <description><![CDATA[<h2>什么是Silverlight Toolkit</h2>
<div>Silverlight Toolkit是由微软提供的一系列的Silverlight控件、组件和工具的集合，不仅免费且完全开源，当前发布的版本中包括12个控件和6套非常酷的主题样式，覆盖的范围包括图表、样式、布局以及用户输入，效果预览：</div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="222" alt="TerryLee_Silverlight_001" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/SilverlightToolkitPart0_1412/TerryLee_Silverlight_001_3.png" width="358" border="0" /> </div>
<div><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="222" alt="TerryLee_Silverlight_002" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/SilverlightToolkitPart0_1412/TerryLee_Silverlight_002_3.png" width="358" border="0" /> </div>
<h2>包含的控件</h2>
<div>当前发布的版本中，包含的控件较为稳定的有如下6个：</div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#TreeView"><font color="#ff6600">TreeView</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#DockPanel"><font color="#ff6600">DockPanel</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#WrapPanel"><font color="#ff6600">WrapPanel</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20November%202008%20overview&amp;referringTitle=Home&amp;ANCHOR#Label"><font color="#ff6600">Label</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#HeaderedContentControl"><font color="#ff6600">HeaderedContentControl</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#HeaderedItemsControl"><font color="#ff6600">HeaderedItemsControl</font></a></b></div>
<div>处于预览的控件有如下6个：</div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#AutoCompleteBox"><font color="#ff6600">AutoCompleteBox</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#NumericUpDown"><font color="#ff6600">NumericUpDown</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#Viewbox"><font color="#ff6600">Viewbox</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%201&amp;referringTitle=Home&amp;ANCHOR#Expander"><font color="#ff6600">Expander</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#ImplicitStyleManager"><font color="#ff6600">ImplicitStyleManager</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%202&amp;referringTitle=Home"><font color="#ff6600">Charting</font></a></b></div>
<div><font color="#ff6600"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="298" alt="TerryLee_Silverlight_003" src="http://images.cnblogs.com/cnblogs_com/Terrylee/WindowsLiveWriter/SilverlightToolkitPart0_1412/TerryLee_Silverlight_003_3.png" width="434" border="0" /></font> </div>
<div>除此之外，还提供了6套非常专业的主题样式，分别为：</div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#ExpressionDarkTheme"><font color="#ff6600">Expression Dark</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#ExpressionLightTheme"><font color="#ff6600">Expression Light</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#RainierPurpleTheme"><font color="#ff6600">Rainier Purple</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#RainierOrangeTheme"><font color="#ff6600">Rainier Orange</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#ShinyBlueTheme"><font color="#ff6600">Shiny Blue</font></a></b></div>
<div><b><a href="http://www.codeplex.com/Silverlight/Wiki/View.aspx?title=Silverlight%20Toolkit%20Overview%20Part%203&amp;referringTitle=Home&amp;ANCHOR#ShinyRedTheme"><font color="#ff6600">Shiny Red</font></a></b></div>
<h2>相关说明</h2>
<div>Silverlight Toolkit微软已经在Codeplex上开源，地址为：</div>
<div><a title="http://www.codeplex.com/Silverlight" href="http://www.codeplex.com/Silverlight"><font color="#ff6600">[url]http://www.codeplex.com/Silverlight[/url]</font></a></div>
<div>大家可以到这里去下载，并参考相关的说明文档。</div>]]></description>
 <link><![CDATA[http://terrylee.blog.51cto.com/342737/151942]]></link>
 <author><![CDATA[lihuijun]]></author>
 <category><![CDATA[开发技术]]></category>
 <pubdate><![CDATA[Wed, 29 Oct 2008 02:06:00 +0000]]></pubdate>
</item>
</channel></rss>