强类型ASP.NET数据绑定

数据绑定似乎是ASP.NET老掉牙的东西了。可是你知道吗,只需要一点小小的改动就可以替换Eval,摆脱字符串依赖并且大大提高性能。

首先在code behind中加入以下方法

   
   
   
   
protected virtual object ExpHelper < TEntity, TREsult > (Func < TEntity, TREsult > func) { var itm = GetDataItem(); return func((TEntity)itm); }

这段代码就是最核心的秘诀了,你完全可以忽视它到底在做什么。其实就是截获每一个被绑定的数据项,并进行强类型转换。

假设我们定义了学生类

   
   
   
   
public class Student { public string Name { get ; set ; } public int Age { get ; set ; } }

如果希望在页面中使用强类型访问学生类而不是用Eval,定义专门访问学生的方法

   
   
   
   
protected object Stu < TResult > (Func < Student, TResult > func) { return ExpHelper < Student, TResult > (func); }

大功告成,于是在页面里我们就能这样绑定数据了

   
   
   
   
< ul > < asp:Repeater ID ="rptStudents" runat ="server" > < ItemTemplate > < li >< %#Stu (_ =>_.Name + "(" +_.Age+")")% ></ li > </ ItemTemplate > </ asp:Repeater > </ ul >

这样做有四大优势

  1. 得到编译时检测
  2. 享受智能提示
  3. 强类型转换比Eval反射性能更高
  4. 页面中的表示更丰富,如上我们可以自由拼接想要的字符串,非常像MVC

更神奇的是可以支持多层嵌套哦。比如我们定义学生的集合Group类和访问器,然后就能用嵌套的Repeater显示分组信息了。完整程序如下

   
   
   
   
< %@ Page Language ="C#" AutoEventWireup ="true" % > < script runat ="server" > public class Student { public string Name { get; set; } public int Age { get; set; } } public class Group { public IEnumerable < Student > Students { get; set; } } protected void Page_Load(object sender, EventArgs e) { //一群学生 var students = new[] { new Student{Name="mike",Age=23}, new Student{Name="jane", Age=12}, new Student{Name="frank",Age=25}, new Student{Name="susan",Age=32}, }; rptStudents.DataSource = students; //分两组 var group0 = new Group(); group0.Students = students.Take(2); var group1 = new Group(); group1.Students = students.Skip(2).Take(2); rptGroups.DataSource = new[] { group0, group1 }; DataBind(); } protected virtual object ExpHelper < TEntity , TREsult > (Func < TEntity , TREsult > func) { var itm = GetDataItem(); return func((TEntity)itm); } //Student访问器 protected object Stu < TResult > (Func < Student , TResult > func) { return ExpHelper < Student , TResult > (func); } //Group访问器 protected object Grp < TResult > (Func < Group , TResult > func) { return ExpHelper < Group , TResult > (func); } </ script > <! DOCTYPE html > < html > < body > < %-- 单层--% > < ul > < asp:Repeater ID ="rptStudents" runat ="server" > < ItemTemplate > < li >< %#Stu (_ =>_.Name + "(" +_.Age+")")% ></ li > </ ItemTemplate > </ asp:Repeater > </ ul > < %-- 嵌套--% > < ul > < asp:Repeater ID ="rptGroups" runat ="server" > < ItemTemplate > < li > < ol > < asp:Repeater ID ="Repeater1" runat ="server" DataSource ='<%#Grp(_=>_.Students) %>' > < ItemTemplate > < li >< %#Stu (_ =>_.Name + "(" +_.Age+")")% ></ li > </ ItemTemplate > </ asp:Repeater > </ ol > </ li > </ ItemTemplate > </ asp:Repeater > </ ul > </ body > </ html >

PS

本文是我以前写的没有发表的小发明,现在拿出来晒,主要是因为这个方法好像知道的人很少。希望大家能帮助测试一下性能,如果觉得合适大可以运用到实际工作中。

 

更新:

感谢Dacey 韦恩卑鄙 dudu老大等人的建议
我已添加了扩展方法版本。喜欢扩展方法这种空降兵的感觉。

现在只要添加一个static的帮助类,名字随你喜欢

   
   
   
   
public static class Helper { static object ExpHelper < TEntity, TResult > (Page page, Func < TEntity, TResult > func) { var itm = page.GetDataItem(); return func((TEntity)itm); } public static object Eval < T > ( this Page page, Func < T, object > func) { return ExpHelper < T, object > (page, func); } }

在页面中就可以

   
   
   
   
< %#this.Eval <Student > (_ => _.Name + "(" + _.Age + ")")%>
  • 注意this是必须的
  • 扩展方法具有很好的粘合性
  • 不需要一个父类定义通用方法
  • 泛型提供多个副本并且容易看清类型
  • 另外能很好的支持refactor,大家试试用ctrl+r+r改属性名
   
   
   
   

你可能感兴趣的:(server,object,Class,asp.net,扩展,asp)