<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[木瓜帐篷·木瓜和草莓]]></title>
<link>http://www.donhwa.com.cn/</link>
<description><![CDATA[木瓜公公和草莓婆婆……]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog3 v2.8]]></copyright>
<webMaster><![CDATA[donhwa@126.com(南院木瓜)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>木瓜帐篷·木瓜和草莓</title>
	<url>http://www.donhwa.com.cn/images/logos.gif</url>
	<link>http://www.donhwa.com.cn/</link>
	<description>木瓜帐篷·木瓜和草莓</description>
</image>

			<item>
			<link>http://www.donhwa.com.cn/article/160.htm</link>
			<title><![CDATA[找不到类型或命名空间word ]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[.Net]]></category>
			<pubDate>Tue,30 Dec 2008 13:31:43 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=160</guid>
		<description><![CDATA[<p>用.net 做导出Word 报表时遇到了问题.</p>
<p><span style="color: #ff0000">找不到类型或命名空间word </span></p>
<p><span style="">虽然添加了引用,但是using 没有写好</span></p>
<p><span style="color: #ff0000">应该加入 using Word = Microsoft.Office.Interop.Word;</span></p>
<p><span style="color: #ff0000">如果只是简单地 using Microsoft.Office.Interop.Word 则命名空间会冲突.</span></p>
<p>&nbsp;</p>]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/159.htm</link>
			<title><![CDATA[动手做个RJ45的环回头]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[木瓜笔记]]></category>
			<pubDate>Tue,23 Dec 2008 13:26:57 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=159</guid>
		<description><![CDATA[动手做个RJ45的环回头： <br/>材料RJ45水晶头一个网线5CM，做个568B标准的头（标准568B：橙白--1，橙--2，绿白--3，蓝--4，蓝白--5，绿--6，棕白--7，棕--8 ），然后因为橙白--1、橙--2两端为信号发送端,绿白--3、绿--6两端为信号接收端，所以把橙白--1，绿白--3的双绞线拨开扭到一起包好；橙--2，绿--6的双绞线拨开扭到一起包好。]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/158.htm</link>
			<title><![CDATA[Response.Redirect 产生的“正在中止线程”错误]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[.Net]]></category>
			<pubDate>Thu,27 Nov 2008 10:44:06 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=158</guid>
		<description><![CDATA[Response.Redirect 产生的“正在中止线程”错误<br/>登陆页面日志中，老是会出现在一个 &#34;正在中止线程“(ThreadAbortException)的例外信息。<br/>调试后发现 例外是由 Response.Redirect 方法产生的，虽然知道是线程的问题， <br/>但是不知为何 Redirect会出现这样的错误，Google了一下后，才发现MS早就发现了这个问题，但提供了解决方法。以下是主要信息的摘要:<br/>症状<br/>如果使用 Response.End、Response.Redirect 或 Server.Transfer 方法，将出现 ThreadAbortException 异常。您可以使用 try-catch 语句捕获此异常。<br/>原因<br/>Response.End 方法终止页的执行，并将此执行切换到应用程序的事件管线中的 Application_EndRequest 事件。不执行 Response.End 后面的代码行。<br/><br/>此问题出现在 Response.Redirect 和 Server.Transfer 方法中，因为这两种方法均在内部调用 Response.End。<br/>解决方案<br/>要解决此问题，请使用下列方法之一： • 对于 Response.End，调用 HttpContext.Current.ApplicationInstance.CompleteRequest 方法而不是 Response.End 以跳过 Application_EndRequest 事件的代码执行。 <br/>• 对于 Response.Redirect，请使用重载 Response.Redirect(String url, bool endResponse)，该重载对 endResponse 参数传递 false 以取消对 Response.End 的内部调用。例如： Response.Redirect (&#34;nextpage.aspx&#34;, false);<br/> <br/> <br/>]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/157.htm</link>
			<title><![CDATA[雅虎公司C#笔试题 ]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[.Net]]></category>
			<pubDate>Mon,24 Nov 2008 08:38:31 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=157</guid>
		<description><![CDATA[<h1 class="postTitle"><a class="postTitle2" id="AjaxHolder_ctl01_TitleUrl" href="http://www.cnblogs.com/mFrog/archive/2008/11/23/1339606.html">雅虎公司C#笔试题</a></h1>
<div class="clear">&nbsp;</div>
<div class="postBody">
<p>拿出来大家一起讨论下，希望知道的，能留言，并写下答案</p>
<p>格式：题号+答案</p>
<p>&nbsp;</p>
<p>Question 1. (单选) <br />
<br />
　　在计算机网络中,表征数据传输可靠性的指标是 <br />
<br />
　　　1. 传输率 <br />
　　　2. 误码率 <br />
　　　3. 信息容量 <br />
　　　4. 频带利用率 <br />
&nbsp;&nbsp; <br />
Question 2. (单选) <br />
<br />
　　以下关于链式存储结构的叙述中哪一条是不正确的? <br />
<br />
　　　1. 结点除自身信息外还包括指针域,因此存储密度小于顺序存储结构 <br />
　　　2. 逻辑上相邻的结点物理上不必邻接 <br />
　　　3. 可以通过计算直接确定第i个结点的存储地址 <br />
　　　4. 插入、删除运算操作方便,不必移动结点 <br />
&nbsp;&nbsp; <br />
Question 3. (单选) <br />
<br />
　　以下哪一个不是栈的基本运算 <br />
<br />
　　　1. 删除栈顶元素 <br />
　　　2. 删除栈底元素 <br />
　　　3. 判断栈是否为空 <br />
　　　4. 将栈置为空栈 <br />
&nbsp;&nbsp; <br />
Question 4. (单选) <br />
<br />
　　以下关于广义表的叙述中,正确的是 <br />
<br />
　　　1. 广义表是0个或多个单元素或子表组成的有限序列 <br />
　　　2. 广义表至少有一个元素是子表 <br />
　　　3. 广义表不可以是自身的子表 <br />
　　　4. 广义表不能为空表 <br />
&nbsp;&nbsp; <br />
Question 5. (单选) <br />
<br />
　　如果一棵二叉树结点的前序序列是A、B、C,后序序列是C、B、A,则该二叉树结点的对称序序列 <br />
<br />
　　　1. 必为A、B、C <br />
　　　2. 必为A、C、B <br />
　　　3. 必为B、C、A <br />
　　　4. 不能确定 <br />
&nbsp;&nbsp; <br />
Question 6. (单选) <br />
<br />
　　在虚拟页式存储管理方案中,下面哪一部分完成将页面调入内存的工作? <br />
<br />
　　　1. 缺页中断处理 <br />
　　　2. 页面淘汰过程 <br />
　　　3. 工作集模型应用 <br />
　　　4. 紧缩技术利用 <br />
&nbsp;&nbsp; <br />
Question 7. (单选) <br />
<br />
　　在DOS系统中,用于记录和管理磁盘数据区使用情况的数据结构 <br />
<br />
　　　1. 位图表 <br />
　　　2. 空闲块表 <br />
　　　3. 文件分配表 <br />
　　　4. 文件控制块 <br />
&nbsp;&nbsp; <br />
Question 8. (单选) <br />
<br />
　　设有关系R(S,D,M),其函数依赖集F={S&rarr;D,D&rarr;M}。则关系R至多满足 <br />
<br />
　　　1. 1NF <br />
　　　2. 2NF <br />
　　　3. 3NF <br />
　　　4. BCNF <br />
&nbsp;&nbsp; <br />
Question 9. (单选) <br />
<br />
　　在数据库逻辑设计中,当将E-R图转换为关系模式时,下面的做法哪一个是不正确的? <br />
<br />
　　　1. 一个实体类型转换为一个关系模式 <br />
　　　2. 一个联系类型转换为一个关系模式 <br />
　　　3. 由实体类型转换成的关系模式的主键是该实体类型的主键 <br />
　　　4. 由联系类型转换成的关系模式的属性是与该联系类型相关的诸实体类型的属性的全体 <br />
&nbsp;&nbsp; <br />
Question 10. (单选) <br />
<br />
　　计算机网络按照所覆盖的地理范围分类,可以分广域网、局域网与 <br />
<br />
　　　1. TCP/IP网 <br />
　　　2. ATM网 <br />
　　　3. ISDN <br />
　　　4. 城域网 <br />
<br />
<br />
Question 11. (单选)&nbsp;&nbsp; <br />
<br />
<br />
　　计算机网络拓扑结构主要取决于它的 <br />
<br />
　　　1. 资源子网 <br />
　　　2. FDDI网 <br />
　　　3. 通信子网 <br />
　　　4. 路由器 <br />
&nbsp;&nbsp; <br />
Question 12. (单选) <br />
<br />
　　网络协议的三个要素是语法、语义与 <br />
<br />
　　　1. 工作原理 <br />
　　　2. 时序 <br />
　　　3. 进程 <br />
　　　4. 服务原语 <br />
&nbsp;&nbsp; <br />
Question 13. (单选) <br />
<br />
　　TCP/IP参考模型中,电子邮件协议SMTP依赖于传输层的 <br />
<br />
　　　1. UDP协议 <br />
　　　2. IP协议 <br />
　　　3. TCP协议 <br />
　　　4. 802.2协议 <br />
&nbsp;&nbsp; <br />
Question 14. (单选) <br />
<br />
　　IEEE802.2协议中10BASE-T标准规定在使用5类双绞线时,从网卡到集线器的最大距离为 <br />
<br />
　　　1. 100m <br />
　　　2. 185m <br />
　　　3. 300m <br />
　　　4. 500m <br />
&nbsp;&nbsp; <br />
Question 15. (单选) <br />
<br />
　　100Mbps Fast Ethernet与10Mbps Ethernet 工作原理的相同之处主要在 <br />
<br />
　　　1. 介质访问控制方法 <br />
　　　2. 物理层协议 <br />
　　　3. 网络层 <br />
　　　4. 发送时钟周期 <br />
&nbsp;&nbsp; <br />
Question 16. (单选) <br />
<br />
　　在Client/Server计算模式中,中间件middleware的作用是隔离应用与 <br />
<br />
　　　1. 结构化查询语言SQL <br />
　　　2. 应用进程 <br />
　　　3. 网络 <br />
　　　4. IP地址 <br />
&nbsp;&nbsp; <br />
Question 17. (单选) <br />
<br />
　　当用户向ISP申请Internet帐户时,用户的E-mail帐户应包括 <br />
　　　1. IP地址 <br />
　　　2. WWW地址 <br />
　　　3. 用户密码(Password) <br />
　　　4. 用户名(User Name)与用户密码(Password) <br />
&nbsp;&nbsp; <br />
Question 18. (单选) <br />
<br />
　　WWW的超链接中定位信息所在的位置使用的是 <br />
<br />
　　　1. 超文本(hypertext)技术 <br />
　　　2. 统一资源定位器(URL, Uniform Resource Locators) <br />
　　　3. 超媒体(hypermedia技术) <br />
　　　4. 超文本标注语言HTML <br />
&nbsp;&nbsp; <br />
Question 19. (单选) <br />
<br />
　　计算机网络系统与分布式系统之间的区别主要是 <br />
<br />
　　　1. 系统物理结构 <br />
　　　2. 系统高层软件 <br />
　　　3. 传输介质类型 <br />
　　　4. 服务器类型 <br />
&nbsp;&nbsp; <br />
Question 20. (单选) <br />
<br />
　　帧中继系统设计的主要目标是用于互连多个 <br />
<br />
　　　1. 广域网 <br />
　　　2. 电话网 <br />
　　　3. 局域网 <br />
　　　4. 0)ATIM网 <br />
<br />
<br />
Question 21. (单选) <br />
<br />
　　ATM网络采用固定长厦的信元传送数据，信元长度为 <br />
<br />
　　　1. 1024B <br />
　　　2. 53B <br />
　　　3. 128B <br />
　　　4. 64B <br />
&nbsp;&nbsp; <br />
Question 22. (单选) <br />
<br />
　　TCP/IP参考模型中的主机-网络层对应于OSI RM中的 <br />
<br />
　　　1. 网络层 <br />
　　　2. 物理层 <br />
　　　3. 数据链路层 <br />
　　　4. 物理层与数据链路层 <br />
&nbsp;&nbsp; <br />
Question 23. (单选) <br />
<br />
　　计算机网络最突出的优点是： <br />
<br />
　　　1. 计算精度高 <br />
　　　2. 内存容量大 <br />
　　　3. 运算速度快 <br />
　　　4. 连网的计算机能够相互共享资源 <br />
&nbsp;&nbsp; <br />
Question 24. (单选) <br />
<br />
　　计算机网络分为局域网、城域网与广域网，其划分的依据是： <br />
<br />
　　　1. 数据传输所使用的介质 <br />
　　　2. 网络的作用范围 <br />
　　　3. 网络的控制方式 <br />
　　　4. 网络的拓扑结构 <br />
&nbsp;&nbsp; <br />
Question 25. (单选) <br />
<br />
　　用二分法查找一个长度为10的、排好序的线性表，查找不成功时，最多需要比较多少次？ <br />
<br />
　　　1. 5 <br />
　　　2. 2 <br />
　　　3. 4 <br />
　　　4. 1 <br />
&nbsp;&nbsp; <br />
Question 26. (单选) <br />
<br />
　　模块内聚度越高，说明模块内各成分彼此结合的程度越 <br />
<br />
　　　1. 松散 <br />
　　　2. 紧密 <br />
　　　3. 无法判断 <br />
　　　4. 相同 <br />
&nbsp;&nbsp; <br />
Question 27. (单选) <br />
<br />
　　软件需求分析阶段的输出主要是 <br />
<br />
　　　1. 需求说明书 <br />
　　　2. 开发计划 <br />
　　　3. 可行性报告 <br />
　　　4. 设计说明书 <br />
&nbsp;&nbsp; <br />
Question 28. (单选) <br />
<br />
　　以下选项中不是项目经理的职责的是？ <br />
<br />
　　　1. 需求分析 <br />
　　　2. 计划 <br />
　　　3. 计划跟踪 <br />
　　　4. 质量管理 <br />
&nbsp;&nbsp; <br />
Question 29. (单选) <br />
<br />
　　单元测试一般在什么时候进行？ <br />
<br />
　　　1. 编码完成后 <br />
　　　2. 系统测试前 <br />
　　　3. 测试用例编写完成后 <br />
　　　4. 集成测试后 <br />
&nbsp;&nbsp; <br />
Question 30. (多选) <br />
<br />
　　配置管理能起到以下哪些作用？ <br />
<br />
　　　1. 版本管理 <br />
　　　2. 变更管理 <br />
　　　3. 需求管理 <br />
　　　4. 测试管理 <br />
<br />
&nbsp;&nbsp; <br />
<br />
Question 31. (单选)&nbsp;&nbsp; <br />
<br />
<br />
　　根据线程安全的相关知识，分析以下代码，当调用test方法时i&gt;10时是否会引起死锁? <br />
<br />
public void test(int i)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
lock(this)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
if (i&gt;10)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
i--;&nbsp;&nbsp; <br />
test(i);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
　　　1. 会锁死 <br />
　　　2. 不会锁死 <br />
<br />
Question 32. (单选) <br />
<br />
　　以下描述错误的是（） <br />
<br />
　　1. 在C++中支持抽象类而在C#中不支持抽象类。 <br />
　　2. C++中可在头文件中声明类的成员而在CPP文件中定义类的成员，在C#中没有头文件并且在同一处声明和定义类的成员。 <br />
　　3. 在C#中可使用 new 修饰符显式隐藏从基类继承的成员。 <br />
　　4. 在C#中要在派生类中重新定义基类的虚函数必须在前面加Override。 <br />
&nbsp;&nbsp; <br />
Question 33. (单选) <br />
<br />
　　int[][] myArray3=new int[3][]{new int[3]{5,6,2},new int[5]{6,9,7,8,3},new int[2]{3,2}}; myArray3[2][2]的值是（）。 <br />
<br />
　　1. 9 <br />
　　2. 2 <br />
　　3. 6 <br />
　　4. 越界 <br />
&nbsp;&nbsp; <br />
Question 34. (单选) <br />
<br />
　　在C#中利用Socket进行网络通信编程的一般步骤是：建立Socket侦听、（ ）、利用Socket接收和发送数据。 <br />
　　1. 建立Socket连接 <br />
　　2. 获得端口号； <br />
　　3. 获得IP地址； <br />
　　4. 获得主机名； <br />
<br />
Question 35. (单选) <br />
　　如果设treeView1=new TreeView(),TreeNode node=new TreeNode(&quot;根结点&quot; )，则treeView1.Nodes.Add(node)返回的是一个 ()类型的值。 <br />
　　1. TreeNode； <br />
　　2. int； <br />
　　3. string； <br />
　　4. TreeView； <br />
&nbsp;&nbsp; <br />
Question 36. (单选) <br />
　　声明一个委托public delegate int myCallBack(int x); 则用该委托产生的回调方法的原型应该是 <br />
　　1. void myCallBack(int x) <br />
　　2. int receive(int num) <br />
　　3. string receive(int x) <br />
　　4. 不确定的 <br />
&nbsp;&nbsp; <br />
Question 37. (单选) <br />
　　关于ASP.NET中的代码隐藏文件的描述正确的是 <br />
　　1. Web窗体页的程序的逻辑由代码组成，这些代码的创建用于与窗体交互。编程逻辑唯一与用户界面不同的文件中。该文件称作为&ldquo;代码隐藏&rdquo;文件，如果用C＃创建，该文件 <br />
　　2. 项目中所有Web窗体页的代码隐藏文件都被编译成.EXE文件 <br />
　　3. 项目中所有的Web窗体页的代码隐藏文件都被编译成项目动态链接库（.dll）文件 <br />
　　4. 以上都不正确 <br />
&nbsp;&nbsp; <br />
Question 38. (单选) <br />
　　What compiler switch creates an xml file from the xml comments in the files in an assembly? <br />
　　1. /text <br />
　　2. /doc <br />
　　3. /xml <br />
　　4. /help <br />
&nbsp;&nbsp; <br />
Question 39. (单选) <br />
　　下面的代码实现了设计模式中的什么模式 <br />
　　public class A { <br />
　　private A instance; <br />
　　private A() { <br />
　　} <br />
　　public static A Instance { <br />
　　get <br />
　　{ <br />
　　if ( A == null ) <br />
　　A = new A(); <br />
　　return instance; <br />
　　} <br />
　　} <br />
　　} <br />
　　　1. Factory <br />
　　　2. Abstract Factory <br />
　　　3. Singleton <br />
　　　4. Builder <br />
&nbsp;&nbsp; <br />
Question 40. (单选) <br />
class Class1 <br />
{ <br />
public static int Count = 0; <br />
static Class1() <br />
{ <br />
Count++; <br />
} <br />
public Class1() <br />
{ <br />
Count++; <br />
} <br />
} <br />
Class1 o1 = new Class1(); <br />
Class1 o2 = new Class1(); <br />
　　请问，Class1.Count的值是多少？( ) <br />
　　　1. 1 <br />
　　　2. 2 <br />
　　　3. 3 <br />
　　　4. 4 <br />
&nbsp;&nbsp; <br />
Question 41. (单选)&nbsp;&nbsp; <br />
<br />
abstract class BaseClass <br />
{ <br />
public virtual void MethodA() <br />
{ <br />
Console.WriteLine(&quot;BaseClass&quot;); <br />
} <br />
public virtual void MethodB() <br />
{ <br />
} <br />
} <br />
class Class1: BaseClass <br />
{ <br />
public void MethodA() <br />
{ <br />
Console.WriteLine(&quot;Class1&quot;); <br />
} <br />
public override void MethodB() <br />
{ <br />
} <br />
} <br />
class Class2: Class1 <br />
{ <br />
new public void MethodB() <br />
{ <br />
} <br />
} <br />
class MainClass <br />
{ <br />
public static void Main(string[] args) <br />
{ <br />
Class2 o = new Class2(); <br />
o.MethodA();&nbsp;&nbsp; <br />
} <br />
} <br />
　　请问，此程序输出结果是: <br />
　　　1. BaseClass <br />
　　　2. BassClass Class1 <br />
　　　3. Class1 <br />
　　　4. Class1 BassClass&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
Question 42. (单选) <br />
public static void Main(string[] args) <br />
{ <br />
int i = 2000; <br />
object o = i; <br />
i = 2001; <br />
int j =(int) o; <br />
Console.WriteLine(&quot;i={0},o={1}, j={2}&quot;,i,o,j); <br />
} <br />
　　　1. i=2001,o=2000,j=2000 <br />
　　　2. i=2001,o=2001,,j=2001 <br />
　　　3. i=2000,o=2001,,j=2000 <br />
　　　4. i=2001,o=2000,j=2001 <br />
&nbsp;&nbsp; <br />
Question 43. (多选) <br />
　　您要创建ASP.NET应用程序用于运行AllWin公司内部的Web站点，这个应用程序包含了50个页面。您想要配置这个应用程序以便当发生一个HTTP代码错误时它可以显示一个自定义的错误页面给用户。您想要花最小的代价完成这些目标，您应该怎么做？(多选) <br />
　　　1. 在这个应用程序的Global.asax文件中创建一个Application_Error过程去处理ASP.NET代码错误。 <br />
　　　2. 在这个应用程序的Web.config文件中创建一个applicationError节去处理ASP.NET代码错误。 <br />
　　　3. 在这个应用程序的Global.asax文件中创建一个CustomErrors事件去处理HTTP错误。 <br />
　　　4. 在这个应用程序的Web.config文件中创建一个CustomErrors节去处理HTTP错误。 <br />
&nbsp;&nbsp; <br />
Question 44. (单选) <br />
<br />
　如下程序的运行结果是：&nbsp;&nbsp; <br />
public abstract class A&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
public A()&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
Console.WriteLine('A');&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public virtual void Fun()&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
Console.WriteLine(&quot;A.Fun()&quot;);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
public class B: A&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
public B()&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
Console.WriteLine('B');&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
public new void Fun()&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
Console.WriteLine(&quot;B.Fun()&quot;);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
public static void Main()&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
A a = new B();&nbsp;&nbsp; <br />
a.Fun();&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
　　　1. A B A.Fun()&nbsp;&nbsp; <br />
　　　2. A B B.Fun() <br />
　　　3. B A A.Fun() <br />
　　　4. B A B.Fun() <br />
&nbsp;&nbsp; <br />
Question 45. (单选) <br />
<br />
　　Which of these string definitions will prevent escaping on backslashes in C#?* <br />
<br />
　　　1. string s = #&rdquo;n Test string&rdquo;; <br />
　　　2. string s = &ldquo;&rsquo;n Test string&rdquo;; <br />
　　　3. string s = @&rdquo;n Test string&rdquo;; <br />
　　　4. string s = &ldquo;n Test string&rdquo;; <br />
&nbsp;&nbsp; <br />
Question 46. (单选) <br />
<br />
　　Which of the following operations can you NOT perform on an ADO.NET DataSet? <br />
<br />
　　　1. A DataSet can be synchronised with a RecordSet. <br />
　　　2. A DataSet can be synchronised with the database. <br />
　　　3. A DataSet can be converted to XML. <br />
　　　4. You can infer the schema from a DataSet <br />
&nbsp;&nbsp; <br />
Question 47. (单选) <br />
<br />
　　In Object oriented Programming, how would you describe encapsulation? <br />
<br />
　　　1. The conversion of one type of object to another. <br />
　　　2. The runtime resolution of method calls. <br />
　　　3. The exposition of data. <br />
　　　4. The separation of interface and implementation. <br />
&nbsp;&nbsp; <br />
Question 48. (单选) <br />
<br />
　　How does assembly versioning in .NET prevent DLL Hell? <br />
<br />
　　　1. The runtime checks to see that only one version of an assembly is on the machine at any one time. <br />
　　　2. .NET allows assemblies to specify the name AND the version of any assemblies they need to run. <br />
　　　3. The compiler offers compile time checking for backward compatibility. <br />
　　　4. It doesn&rsquo;t. <br />
&nbsp;&nbsp; <br />
Question 49. (单选) <br />
<br />
　　三种常用的字符串判空串方法： <br />
<br />
　　　1: bool isEmpty = (str.Length == 0);&nbsp;&nbsp; <br />
　　　2: bool isEmpty = (str == String.Empty);&nbsp;&nbsp; <br />
　　　3: bool isEmpty = (str == &quot;&quot;); <br />
<br />
　　哪种方法最快？ <br />
<br />
　　　1. 1 <br />
　　　2. 2 <br />
　　　3. 3 <br />
&nbsp;&nbsp; <br />
Question 50. (单选) <br />
<br />
public sealed class SampleSingleton1 <br />
{ <br />
private int m_Counter = 0; <br />
　　private SampleSingleton1() <br />
{ <br />
Console.WriteLine(&quot;&quot;初始化SampleSingleton1。&quot;&quot;); <br />
} <br />
<br />
public static readonly SampleSingleton1 Singleton = new SampleSingleton1(); <br />
<br />
public void Counter() <br />
{ <br />
m_Counter ++; <br />
} <br />
}&nbsp;&nbsp; <br />
<br />
　　以上代码实现了设计模式中的哪种模式？ <br />
<br />
　　　1. 原型 <br />
　　　2. 抽象工厂 <br />
　　　3. 单键 <br />
　　　4. 生成器</p>
</div>]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/156.htm</link>
			<title><![CDATA[DirectX编程：C#中利用Socket实现网络语音通信[初级版本] ]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[木瓜资源]]></category>
			<pubDate>Wed,19 Nov 2008 13:39:06 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=156</guid>
		<description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [来源：<a href="http://www.cnblogs.com/stg609/archive/2008/11/19/1334544.html">http://www.cnblogs.com/stg609/archive/2008/11/19/1334544.html</a> 作者：stg609]</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在时下的VOIP软件很多，比较有名的就是Skype，还有其它诸如UUcall、快门等等。它们提供的功能除了网络上的语音通话外，还可以与固定电话、手机等通话。在本篇中主要介绍利用C#实现语音通信的基本方法。但是目前只实现了网络上语音传输的基本功能，而且比较粗糙，没有采用什么算法来优化，所以大家千万不要期望过高。我写这篇的目的除了记录自己的经历之外，更希望有高手能给出改进的意见或算法。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 开发平台：.NET Framework 2.0 ，VS 2005，Windows XP，DirectX SDK（June 2008）下载页面 。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 开发语言：C#。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 测试环境：Windows XP 、.net framework 2.0、普通局域网。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 测试结果：在多台安装了windows XP系统且配置不同的电脑上测试，均能正常运行。可以进行语音对话，但是有明显的杂音，沿时低。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 限于篇幅，在本文中会详细介绍本人认为比较关健的问题，其它部分只做大概介绍，为了便于大家理解，可以先阅读：<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1.DirectX编程：[初级]C# 中利用 DirectSound 录音<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2.C# Socket编程笔记</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 在本文中打算按照以下顺序介绍：<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1.项目结果预览与说明<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2.实现方法概要<br />
&nbsp;&nbsp;&nbsp;&nbsp; 3.语言采集<br />
&nbsp;&nbsp;&nbsp;&nbsp; 4.语音传输<br />
&nbsp;&nbsp;&nbsp;&nbsp; 5.语音播放</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 项目结果预览与说明</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 界面如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明：界面很简单，只提供了一个选择或输入对方IP的功能，当选择合适局域网内IP之后，单击确定便激活了语音聊天的按钮。如果你想进行语音聊天就可以开始聊天了，聊天端口采用8000。本软件只适用于局域网内用户的聊天，另外因为没有增加用户认证的功能，所以只有在双方都启动了这款软件才能进行通信。如果只想在单机上测试，那只需要选择本机的IP便可。由于囧于技术水平，尝试N次之后，任不知如何才能正确地实现语音效果（如回声消除、降噪等）来保障音质，因此在单机测试会有回声干扰，嚣叫声比较严重，希望高手解囊。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实现方法概要</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 要想实现语音聊天，有几个步骤是必须的（就是我不说，相信你应该也能想得到一些）：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a 语音采集：采集的作用就是从你的麦克风中获取数据，我采用DirectSound类来实现这个技术。参考：C# 中利用 DirectSound 录音<br />
&nbsp;&nbsp; （b 语音编码：利用语音编码算法对采集到的话音进行压缩编码，进行编码的目的是为了减少网络带宽的压力。）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c 语音传输：将采集到的声音传输到网络上的其它主机，我采用Socket UDP方式来实现。参考：C# Socket编程笔记<br />
&nbsp;&nbsp; （d 语音解码：如果所传输的语音进行过压缩编码，则必须对语音进行解码，否则无法得到原始语音数据。）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e 语音播放：当对方通过网络传输到本机时（，如果需要解码则先执行d），进行实时播放。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面红色标记的步骤，可以省略。在本软件中，我并未采用这两个步骤，因为当我采用了这两个步骤后，发现语音时延异常的严重。我采用的编解码算法是G.729,利用的是g729.dll库文件，压缩效果不错，但是时延比较严重，可能是自己哪里没有设置好。如果有朋友使用过该算法，且时延低的，希望不吝赐教。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来，重点介绍语音采集、语音传输、语音播放的实现。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 语音采集<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于所实现的方法与录音方法一致，因此不会着墨过多，如果你不能很好的理解，请先参考：C# 中利用 DirectSound 录音</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与录音不同的是，录音我们需要建立一个WAVE文件来存储这些采集到的数据，而在语音聊天中，则不需要存储，当采集到一些数据后，就立刻发送出去，因此也不需要开辟很大的空间来存放PCM数据。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们先来回顾下采集的基本步骤：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. 设置PCM格式，设置相关的参数，如：采样频率、量化位数等。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. 建立采集用的设备对象，建立采集用的缓冲区对象。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. 设置缓冲区通知，设置通知被触发后的事件。通知是用于当缓冲区的读指针达到某预设位置时触发通知事件，提醒我们可以对某部分的数据进行传送了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4. 开始采集声音。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5. 当通知被触发后，建立一个新的线程来处理数据传送的事件。（建立一个新的线程，就是为了防止采集过程被中断）。</p>
<p>主要代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 设置音频格式，如采样率等<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;returns&gt;设置完成后的格式&lt;/returns&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private WaveFormat SetWaveFormat()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaveFormat format = new WaveFormat();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.FormatTag = WaveFormatTag.Pcm;//设置音频类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.SamplesPerSecond = 11025;//采样率（单位：赫兹）典型值：11025、22050、44100Hz<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.BitsPerSample = 16;//采样位数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.Channels = 1;//声道<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));//单位采样点的字节数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return format;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //按照以上采样规格，可知采样1秒钟的字节数为22050*2=44100B 约为 43K<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 创建捕捉设备对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;returns&gt;如果创建成功返回true&lt;/returns&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private bool CreateCaputerDevice()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //首先要玫举可用的捕捉设备<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CaptureDevicesCollection capturedev = new CaptureDevicesCollection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Guid devguid;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (capturedev.Count &gt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; devguid = capturedev[0].DriverGuid;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Windows.Forms.MessageBox.Show(&quot;当前没有可用于音频捕捉的设备&quot;, &quot;系统提示&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //利用设备GUID来建立一个捕捉设备对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capture = new Capture(devguid);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 创建捕捉缓冲区对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void CreateCaptureBuffer()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //想要创建一个捕捉缓冲区必须要两个参数：缓冲区信息（描述这个缓冲区中的格式等），缓冲设备。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaveFormat mWavFormat = SetWaveFormat();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CaptureBufferDescription bufferdescription = new CaptureBufferDescription();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bufferdescription.Format = mWavFormat;//设置缓冲区要捕捉的数据格式<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iNotifySize = mWavFormat.AverageBytesPerSecond / iNotifyNum;//1秒的数据量/设置的通知数得到的每个通知大小小于0.2s的数据量，话音延迟小于200ms为优质话音<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iBufferSize = iNotifyNum * iNotifySize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bufferdescription.BufferBytes = iBufferSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bufferdescription.ControlEffects = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bufferdescription.WaveMapped = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capturebuffer = new CaptureBuffer(bufferdescription, capture);//建立设备缓冲区对象</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置通知<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void CreateNotification()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferPositionNotify[] bpn = new BufferPositionNotify[iNotifyNum];//设置缓冲区通知个数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置通知事件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyEvent = new AutoResetEvent(false);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyThread = new Thread(RecoData);//通知触发事件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyThread.IsBackground = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyThread.Start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; iNotifyNum; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bpn[i].Offset = iNotifySize + i * iNotifySize - 1;//设置具体每个的位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bpn[i].EventNotifyHandle = notifyEvent.Handle;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myNotify = new Notify(capturebuffer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myNotify.SetNotificationPositions(bpn);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //线程中的事件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void RecoData()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 等待缓冲区的通知消息<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyEvent.WaitOne(Timeout.Infinite, true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 录制数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RecordCapturedData(Client,epServer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //真正转移数据的事件，其实就是把数据传送到网络上去。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void RecordCapturedData(Socket Client,EndPoint epServer )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] capturedata = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int readpos = 0, capturepos = 0, locksize = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capturebuffer.GetCurrentPosition(out capturepos, out readpos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; locksize = readpos - iBufferOffset;//这个大小就是我们可以安全读取的大小<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (locksize == 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (locksize &lt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {//因为我们是循环的使用缓冲区，所以有一种情况下为负：当文以载读指针回到第一个通知点，而Ibuffeoffset还在最后一个通知处<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; locksize += iBufferSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //capturedata = g729.Encode(capturedata);//语音编码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Client.SendTo(capturedata, epServer);//传送语音<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iBufferOffset += capturedata.Length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iBufferOffset %= iBufferSize;//取模是因为缓冲区是循环的。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上述代码可以很好的采集到声音数据，几乎与原始声音一致。如果你已经可以实现录音，那么以上对你来说应该并不陌生。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 语音传输<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这部分并不是很难，如果你熟悉socket编程，那么就可以PASS这一部分了，与以往传输不同的只是现在传输的是语音而已。如果你没接触过socket，那可以瞧瞧C# Socket编程笔记。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 感觉这部分叫&ldquo;语音传输&rdquo;并不是很恰当，因为其实真正用于传输的语句只有一句。除了语音传输之外，我们还需要对网络进行监听，从而能捕获对方发送给自己的语音信息。但是，也不知道叫什么好，就估且这么叫着吧。在这一部分，我主要讲下大致流程。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. 建立socket对象，在实例化这个对象的时候有一个参数是设置使用的协议，在本软件中，我采用的是UDP。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么要采用UDP？建立TCP能不能传送语音，答案肯定是能的。在本软件中，我考虑的主要是语音延时问题， 采用TCP在建立连接和维护连接中对时间和系统资源的开销较大，因此会有明显的时延发生，严重影响了实时性。另外，因为UDP是无连接的，这使得采用UDP可以支持日后功能上的扩展（如：组播）。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. 绑定本机的IP和端口，因为一个主机可能会有不止一个IP地址，如回发地址：127.0.0.1 和局域网地址：192.168.#.#。为了增加可用性，我这里选择绑定到任何本机可用的IP地址（IPAddress.Any），而端口我们约定默认为8000。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. 启动监听线程，来监听网络。我采用异步的方式，以便获得更好的系统响应度。</p>
<p>主要代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Thread ListenThread;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private byte[] bytData;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 监听方法，用于监听远程发送到本机的信息<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void Listen()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ListenThread = new Thread(new ThreadStart(DoListen));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ListenThread.IsBackground = true;//设置为后台线程，这样当主线程结束后，该线程自动结束<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ListenThread.Start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private EndPoint epRemote;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 监听线程<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void DoListen()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytData = new byte[intMaxDataSize];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; epRemote = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (LocalSocket.Poll(5000, SelectMode.SelectRead))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {//每5ms查询一下网络，如果有可读数据就接收<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LocalSocket.BeginReceiveFrom(bytData, 0, bytData.Length, SocketFlags.None, ref epRemote, new AsyncCallback(ReceiveData), null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 接收数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name=&quot;iar&quot;&gt;&lt;/param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void ReceiveData(IAsyncResult iar)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int intRecv = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intRecv = LocalSocket.EndReceiveFrom(iar, ref epRemote);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (intRecv &gt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] bytReceivedData = new byte[intRecv];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Buffer.BlockCopy(bytData, 0, bytReceivedData, 0, intRecv);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; voicecapture1.GetVoiceData(intRecv, bytReceivedData);//调用声音模块中的GetVoiceData（）从字节数组中获取声音并播放<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //GetVoiceData（）会在下一部分中提到<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4. 数据的发送因为只有一句话，所以我直接放在上一部分的语音采集中了。 Client.SendTo(capturedata, epServer);//传送语音<br />
&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 语音播放<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最麻烦的就是这部分了，而且感觉现在的实现方法仍然需要改进才好。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当声音传输到本机后，该怎么样才能让这些数据经过音响设备放出声音来呢？因为声音播放是从缓冲区中获取声音数据的因此我们必须先将获取到的数据写入缓冲区，然后再调用相应的方法来播放。看起来似乎不复杂，可是实现起来远没有这么简单。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我遇到的问题：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大家可以看下语音采集部分，我是在每次通知后进行语音采集然后就将采集到的语音发送到网络上，如果运行正常的话，这一部分数据实际播放长度远小于1秒。也就是说对方每次接收到的语音长度为毫秒级。而且如果网络质量可以的话，那么连续两次接收到数据的时间间隔也是相当小的。这样就产生问题了，如果我在接收到第一次数据后，将它写入缓冲区，然后调用相应的播放方法，由于语音长度实际很短，因此几乎听不到什么效果，而且可能发生当第一次缓冲区中的数据还没播放完，就已经被第二次的数据覆盖，导致声音混乱。经测试，此种方法无法达到声音实时效果。期间我也曾修改过数据发送部分，希望当语音长度达到某一长度时在发送，可是问题依旧，看样子重要的是在接收端进行相应处理。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 直接缓冲播放的方法不行，那就换~~<br />
&nbsp;&nbsp;&nbsp;&nbsp; 上网搜，可惜的是这方面的资料实在有限，C#的就更少了。参考一些文献，大家提到利用在缓冲区设置两个指针，一个播放指针，一个写指针（写指针用于表示当前从网络上接收到的数据从写指针所指示位置开始往下写，播放指针则表示当前所播放的数据末尾）。当播放指针达到某个位置时就播放某一部分数据，而不影响将被写入的缓冲区部分，这样就可以很好的解决数据覆盖的问题。除此之外，还要将缓冲区设置为循环缓冲区，也就是头尾相接，当到达尾部时，自己从部开始，此时将覆盖头部数据。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看了这些，你是不是感觉很眼熟？是不是和语音采集很类似？是的，我们在捕捉缓冲区中就是这样设置的，我们利用通知来设置触发事件。不同的是我们接收语音用的缓冲区并不是捕捉缓冲区，MS为捕捉单独设置了一个捕捉缓冲区。我们利用的是另一个缓冲区，辅助缓冲区（SecondaryBuffer）。后来发现该缓冲区也有类似的通知，这意味什么？我当时很兴奋，可是~~相当郁闷的是，我不管怎么设置通知，编译时都会报错，到外询求答案，均无果。在 MS 相关网站上咨询后，有一位叫jwatte的答案，让我又高兴又失望：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 原话如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Notify is broken in DirectSound, has been for a long time, and probably will never be fixed.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The only way to know when you need to play the next piece of data is to check the play pointer each time through your main loop, and then lock the buffer and fill in whatever part has been played out.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Also, DirectSound is now in &quot;maintenance&quot; mode, and won't be further developed by Microsoft. Instead, for game applications, they recommend you use XAudio2 to play sound.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 简单意思就是：Notify出问题已经很长时间了，而且MS可能永远都不会去修复这个问题。而且他也为播放声音提供了些建议，这些建议与上面所讲的基本一致。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至于这个答案是否正确，因为无从考证，就不再讨论了。如果哪位高手曾经实现过，希望赐教。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 既然目前无法正常使用，就只能来手动写了。这个方法名就是：GetVoiceData（）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 思路如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &middot;利用MemoryStream来代表这个接收缓冲区。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &middot;设置两个表示指针位置的字段：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int intPosWrite = 0;//内存流中写指针位移<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int intPosPlay = 0;//内存流中播放指针位移<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &middot;当接收到数据后，则移动写指针，移动的长度为接收到的数据长度。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &middot;利用一个字段表示通知大小：private int intNotifySize = 5000;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &middot;当写指针的位置达到通知大小，则执行播放操作，然后移动播放指针到刚才的通知的位置。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &middot;如果当前写指针的位移与将要写入到缓冲区的数据大小相加后超过缓冲容量的，则进行摩尔运算，实现循环的效果。</p>
<p>GetVoiceData（）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int intPosWrite = 0;//内存流中写指针位移<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int intPosPlay = 0;//内存流中播放指针位移<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int intNotifySize = 5000;//设置通知大小</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 从字节数组中获取音频数据，并进行播放<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name=&quot;intRecv&quot;&gt;字节数组长度&lt;/param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name=&quot;bytRecv&quot;&gt;包含音频数据的字节数组&lt;/param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void GetVoiceData(int intRecv, byte[] bytRecv)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //intPosWrite指示最新的数据写好后的末尾。intPosPlay指示本次播放开始的位置。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (intPosWrite + intRecv &lt;= memstream.Capacity)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {//如果当前写指针所在的位移+将要写入到缓冲区的长度小于缓冲区总大小<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((intPosWrite - intPosPlay &gt;= 0 &amp;&amp; intPosWrite - intPosPlay &lt; intNotifySize) || (intPosWrite - intPosPlay &lt; 0 &amp;&amp; intPosWrite - intPosPlay + memstream.Capacity &lt; intNotifySize))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Write(bytRecv, 0, intRecv);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intPosWrite += intRecv;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (intPosWrite - intPosPlay &gt;= 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {//先存储一定量的数据，当达到一定数据量时就播放声音。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffDiscript.BufferBytes = intPosWrite - intPosPlay;//缓冲区大小为播放指针到写指针之间的距离。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SecondaryBuffer sec = new SecondaryBuffer(buffDiscript, PlayDev);//建立一个合适的缓冲区用于播放这段数据。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Position = intPosPlay;//先将memstream的指针定位到这一次播放开始的位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sec.Write(0, memstream, intPosWrite - intPosPlay, LockFlag.FromWriteCursor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sec.Play(0, BufferPlayFlags.Default);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Position = intPosWrite;//写完后重新将memstream的指针定位到将要写下去的位置。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intPosPlay = intPosWrite;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (intPosWrite - intPosPlay &lt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffDiscript.BufferBytes = intPosWrite - intPosPlay + memstream.Capacity;//缓冲区大小为播放指针到写指针之间的距离。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SecondaryBuffer sec = new SecondaryBuffer(buffDiscript, PlayDev);//建立一个合适的缓冲区用于播放这段数据。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Position = intPosPlay;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sec.Write(0, memstream, memstream.Capacity - intPosPlay, LockFlag.FromWriteCursor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Position = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sec.Write(memstream.Capacity - intPosPlay, memstream, intPosWrite, LockFlag.FromWriteCursor);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sec.Play(0, BufferPlayFlags.Default);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Position = intPosWrite;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intPosPlay = intPosWrite;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {//当数据将要大于memstream可容纳的大小时<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int irest = memstream.Capacity - intPosWrite;//memstream中剩下的可容纳的字节数。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Write(bytRecv, 0, irest);//先写完这个内存流。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Position = 0;//然后让新的数据从memstream的0位置开始记录<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memstream.Write(bytRecv, irest, intRecv - irest);//覆盖旧的数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intPosWrite = intRecv - irest;//更新写指针位置。写指针指示下一个开始写入的位置而不是上一次结束的位置，因此不用减一<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样，基本上就可以实现语音聊天了。可是这样的效果还只能是初步的，而且由于回声的原因，相当影响音质，还可能产生嚣叫，为了解决这个问题，我本打算采用MS提供的AEC算法，可是由于不知道如何实现，一直无法得到效果，因此这也是比较遗憾的地方。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可执行文件（注：要在安装了 .net framework 2.0 的平台上运行）：MatureVoiceEXE.rar<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源文件：MatureVoice.rar<br />
&nbsp;&nbsp;</p>]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/155.htm</link>
			<title><![CDATA[ASP.NET中的“外部组件发生异常”信息]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[木瓜笔记]]></category>
			<pubDate>Wed,19 Nov 2008 09:33:44 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=155</guid>
		<description><![CDATA[今天VS2008进行调试生成网站时, 莫名其妙地发现出现个错误.<br/>ASP.NET中的“外部组件发生异常”信息<br/><br/>检查后发现是我的用户控件名称被改动过。与.cs文件的类名不一致，所以引发错误。<br/>如 acontrol.ascx&nbsp;&nbsp; acontrol.ascx.cs 是关联的。<br/>我把 acontrol.ascx 改成了 bcontrol.ascx <br/>虽然 acontrol.ascx.cs 自动改成了 bcontrol.ascx.cs<br/>但是其代码里 仍是 public partial class acontrol<br/>而 bcontrol.ascx 代码中<br/>&lt;%@ Control Language=&#34;C#&#34; AutoEventWireup=&#34;true&#34; CodeBehind=&#34;这一项&#34; Inherits=&#34;又一项&#34; %&gt;<br/>不一致。导致的。]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/154.htm</link>
			<title><![CDATA[为IE7 指定样式]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[网页设计]]></category>
			<pubDate>Tue,18 Nov 2008 16:29:30 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=154</guid>
		<description><![CDATA[为IE7 指定样式<br/>&lt;!--[if lt IE 7]&gt;&lt;link rel=&#34;stylesheet&#34; type=&#34;text/css&#34; href=&#34;<a href="http://creativecommons.org/includes/deed3-ie.css" target="_blank" rel="external">http://creativecommons.org/includes/deed3-ie.css</a>&#34; media=&#34;screen&#34; /&gt;&lt;![endif]--&gt;]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/153.htm</link>
			<title><![CDATA[结构化思维与面向对象思维]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[木瓜笔记]]></category>
			<pubDate>Tue,18 Nov 2008 08:57:59 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=153</guid>
		<description><![CDATA[<p><strong><span style="font-family: 宋体">摘自<a class="headermaintitle" id="Header1_HeaderTitle" href="http://www.cnblogs.com/Barton131420/"><font color="#000000" size="4">Kanas.Net Blog</font></a></span></strong></p>
<p><strong><span style="font-family: 宋体">结构化思维是面向对象思维的基础。</span></strong><span style="font-family: 宋体">幻想中的一步登入</span>OO<span style="font-family: 宋体">的天空并无可能。面向对象的很多原则与结构化思维并无矛盾。真正对</span>OO<span style="font-family: 宋体">从理论到实践都透彻的人并不一定排斥结构化思维。</span></p>
<p><strong><span style="font-family: 宋体">不要比较面向对象与结构化思维的得失。</span></strong><span style="font-family: 宋体">谈到得失就必须有一杆秤。可惜这个世界上没有这样一杆公平的秤。每个人的经历不同、背景不同、思维方式不同，评估的结果就千差万别。其实没有对错，只有针对每个具体人的有效和无效。前面所述，通过面向对象可以将一个复杂问题迅速简化，当我遇到问题时候，我的方法通常是三步走：第一步解决最小的简单模型；第二步解决复合的常规模型；第三步解决扩展的推广模型。这样的确可能比结构化编程费一些事情，但基于我的智力，没有办法一次解决，所以我这样选择是基于我个人的情况。</span></p>
<p><strong><span style="font-family: 宋体">不要讨论面向对象的性能损失。</span></strong><span style="font-family: 宋体">比方说，很多人都认为基于托管代码的系统比基于原生代码的系统慢，但据</span>ACM(<span style="font-family: 宋体">美国计算机协会</span>)1999<span style="font-family: 宋体">年的调查报告，采用</span>Java<span style="font-family: 宋体">或者</span>C/C++<span style="font-family: 宋体">编写的系统，性能差异很小，而不同程序员间的差异却高达</span>30<span style="font-family: 宋体">倍！既然如此，为什么不把更多精力花费在代码间，而是讨论面向对象会给系统带来多大的性能损失呢？</span></p>
<p><strong><span style="font-family: 宋体">不要讨论什么充血模型或者贫血模型。</span></strong><span style="font-family: 宋体">解决问题才是最高目标，何必在乎形式呢？既然连结构化思维都可以接受，为什么要排斥所谓的贫血模型呢？</span>(<span style="font-family: 宋体">实话说我个人非常排斥老马的某些观点，为什么要把一个灵活开放的东西搞得那么死板教条呢？</span>)<span style="font-family: 宋体">譬如，面向对象有一个原则是尽量采用</span>chatty<span style="font-family: 宋体">接口，创建许多简单方法。而在分布式编程中这个原则就成了灾难</span>(<span style="font-family: 宋体">你不得不多次连接调用</span>)<span style="font-family: 宋体">，所以分布式编程的原则是尽量采用</span>chunky<span style="font-family: 宋体">接口，把方法留给本地，这是典型的结构化思维。所以原则并不是一成不变的。<br />
</span></p>
<p><strong><span style="font-family: 宋体">不要把责任推给你的上司、团队或者组织。</span></strong><span style="font-family: 宋体">不论你是一般程序员，还是团队负责人，每个人都是团队的重要成员，每个人都会对你正参与开发的系统、对团队产生同样的影响</span><span style="font-family: 宋体">。如果你一直希望改变你目前的方式，那就需要产生额外的效果，令你的上司和团队成员支持你。如果他们不支持你，不是因为他本身的素质，而是因为你没有让他看到效果。除了你自己是可以控制的，团队中的任何人你都只能影响，而不能控制。要改变他们，不是靠说教，而是靠实实在在的绩效。检讨一下你自己，是不是自己在某一方面做得不够好？或者根本你的出发点或者目标就值得怀疑？我相信很多人在对项目质量的考评中，进度会放在比质量更优先的位置。事实上进度与质量并不矛盾。如果组织更注重进度指标或者甚至根本不注重质量指标，你可以在不影响进度的前提下，提升质量指标，一定会获得组织的肯定。然后你就会慢慢发现，其实进度和质量可以相互促进而不是相互冲突。</span></p>]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/152.htm</link>
			<title><![CDATA[重振旗鼓]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[小 日 子]]></category>
			<pubDate>Mon,17 Nov 2008 17:28:42 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=152</guid>
		<description><![CDATA[<span style="font-size:18pt">重振旗鼓</span><br/>.VS2008简体中文正式版序列号<br/><br/><br/><br/>1.Visual Studio 2008 Professional Edition:<br/>XMQ2Y-4T3V6-XJ48Y-D3K2V-6C4WT<br/><br/><br/><br/>2.Visual Studio 2008 Team Test Load Agent:<br/>WPX3J-BXC3W-BPYWP-PJ8CM-F7M8T<br/><br/><br/><br/>3.Visual Studio 2008 Team System:<br/>PYHYP-WXB3B-B2CCM-V9DX9-VDY8T<br/><br/><br/><br/>4.Visual Studio 2008 Team Foundation Server:<br/>WPDW8-M962C-VJX9M-HQB4Q-JVTDM<br/><br/>预计中国互联网渗透率将提高到24%，广告主也会将网络广告支出提升20%。目前，网络广告仅占中国整体广告市场的3.5%，因此仍然可以对中国网络广告市场 30%的长期增长率存在信心。”<br/><a href="http://money.163.com/08/1021/08/4OP070H200251RJ2.html" target="_blank" rel="external">http://money.163.com/08/1021/08/4OP070H200251RJ2.html</a><br/><br/><br/>---------------------------<br/>提取失败<br/>---------------------------<br/>映像文件 up&#100;ate\iesetup.exe 有效，但不适用于此计算机类型。<br/><br/><br/>---------------------------<br/>确定&nbsp;&nbsp; <br/>---------------------------]]></description>
		</item>
		
			<item>
			<link>http://www.donhwa.com.cn/article/151.htm</link>
			<title><![CDATA[NVelocity介绍 1.1  Velocity是什么]]></title>
			<author>donhwa@126.com(admin)</author>
			<category><![CDATA[木瓜笔记]]></category>
			<pubDate>Fri,31 Oct 2008 20:27:45 +0800</pubDate>
			<guid>http://www.donhwa.com.cn/default.asp?id=151</guid>
		<description><![CDATA[<p>&nbsp;</p>
<h1 class="postTitle"><a class="postTitle2" id="AjaxHolder_ctl01_TitleUrl" href="http://www.cnblogs.com/h-hello/articles/1317934.html">NVelocity介绍 </a></h1>
<div class="clear">&nbsp;</div>
<div class="postBody">
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><a target="_blank" name="_Toc8028255"><font face="Times New Roman"><span style="font-weight: normal">1.1 </span><span style="font-weight: normal">&nbsp;</span></font></a><span style="font-weight: normal"><font face="Times New Roman">Velocity</font></span><span style="font-weight: normal; font-family: 黑体">是什么</span></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">是一个基于</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">的模板引擎（</span><font face="Times New Roman">template engine</font><span style="font-family: 宋体">）。它允许任何人仅仅简单的使用模板语言（</span><font face="Times New Roman">template language</font><span style="font-family: 宋体">）来引用由</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">代码定义的对象。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">当</span><font face="Times New Roman">nVelocity </font><span style="font-family: 宋体">应用于</span><font face="Times New Roman">web</font><span style="font-family: 宋体">开发时，界面设计人员可以和</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">程序开发人员同步开发一个遵循</span><font face="Times New Roman">MVC</font><span style="font-family: 宋体">架构的</span><font face="Times New Roman">web</font><span style="font-family: 宋体">站点，也就是说，页面设计人员可以只关注页面的显示效果，而由</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">程序开发人员关注业务逻辑编码。</span><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">将</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">代码从</span><font face="Times New Roman">web</font><span style="font-family: 宋体">页面中分离出来，这样为</span><font face="Times New Roman">web</font><span style="font-family: 宋体">站点的长期维护提供了便利，同时也为我们在</span><font face="Times New Roman">aspx</font><span style="font-family: 宋体">之外又提供了一种可选的方案。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">的能力远不止</span><font face="Times New Roman">web</font><span style="font-family: 宋体">站点开发这个领域，例如，它可以从模板（</span><font face="Times New Roman">template</font><span style="font-family: 宋体">）产生</span><font face="Times New Roman">SQL</font><span style="font-family: 宋体">和</span><font face="Times New Roman">PostScript</font><span style="font-family: 宋体">、</span><font face="Times New Roman">XML</font><span style="font-family: 宋体">，它也可以被当作一个独立工具来产生源代码和报告，或者作为其他系统的集成组件使用。</span><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">也可以为很多</span><font face="Times New Roman">web</font><span style="font-family: 宋体">开发架构提供模板服务（</span><font face="Times New Roman">template service</font><span style="font-family: 宋体">）。我们的系统就提供一个模板服务的方式允许一个</span><font face="Times New Roman">web</font><span style="font-family: 宋体">应用以一个真正的</span><font face="Times New Roman">MVC</font><span style="font-family: 宋体">模型进行开发。</span></p>
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><font face="Times New Roman"><span style="font-weight: normal">1.2 </span><span style="font-weight: normal">nVelocity</span></font><span style="font-weight: normal; font-family: 黑体">能为我们作什么？</span></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">假设你是一家专门出售</span><font face="Times New Roman">Mud</font><span style="font-family: 宋体">的在线商店的页面设计人员，让我们暂且称它为&ldquo;在线</span><font face="Times New Roman">MUD</font><span style="font-family: 宋体">商店&rdquo;。你们的业务很旺，客户下了各种类型和数量的</span><font face="Times New Roman">Mud</font><span style="font-family: 宋体">订单。他们都是通过输入用户名和密码后才登陆到你的网站，登陆后就允许他们查看订单并购买更多的</span><font face="Times New Roman">Mud</font><span style="font-family: 宋体">。现在，一种非常流行的</span><font face="Times New Roman">mud</font><span style="font-family: 宋体">正在打折销售。另外有一些客户规律性的购买另外一种也打折但不是很流行的</span><font face="Times New Roman">Bright Red Mud</font><span style="font-family: 宋体">，由于购买的人并不多所以它被安置在页面的边缘。所有用户的信息都是被跟踪并存放于数据库中的，所以某天有一个问题可能会冒出来：为什么不使用</span><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">来使用户更好的浏览他们感兴趣的商品呢？</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">使得</span><font face="Times New Roman">web</font><span style="font-family: 宋体">页面的客户化工作非常容易。作为一个站点的设计人员，你希望每个用户登陆时都拥有自己的页面。</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">你会见了一些公司内的软件工程师，你发现他们每个人都同意客户应该拥有具有个性化的信息。那让我们把软件工程师应该作的事情放在一边，看一看你应该作些什么吧。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">你可能在页面内嵌套如下的</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">（</span><font face="Times New Roman">nVelocity template language</font><span style="font-family: 宋体">）声明：</span><font face="Times New Roman"> <br />
</font></p>
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
http://www.CodeHighlighter.com/<br  />
<br  />
--><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">html</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<br />
</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">body</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<br />
Hello&nbsp;$customer.Name!<br />
<br />
</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">table</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<br />
#foreach(&nbsp;$mud&nbsp;in&nbsp;$nudsOnSpecial&nbsp;)<br />
<br />
#if&nbsp;(&nbsp;$customer.hasPurchased(&nbsp;$mud&nbsp;)&nbsp;)<br />
<br />
</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">tr</span><span style="color: rgb(0,0,255)">&gt;&lt;</span><span style="color: rgb(128,0,0)">td</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">$flogger.getPromo(&nbsp;$mud&nbsp;)</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">td</span><span style="color: rgb(0,0,255)">&gt;&lt;/</span><span style="color: rgb(128,0,0)">tr</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<br />
#end<br />
<br />
#end<br />
<br />
</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">table</span><span style="color: rgb(0,0,255)">&gt;<br />
</span></div>
<br />
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><a target="_blank" name="_Toc90698661"><font face="Times New Roman"><span style="font-weight: normal">1.1 <span style="font-weight: normal">VTL (</span>nVelocity </span></font></a><font face="Times New Roman"><span style="font-weight: normal">template language</span><span style="font-weight: normal">)</span></font></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">VTL</font><span style="font-family: 宋体">意味着提供最简单、最容易并且最整洁的方式合并页面动态内容。</span><font face="Times New Roman"> VTL </font><span style="font-family: 宋体">使用</span><font face="Times New Roman">references</font><span style="font-family: 宋体">来在站点内嵌套动态内容，一个变量就是一种类型的</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">。变量是某种类型的</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">，它可以指向</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">代码中的定义，或者从当前页面内定义的</span><font face="Times New Roman">VTL statement</font><span style="font-family: 宋体">得到值。下面是一个</span><font face="Times New Roman">VTL statement</font><span style="font-family: 宋体">的例子，它可以被嵌套到</span><font face="Times New Roman"> HTML</font><span style="font-family: 宋体">代码中：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $a = &ldquo;Velocity&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">和所有的</span><font face="Times New Roman">VTL statement</font><span style="font-family: 宋体">一样，这个</span><font face="Times New Roman">statement</font><span style="font-family: 宋体">以＃字符开始并且包含一个</span><font face="Times New Roman">directive</font><span style="font-family: 宋体">：</span><font face="Times New Roman">set</font><span style="font-family: 宋体">。当一个在线用户请求你的页面时，</span><font face="Times New Roman">nVelocity Template Engine</font><span style="font-family: 宋体">将查询整个页面以便发现所有＃字符，然后确定哪些是</span><font face="Times New Roman">VTL statement</font><span style="font-family: 宋体">，哪些不需要</span><font face="Times New Roman">VTL </font><span style="font-family: 宋体">作任何事情。</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃字符后紧跟一个</span><font face="Times New Roman">directive</font><span style="font-family: 宋体">：</span><font face="Times New Roman">set</font><span style="font-family: 宋体">时，这个</span><font face="Times New Roman">set directive</font><span style="font-family: 宋体">使用一个表达式（使用括号封闭）将一个值设置给变量。变量被列在左边，而它的值被列在右边，最后他们之间使用＝号分割。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">在上面的例子中，变量是</span><font face="Times New Roman">$a</font><span style="font-family: 宋体">，而它的值是</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">。和其他的</span><font face="Times New Roman">references</font><span style="font-family: 宋体">一样以</span><font face="Times New Roman">$</font><span style="font-family: 宋体">字符开始，而值总是以双引号封闭。</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">中仅有</span><font face="Times New Roman">String</font><span style="font-family: 宋体">可以被赋值给变量。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">记住以下的规则：</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">使用</span><font face="Times New Roman">$</font><span style="font-family: 宋体">字符开始的</span><font face="Times New Roman">references</font><span style="font-family: 宋体">用于得到什么；使用</span><font face="Times New Roman">#</font><span style="font-family: 宋体">字符开始的</span><font face="Times New Roman">directives</font><span style="font-family: 宋体">用于作些什么。</span></p>
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><font face="Times New Roman"><span style="font-weight: normal">1.2 </span>Hello nVelocity World</font></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">一旦某个变量被分配了一个值，那么你就可以在</span><font face="Times New Roman">HTML</font><span style="font-family: 宋体">文件的任何地方引用它。在下面的例子中，一个值被分配给</span><font face="Times New Roman">$foo</font><span style="font-family: 宋体">变量，并在其后被引用。</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;html&gt;&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;body&gt;&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $foo = &ldquo;nVelocity&rdquo; )&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">Hello $foo World!&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;/body&gt;&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;/html&gt;&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">上面的实现结果是在页面上打印&ldquo;</span><font face="Times New Roman">Hello nVelocity World</font><span style="font-family: 宋体">！&rdquo;</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">为了使包含</span><font face="Times New Roman">VTL directives</font><span style="font-family: 宋体">的</span><font face="Times New Roman">statement</font><span style="font-family: 宋体">更具有可读性，我们鼓励你在新行开始一个</span><font face="Times New Roman">VTL statement</font><span style="font-family: 宋体">，尽管你不是必须这么作。</span><font face="Times New Roman">Set directive</font><span style="font-family: 宋体">将在后面详细描述。</span></p>
<br />
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><span style="font-weight: normal"><font face="Times New Roman">1.1 </font></span><span style="font-family: 黑体">注释</span></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">单行注释：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;## This is a single line comment.</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">多行注释：</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;#*&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;&nbsp; Thus begins a multi-line comment. Online visitors won&rsquo;t</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;&nbsp; see this text because the Velocity Template Engine will ignore it.</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;*#&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">文档格式：</span><font face="Times New Roman">&nbsp; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;#**&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;&nbsp; This is a VTL comment block and&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;&nbsp; may be used to store such information as the document author </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 42pt"><font face="Times New Roman">and versioning information:&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;&nbsp; @version 5&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;&nbsp; @author&nbsp;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&nbsp;*#&nbsp;</font></p>
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><font face="Times New Roman"><span style="font-weight: normal">1.2 </span>References</font></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">在</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中有三种类型的</span><font face="Times New Roman">references</font><span style="font-family: 宋体">：变量</span><font face="Times New Roman">(variables)</font><span style="font-family: 宋体">、属性</span><font face="Times New Roman">(properties)</font><span style="font-family: 宋体">、方法</span><font face="Times New Roman"> (methods)</font><span style="font-family: 宋体">。作为一个使用</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">的页面设计者，你和你的工程师必须就</span><font face="Times New Roman">references</font><span style="font-family: 宋体">的名称达成共识，以便你可以在你的</span><font face="Times New Roman">template</font><span style="font-family: 宋体">中使用它们。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中一切</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">可以作为一个</span><font face="Times New Roman">String</font><span style="font-family: 宋体">对象处理。如果有一个对象</span><font face="Times New Roman">$foo</font><span style="font-family: 宋体">是一个</span><font face="Times New Roman">Integer</font><span style="font-family: 宋体">对象，那么</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">将调用它的</span><font face="Times New Roman">toString()</font><span style="font-family: 宋体">方法将这个对象转型为</span><font face="Times New Roman">String</font><span style="font-family: 宋体">类型。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.2.1 </font></span><span style="font-family: 黑体">变量</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">格式要求同</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.1 </font></span><span style="font-family: 黑体">属性</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">例子：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$customer.Address</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$purchase.Total</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$customer.Address</font><span style="font-family: 宋体">有两种含义。它可以表示：查找</span><font face="Times New Roman">hashtable</font><span style="font-family: 宋体">对象</span><font face="Times New Roman">customer</font><span style="font-family: 宋体">中以</span><font face="Times New Roman">Address</font><span style="font-family: 宋体">为关键字的值；也可以表示调用</span><font face="Times New Roman">customer</font><span style="font-family: 宋体">对象的</span><font face="Times New Roman"> getAddress()</font><span style="font-family: 宋体">方法。当你的页面被请求时，</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">将确定以上两种方式选用那种，然后返回适当的值。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.2 </font></span><span style="font-family: 黑体">方法</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">一个方法就是被定义在</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">中的一段代码，并且它有完成某些有用工作的能力，例如一个执行计算和判断条件是否成立、满足等。方法是一个由</span><font face="Times New Roman">$</font><span style="font-family: 宋体">开始并跟随</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">标识符组成的</span><font face="Times New Roman">References</font><span style="font-family: 宋体">，一般还包括一个</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">方法体。例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$customer.getAddress()</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$purchase.getTotal()</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$page.setTitle( &ldquo;My Home Page&rdquo; )</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$person.setAttributes( [&ldquo;Strange&rdquo;, &ldquo;Weird&rdquo;, &ldquo;Excited&rdquo;] )</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">前两个例子</span><font face="Times New Roman">$customer.getAddress()</font><span style="font-family: 宋体">和</span><font face="Times New Roman">$purchase.getTotal()</font><span style="font-family: 宋体">看起来挺想上面的属性</span><font face="Times New Roman">$customer.Address </font><span style="font-family: 宋体">和</span><font face="Times New Roman"> $purchase.Total</font><span style="font-family: 宋体">。如果你觉得他们之间有某种联系的话，那你是正确的。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">VTL</font><span style="font-family: 宋体">属性可以作为</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">方法的缩写。</span><font face="Times New Roman">$customer.Address</font><span style="font-family: 宋体">属性和使用</span><font face="Times New Roman">$customer.getAddress()</font><span style="font-family: 宋体">方法具有相同的效果。如果可能的话使用属性的方式是比较合理的。属性和方法的不同点在于你能够给一个方法指定一个参数列表。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.1 </font></span><span style="font-family: 黑体">正式</span><span style="font-family: 宋体">reference</span><span style="font-family: 黑体">标记</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">re</span><font face="Times New Roman">ference</font><span style="font-family: 宋体">的</span><span style="font-family: 宋体">正式</span><span style="font-family: 宋体">格式如下：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">${mudSlinger}</font><span style="font-family: 宋体">变量</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">${customer.Address}</font><span style="font-family: 宋体">属性</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">${purchase.getTotal()}</font><span style="font-family: 宋体">方法</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">非</span><span style="font-family: 宋体">正式</span><span style="font-family: 宋体">格式更见常用，但是有时还是使用正是格式比较适合。例如：你希望通过一个变量</span><font face="Times New Roman">$vice</font><span style="font-family: 宋体">来动态的组织一个字符串。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">Jack is a $vicemaniac. </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">本来变量是</span><font face="Times New Roman">$vice</font><span style="font-family: 宋体">现在却变成了</span><font face="Times New Roman">$vicemaniac</font><span style="font-family: 宋体">，这样</span><font face="Times New Roman">Veloctiy</font><span style="font-family: 宋体">就不知道您到底要什么了。所以，应该使用正是格式书写</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">Jack is a ${vice}maniac </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">现在</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">知道变量是</span><font face="Times New Roman">$vice</font><span style="font-family: 宋体">而不是</span><font face="Times New Roman">$vicemania</font><span style="font-family: 宋体">c</span><span style="font-family: 宋体">。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.2 </font></span><span style="font-family: 宋体">Quiet reference notation</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">例</span><span style="font-family: 宋体">如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;input type=&rdquo;text&rdquo; name=&rdquo;email&rdquo; value=&rdquo;$email&rdquo; /&gt;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">当页面的</span><font face="Times New Roman">form</font><span style="font-family: 宋体">被初始加载时，变量</span><font face="Times New Roman">$email</font><span style="font-family: 宋体">还没有值，这时你肯定是希望它能够显示一个空白来代替输出</span><font face="Times New Roman">&rdquo;$email&rdquo;</font><span style="font-family: 宋体">这样的字段。那么使用</span><font face="Times New Roman">quiet reference notation</font><span style="font-family: 宋体">就比较合适。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;input type=&rdquo;text&rdquo; name=&rdquo;email&rdquo; value=&rdquo;$!email&rdquo;/&gt;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">这样文本框的初始值就不会是</span><font face="Times New Roman">email</font><span style="font-family: 宋体">而是空值了。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">正式和</span><font face="Times New Roman">quiet</font><span style="font-family: 宋体">格式的</span><font face="Times New Roman">reference notation</font><span style="font-family: 宋体">也可一同使用，像下面这样：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;input type=&rdquo;text&rdquo; name=&rdquo;email&rdquo; value=&rdquo;$!{email}&rdquo;/&gt;</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><br />
&nbsp;</p>
<div id="textstyle_22444" style="margin-top: 20px; font-size: 9pt; min-height: 150px; text-indent: 24px; line-height: 22px">
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><font face="Times New Roman"><span style="font-weight: normal">1.1.1 </span>Getting literal</font></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">使用特殊字符</span><font face="Times New Roman">$</font><span style="font-family: 宋体">和</span><font face="Times New Roman">#</font><span style="font-family: 宋体">来帮助它工作，所以如果要在</span><font face="Times New Roman">template</font><span style="font-family: 宋体">里使用这些特殊字符要格外小心。本节将讨论</span><font face="Times New Roman">$</font><span style="font-family: 宋体">字符。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">在</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中使用</span><font face="Times New Roman">$2.5</font><span style="font-family: 宋体">这样的货币标识是没有问题得的，</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">不会将它错认为是一个</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">，因为</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中的</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">总是以一个大写或者小写的字母开始。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中使用</span><font face="Times New Roman">&ldquo;&quot;&rdquo;</font><span style="font-family: 宋体">作为转义字符。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $email = &ldquo;foo&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">将输出为：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">foo </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;foo </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">如果</span><font face="Times New Roman">email</font><span style="font-family: 宋体">变量没有被定义则</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">将被输出为：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&quot;&quot;&quot;$email </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">注意：</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中未被定义的变量将被认为是一个字符串，所以以下例子：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $foo = &ldquo;gibbous&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$moon = $foo </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">的输出结果是：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$moon = gibbous </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">现在你已经对</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">比较熟悉了，你可以将他们高效的应用于你的</span><font face="Times New Roman">template</font><span style="font-family: 宋体">了。</span><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">利用了很多</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">规范以方便了设计人员的使用。例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo.getBar()</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">##</font><span style="font-family: 宋体">与下面这句相同</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo.Bar</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$data.getUser(&ldquo;john&rdquo;)</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">##</font><span style="font-family: 宋体">与下面这句相同</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$data.User(&ldquo;john&rdquo;)</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$data.getRequest().getServerName() </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#</font><span style="font-family: 宋体">与下面这句相同</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$data.Request.ServerName </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">##</font><span style="font-family: 宋体">与下面这句相同</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">${data.Request.ServerName} </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">但是，注意</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">中不会将</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">解释为对象的实例变量。例如：</span><font face="Times New Roman">$foo.Name</font><span style="font-family: 宋体">将被解释为</span><font face="Times New Roman">Foo</font><span style="font-family: 宋体">对象的</span><font face="Times New Roman">getName</font><span style="font-family: 宋体">（）方法，而不是</span><font face="Times New Roman">Foo</font><span style="font-family: 宋体">对象的</span><font face="Times New Roman">Name</font><span style="font-family: 宋体">实例变量。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><br />
&nbsp;</p>
<h2 style="margin: 6pt 0cm 6pt 28.8pt"><font face="Times New Roman"><span style="font-weight: normal">1.1 </span>Directives</font></h2>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">Reference</font><span style="font-family: 宋体">允许设计者使用动态的内容，而</span><font face="Times New Roman">directive</font><span style="font-family: 宋体">使得你可以应用</span><font face="Times New Roman">.NET</font><span style="font-family: 宋体">代码来控制你的显示逻辑，从而达到你所期望的显示效果。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.1 </font></span><span style="font-family: 黑体">赋值</span><font face="Times New Roman">#set</font></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set directive</font><span style="font-family: 宋体">被用于设置一个</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">的值。例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $primate = &ldquo;monkey&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $customer.Behavior = $primate ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">赋值左侧的（</span><font face="Times New Roman">LHS</font><span style="font-family: 宋体">）必须是一个变量或者属性</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">。右侧（</span><font face="Times New Roman">RHS</font><span style="font-family: 宋体">）可以是以下类型中一种：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">变量</span><font face="Times New Roman">reference</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">字符串</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">属性</span><font face="Times New Roman">reference</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">方法</span><font face="Times New Roman">reference</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">数字</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">ArrayList</span></p>
<div id="textstyle_22446" style="margin-top: 20px; font-size: 9pt; min-height: 150px; text-indent: 24px; line-height: 22px">
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-family: 宋体">下面是应用各种类型的RHS的例子：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃</span><font face="Times New Roman">set ( $monkey = $bill ) ##</font><span style="font-family: 宋体">变量</span><font face="Times New Roman">reference </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃</span><font face="Times New Roman">set ( $monkey.Friend = &ldquo;monica&rdquo; ) ##</font><span style="font-family: 宋体">字符串</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃</span><font face="Times New Roman">set ( $monkey.Blame = $whitehouse.Leak ) ##</font><span style="font-family: 宋体">属性</span><font face="Times New Roman">reference </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃</span><font face="Times New Roman">set ( $monkey.Plan = $spindoctor.weave($web) ) ##</font><span style="font-family: 宋体">方法</span><font face="Times New Roman">reference </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃</span><font face="Times New Roman">set ( $monkey.Number = 123 ) ##</font><span style="font-family: 宋体">数字</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">＃</span><font face="Times New Roman">set ( $monkey.Say = [&ldquo;Not&rdquo;, $my, &ldquo;fault&rdquo;] ) ##ArrayList </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">注意：最后一个例子的取值方法为：</span><font face="Times New Roman">$monkey.Say.get(0) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">RHS</font><span style="font-family: 宋体">也可以是一个简单的算术表达式：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $value = $foo + 1 ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $value = $bar -1 ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $value = $foo * $bar ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $value = $foo / $bar ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">如果你的</span><font face="Times New Roman">RHS</font><span style="font-family: 宋体">是一个</span><font face="Times New Roman">null</font><span style="font-family: 宋体">，</span><font face="Times New Roman">VTL</font><span style="font-family: 宋体">的处理将比较特殊：它将指向一个已经存在的</span><font face="Times New Roman">reference</font><span style="font-family: 宋体">，这对初学者来讲可能是比较费解的。例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $resut = $query.criteria(&ldquo;name&rdquo;) ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">结果是</span><font face="Times New Roman">$result </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $resut = $query.criteria(&ldquo;address&rdquo;) ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">结果是</span><font face="Times New Roman">$result </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">如果</span><font face="Times New Roman">$query.criteria(&ldquo;name&rdquo;)</font><span style="font-family: 宋体">返回一个</span><font face="Times New Roman">&ldquo;bill&rdquo;</font><span style="font-family: 宋体">，而</span><font face="Times New Roman">$query.criteria(&ldquo;address&rdquo;)</font><span style="font-family: 宋体">返回的是</span><font face="Times New Roman">null</font><span style="font-family: 宋体">，则显示的结果如下：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">结果是</span><font face="Times New Roman">bill </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">结果是</span><font face="Times New Roman">bill </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">看看下面的例子：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $criteria = [&quot;name&quot;, &quot;address&quot;] ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#foreach( $criterion in $criteria ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $result = $query.criteria($criterion) ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#if( $result ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">Query was successful </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#end </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#end </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">在上面的例子中，程序将不能智能的根据</span><font face="Times New Roman">$result</font><span style="font-family: 宋体">的值决定查询是否成功。在</span><font face="Times New Roman">$result</font><span style="font-family: 宋体">被</span><font face="Times New Roman">#set</font><span style="font-family: 宋体">后（</span><font face="Times New Roman">added to the context</font><span style="font-family: 宋体">），它不能被设置回</span><font face="Times New Roman">null</font><span style="font-family: 宋体">（</span><font face="Times New Roman">removed from the context</font><span style="font-family: 宋体">）。打印的结果将显示两次查询结果都成功了，但是实际上有一个查询是失败的。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">为了解决以上问题我们可以通过预先定义的方式：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $criteria = [&ldquo;name&rdquo;, &ldquo;address&rdquo;] ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#foreach( $criterion in $criteria ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $result = false ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set( $result = $query.criteria( $criterion ) ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#if( $result ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">Query was successful </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#end </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#end</font></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.1 </font></span><span style="font-weight: normal; font-family: 黑体">字符串</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">当你使用</span><font face="Times New Roman">#set directive</font><span style="font-family: 宋体">，字符串封闭在一对双引号内。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $directoryRoot = &ldquo;www&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $templateName = &ldquo;index.vm&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $template = &ldquo;$directoryRoot/$tempateName&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$template </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">上面这段代码的输出结果为：</span><font face="Times New Roman">www/index.vm</font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">但是，当字符串被封装在单引号内时，它将不被解析：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $foo = &ldquo;bar&rdquo; ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#set ( $blargh = &lsquo;$foo' ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">结果：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">bar </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">上面这个特性可以通过修改</span><font face="Times New Roman">Views</font><span style="font-family: 宋体">目录下的</span><font face="Times New Roman">nvelocity.properties</font><span style="font-family: 宋体">文件的</span><font face="Times New Roman">stringliterals.interpolate = false</font><span style="font-family: 宋体">的值来改变上面的特性是否有效。</span></p>
<h3 style="margin: 7pt 0cm 0pt; text-indent: 0cm"><font size="5"><span style="font-weight: normal"><font face="Times New Roman">1.1.2 </font></span><span style="font-family: 黑体">条件语句</span></font></h3>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">if/elseif/else </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">当一个</span><font face="Times New Roman">web</font><span style="font-family: 宋体">页面被生成时使用</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">的</span><font face="Times New Roman">#if directrive</font><span style="font-family: 宋体">，如果条件成立的话可以在页面内嵌入文字。例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#if ( $foo ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;strong&gt;nVelocity!&lt;/strong&gt; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#end </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">上例中的条件语句将在以下两种条件下成立：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo</font><span style="font-family: 宋体">是一个</span><font face="Times New Roman">boolean</font><span style="font-family: 宋体">型的变量，且它的值为</span><font face="Times New Roman">true </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">$foo</font><span style="font-family: 宋体">变量的值不为</span><font face="Times New Roman">null </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">这里需要注意一点：</span><font face="Times New Roman">Velocity context</font><span style="font-family: 宋体">仅仅能够包含对象，所以当我们说</span><font face="Times New Roman">&ldquo;boolean&rdquo;</font><span style="font-family: 宋体">时实际上代表的时一个</span><font face="Times New Roman">Boolean</font><span style="font-family: 宋体">对象。即便某个方法返回的是一个</span><font face="Times New Roman">boolean</font><span style="font-family: 宋体">值，</span><font face="Times New Roman">Velocity</font><span style="font-family: 宋体">也会利用内省机制将它转换为一个</span><font face="Times New Roman">Boolean</font><span style="font-family: 宋体">的相同值。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">如果条件成立，那么</span><font face="Times New Roman">#if</font><span style="font-family: 宋体">和</span><font face="Times New Roman">#end</font><span style="font-family: 宋体">之间的内容将被显示。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#elseif</font><span style="font-family: 宋体">和</span><font face="Times New Roman">#else</font><span style="font-family: 宋体">元素可以同</span><font face="Times New Roman">#if</font><span style="font-family: 宋体">一同使用。例如：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#if( $foo &lt; 10 ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;strong&gt; Go North &lt;/strong&gt; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#elseif( $foo == 10 ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;strong&gt; Go East &lt;/strong&gt; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#elseif( $foo == 6 ) </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;strong&gt; Go South &lt;/strong&gt; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#else </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">&lt;strong&gt; Go West &lt;/strong&gt; </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><font face="Times New Roman">#end </font></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 24pt"><span style="font-family: 宋体">注意这里的</span><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">的数字是作为</span><font face="Times New Roman">Integer</font><span style="font-family: 宋体">来比较的</span><font face="Times New Roman">――</font><span style="font-family: 宋体">其他类型的对象将使得条件为</span><font face="Times New Roman">false</font><span style="font-family: 宋体">，它使用</span><font face="Times New Roman">&ldquo;</font><span style="font-family: 宋体">＝＝</span><font face="Times New Roman">&rdquo;</font><span style="font-family: 宋体">来比较两个值，而且</span><font face="Times New Roman">nVelocity</font><span style="font-family: 宋体">要求等号两边的值类型相同。</span></p>
</div>
</div>
</div>]]></description>
		</item>
		
</channel>
</rss>
