在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
ASP.NET使用动态编译技术,在运行时动态将同一目录的*.aspx文件先生成*.cs,然后调用CompilerServices将其编译成assemblies(可以到你的%SYSTEMROOT%\Microsoft.NET\Framework\V1.x.xxxx\Temporary ASP.NET Files下面看看)。因此了解ASP.NET编译的过程是优化ASP.NET运行效率的关键之一。以常用的数据绑定语法为例,我们可以发现它的转化规则是: .aspx: -> .cs: System.Convert.ToString(data-binding expression); 其中data-binding expression是原封不动复制过来的,这样你写数据绑定表达式的时候就心里有谱了吧。关于常见于数据绑定表达式中的Container、DataItem、DataBinder.Eval是这样:DataBinder是System.Web里面的一个静态类,它提供了Eval方法用于简化数据绑定表达式的编写,但是它使用的方式是通过Reflection等开销比较大的方法来达到易用性,因此其性能并不是最好的。而Container则根本不是任何一个静态的对象或方法,它是ASP.NET页面编译器在数据绑定事件处理程序内部声明的局部变量,其类型是可以进行数据绑定的控件的数据容器类型(如在Repeater内部的数据绑定容器叫RepeaterItem),在这些容器类中基本都有DataItem属性,因此你可以写Container.DataItem,这个属性返回的是你正在被绑定的数据源中的那个数据项。如果你的数据源是DataTable,则这个数据项的类型实际是DataRowView。 现在你可以想想下面哪种写法效率最高(以Repeater+DataTable数据源为例):
NOTE: 后两种用法需要引入System.Data名称空间……答案一天后揭晓,欢迎有空的朋友自己测试得出结论!
揭晓+简要分析:
乍一看1-3都是使用DataBinder.Eval方法来进行数据绑定计算,而4-5是使用strong type直接获取数据绑定的值。按照我之前的推理,很多朋友会认为4-5都会比1-3快,而实际上第4种用法也是在网上很常见的一种针对DataBinder.Eval而进行的“优化”。 实际上根据我们的测试,第4种写法的效率在某些很常见的情形下(即传入的字段名与数据表内部的字段名大小写有出入时)甚至比不上最普遍的第1种写法。不过原理还是对的,就是避免通过reflection或类似机制(如System.ComponentModel中的PropertyDescriptor机制)获得数据,然而使用DataRowView的indexer的效率在字段数量较多导致Hashtable产生寻址冲突时不如使用其Row属性(DataRow类型)的indexer的效率。原因是DataRowView的indexer实现了view的功能,而这个功能对于大多数应用在这个场合都是不需要的,且它的开销甚至比DataBinder.Eval还要大!(本段内容过于武断,在被反复质疑之下我又做了若干试验寻得正确原因)因此简单的使用第五种写法通常是可以获得较佳的性能的,而最好不要在不必要的时候直接使用DataRowView的indexer。 现在回到1-3的讨论。首先一点,请大家注意看Eval方法的二种overload: object DataBinder.Eval(object container, string expression) 注意到ASP.NET在生成的.cs文件中是使用System.Convert.ToString来将Eval的结果转换成string的,因此显式的提供值为null或String.Empty的format参数将使得Eval首先调用第一种方法得到绑定结果的对象,然后直接调用该对象的ToString()方法将其返回到Convert.ToString方法,对于该方法编译器已经在编译期将其连接到Convert.ToString(string)的重载上,而该方法则直接返回传入的字串。那如果直接使用第一种方法呢?虽然第二种方法是先调用第一种方法的,但是由于它的返回值是object类型,编译器将为其选择Convert.ToString(object)的重载,在这个重载方法中将进行一些额外的判断以将对象转换为string类型,而这些额外判断显然带来了额外的开销——尽管基本上算不得主要矛盾。 至于说第3种写法,由于在expression参数中多引入了一层间接,因此需要多进行一次反射以解析表达式,因此效率非常之低。 那这里再卖个关子,请推测第5种方法是否还可以进一步优化?(我是指在最常见的ASP.NET开发情形中):P 通过上面的分析,我们可以得到下面的结论:
各种格式化绑定方法: Text='<%# DataBinder.Eval(Container.DataItem, "common") %>' Text='<%# Bind("common") %>' Text=' <%# "string_add_test_" + ((System.Data.DataRowView)Container.DataItem)["common"] + "这种写法更高效" %>'> Text='<%# DataBinder.Eval(Container, "DataItem.HireDate","{0:yyyy年MM月dd日}") %>'> Text=' <%# Convert.ToDateTime(((System.Data.DataRowView)Container.DataItem)["HireDate"]).ToString("yyyy年MM月dd日") + "格式化" %>' Text=' <%# DataBinder.Eval(Container.DataItem, "Title").ToString().Trim().Length>7?DataBinder.Eval(Container.DataItem, "Title").ToString().Trim().Substring(0,7):DataBinder.Eval(Container.DataItem, "Title").ToString().Trim() %>' Text='<%# Convert.ToDecimal(((System.Data.DataRowView)Container.DataItem) ["UnitPrice"]).ToString("F2") %>' Checked = '<%# Convert.ToBoolean(((System.Data.DataRowView)Container.DataItem) ["check"]) %>' |
请发表评论