資料繫結似乎是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>
這樣做有四大優勢
- 得到編譯時間檢測
- 享受智能提示
- 強型別轉換比Eval反射效能更高
- 頁面中的表示更豐富,如上我們可以自由拼接想要的字串,非常像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改屬性名稱