不管你是对Windows Forms, ASP .NET, Web Services感兴趣, 还是对 .NET Framework感兴趣,这些技巧帮助你探索新的.NET技术。
By Dino Esposito

.NET Framework比以前更大了,包含了大量的类和方法,但是开发团体还没有探索和理解大多数的难以置信的软件特性,这些特性开始的时候也许是个bug或者设计缺陷,第二次出现的时候也许就被认为是一个重大的改进,包涵了更多的思考。

按照这不可避免的再优化过程,和其他开发者共享技巧是一个能够让你在建立你的第一个.NET应用程序时把握正确方法的途径,尽管它远远不能够提供你正在寻找的明确的解决方案。我总结了能够使你的.NET开发效率更高的十个技巧。为了能尽可能多的帮助开发人员,这些技巧覆盖了这项技术的整个范围,从ADO.NET到ASP.NET,从CLR到Framework,从Windows Forms到Web Services。这些技巧,再加上我可以预期的,将会对开发人员产生很大的影响。

#1建立你的DataGrid的页脚
DataGrid控件的页脚起着很重要的作用—也就是说,页脚能总结页面里的部分内容。除非你设置ShowFooter成True, 否则页脚是看不见的。一旦你设置了,页脚就会出现,但是它和其它行有同样数目的列。如果你觉得这个可以,那就没有问题。否则,你就需要给页脚增加字段或者去掉现有的字段。

OnItemCreated是关键的调用事件。它是事件处理程序的开始:

ListItemType itemType = _e.Item.ItemType;
if (itemType == ListItemType.Footer)
  {
     e.Item.Cells.RemoveAt(1);
     e.Item.Cells.RemoveAt(1);
     cellSummary.ColumnSpan = 3;
     e.Item.Cells[0].Text = "…";
   }

确保页脚建立时你能够干涉,然后取得在页脚行显示的实例。这样你就可以随意增加和减少单元了。别忘了把ColumnSpan属性设置成为列的初始值,以避免显示的问题,比如,页脚线比其它格子长或者短了。

#2 使用 Cache 对象而不使用 Application对象
在ASP中,你使用Application对象来发现全局事件和储存全局范围的数据。假设许多不同的用户可以访问同一个数据,你必须使用Lock 和Unlock方法来实现连续访问和避免访问冲突或者其它不可预测的结果。在ASP.NET中,和Application对象一起的,还有Cache对象,它和Application有相同的特征,但最终可以在不止一个场合来做Application的替代品。

Cache对象和Application对象都是集合数据容器,其内容能跨越页面和Session领域。他们都不支持Web farm和Web garden情况。Web farm是多个服务器运行一个应用程序的网络服务器结构。Web garden是同一个服务器上的多个进程运行一个程序。

和Application不同的是,Cache对象在应用程序的第一次调入时并没有实例化。仅当你使用它时它才会被创建。另外,Cache对象还可以尽可能地减小其数据项占有的内存空间。你可以给Cache设置相对的或绝对的有效期,也可以设置优先级和衰变因子。然后,你就对你的全局数据状态有了更大的控制能力,也能够执行在低内存状况下适度降级的特别方案。还有,就是,Cache对象是线程安全的,不需要加锁和解锁。

#3 用GET或POST调用服务
网络服务从根本上来说是一个你通过HTTP来连接的一个网址(URL)。当你为给定的网络服务建立了一个代理类,除非有其他方面的说明,命令行工具wsdl.exe给你提供了一个类,这个类使用SOAP协议使得可以远程调用网络服务。

尽管SOAP协议被认为是调用远程程序的标准,但是没有什么可以阻止你使用简单的GET或者POST方法来调用.NET网络服务。顺便说一下,POST命令传递SOAP有效负荷。

你可以在代理类中直接建立这个特征,只要当调用wsdl.exe 设备时,你转换协议为httpget或者httppost就可以了。封包类的源代码相应的调整。你也可以使用XmlHttpRequest对象和简单的脚本或者编译的代码来调用网络服务(更多信息,见资源):

Set http = _CreateObject("Microsoft.XMLHTTP")
  http.open "GET", "http://server/service.asmx/MethodName", false
  http.send ""
  MsgBox http.responseText

通过使用XmlHttpRequest,你可以通过Win32,脚本,总的来说,非.NET代码来连接网络服务。

#4 使用Cookieless Sessions
在ASP.NET中,Session对象参考一个软件配置实体,在那里你可以设置成进程中或者进程外模式。Session对象读取许多运行时设置,这些设置你可以存在Web server的framework的安装目录,或者存在从web.config文件得来的应用程序的BIN目录。web.config文件来决定许多ASP.NET组件的设置。如果你放config.web的拷贝在你的应用程序的当地子目录下,这个设置覆盖掉在framework目录中的默认设置。

你要配置的是Session管理器是否能够识别客户端使用cookies的 Session. 在应用程序的config.web文件中设置下面一行使Session管理器能够在不使用Cookie的情况下工作。

<sessionState cookieless="true" />

#5 使用定制的Grid分页
Web Form的DataGrid控件有内置的支持分页。它自动显示一个分页条,几乎不用写多少代码,就可以显示给定记录大小的页面。然而,默认的,所有必须的记录隐藏在DataGrid对象的DataSource属性中。这就意味 着你必须一次取回所有的数据。尽管当记录很少时这不是什么问题,但是当有成千上万条记录时,这就变成了一个问题。在这种情况下,你就必须手工取回记录,把他们存在磁盘里,而不是数据库管理系统。

你必须通知DataGrid这个特殊的行为。幸运的是,DataGrid提供了一个AllowCustomPagination属性,当这个属性设置成为True时,就会大大改变这个控件的内置行为。这时,grid总是从头到尾读取从DataSource属性中找到的记录。你应该用属于当前页的数据来补充这个容器。一般情况下,grid自己只取属于这页的从DataSource属性中取到的记录。

#6 从数据库中装入关键字信息
DataTable对象让你设置特定表的内存中的主键。这个行为加快了在DataTable和相关的DataView对象之间的搜索。另外一个好处就是阻止重复录入,它干扰表的完整性。这样,你在数据提交到数据库做一个批处理更新之前就有足够的时间来修正表,甚至向用户提供适当的警告。

你可以在批处理代码中手工设定这些信息:

// ds is an existing dataset
DataColumn[] keys = new DataColumn[1];
DataTable dt = ds.Tables["MyTable"];
keys[0] = dt.Columns["ID"];
dt.PrimaryKey = keys;

你可以在填充数据集时自动设置和检测主键信息。它是这样实现的:你设置数据适配器的MissingSchemaAction属性执行下面的查询代码来自动诊测信息。

SqlDataAdapter da = new SqlDataAdapter(strCmd, strConn);
DataSet ds = new DataSet();
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
da.Fill(ds, "MyTable");

#7 需要选择的Checkboxes
在ASP中,你有几个Checkboxes,都有相同的名字:

<input type="checkbox" name="foo" value="…">

你可以得到Checkbox的相应的值从下面的行代码:

<% a = split(Request.Form("foo"), ",")  %>

Request.Form("foo")返回一个用逗号隔离的字符串,这个字符串是所有选择项的串值形成的。你把这个字符串交给一个VBScript的分离函数,就得到一个易于管理的结构,比如数组。

同样的代码在ASP.NET中将没有办法运行。如果你使用<asp:checkbox>服务端控件。为了使它工作,使用HtmlInputCheckBox控件,写代码如下:

<type="checkbox" runat="server" name="foo" value="…"> 

即使asp:checkbox和input type="checkbox"服务端标签等价于同样的HTML代码,ASP.NET确保输出asp:checkbox和<asp>名字空间中的其它控件的标签的唯一的ID和名字。

#8 自动主表/详细表浏览
如果你在Windows Forms应用程序中用DataGrid控件来显示主表/详细表。其变化在于framework为你自动同步展示。

关键在于在两个表之间建立数据关联和用来定义详细表的数据源的组合表达式。我们假设你有两个表:Customers 和 Orders,其中都有CustID字段。你按照ADO .NET DataRelation对象建立一个关联:

// ds is an existing DataSet
Dim dc1, dc2 As DataColumn
dc1 = ds.Tables("Customers").Columns("custid")
dc2 = ds.Tables("Orders").Columns("custid")
Dim r As DataRelation
r = New DataRelation("OrdersByCustomer", dc1, dc2)
ds.Relations.Add(r)

不论何时你用DataRow对象表示主表(Customers)中的一行,在这种情况下,你可以根据关联,使用DataRow 的 GetChildRows方法得到子表的数据。就Windows Forms而言,这个编程过程中使用下面的代码:

dGrid.DataSource = ds
dGrid.DataMember = "Customers.OrdersByCustomer"

当你用表达式比如MasterTable.Relation连接详细子表,其内容就会自动地正确地更新。

#9 用类实现文件变更通知
.NET把 Win32文件通知类功能整合到FileSystemWatcher类上来。这些核心类主要负责当检测到系统文件层发生改变时通知客户端应用程序。按照特定的参数,当文件建立、修改、重命名或者删除时,通知对象发信号描述应用程序状态。

对于Win32程序来说,了解Windows NT 和indows 2000下有关文件的名称和有关事件的起因是困难的。所有这些在 .NET中被FileSystemWatcher类取代了。

FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = "c:\\";
watcher.Filter = "*.txt";
watcher.NotifyFilter = NotifyFilters.LastWrite;

一旦对象被配置后,你开始检测:

watcher.EnableRaisingEvents = true;

任何检测到的事件激活了应用程序事件。你可以象如下记录事件:

watcher.Changed += new FileSystemEventHandler(OnChanged);

事件处理程序参数提供你所需要的所有的文件和信息。

#10 编译代码
.NET Framework提供类,这些类可以让你用指定的语言编译代码。它们封包在System.CodeDom.Compiler名字空间里。下面代码片断显示了如何得到运行在内存中的C#编译器的实例:

CSharpCodeProvider csc = new CSharpCodeProvider();
ICodeCompiler icc = csc.CreateCompiler(); 

接着,你将设置CompilerParameters类的一些输入参数:

CompilerParameters co = new CompilerParameters();
co.OutputAssembly = "foo.exe";
co.ReferencedAssemblies.Add("system.dll");

你必须至少指明可执行的名称,设置GenerateExecutable为False如果你想要一个DLL, 并且增加集合列表供参考: icc.CompileAssemblyFromFile(co,csfile);

为了运行编译过程,使用CompileAssemblyFromFile(),传递给它参数和源文件名。你可以使用类CompilerResults以了解最新生成的集合的更多信息。


关于作者:
Dino Esposito是一个主要工作在意大利罗马的培训师和顾问。他也是即将被Microsoft出版社发行的ADO.NET书籍的作者,他花费了大部分的时间在为Wintellect网站教ASP.NET和ADO.NET课程。如果你有一些技术问题,你可以用dinoe@wintellect.com电子邮件地址联系他。