前言:
在項目開發過程中,有一項任務是我們要反復執行的:獲取窗體控件的值,然后賦值到實體,再把實體值保存到數據庫;load的時候,還有獲取實體,再把實體屬性值賦值到控件。如下所示:
1、獲取窗體控件的值,然后賦值到實體

1 public partial class TestEdit : Page 2 { 3 private readonly StudentService service = new StudentService(); 4 private Student student = new Student(); 5 6 protected void Page_Load(object sender, EventArgs e) 7 { 8 if (!IsPostBack && !string.IsNullOrEmpty(Request["ID"])) 9 { 10 student = service.GetStudentById(Request["ID"]); 11 if (student == null) 12 return; 13 14 txtName.Text = student.Name; 15 ddlSex.SelectedValue = student.Sex; 16 txtAge.Text = student.Age.ToString(); 17 ddlDegree.SelectedValue = student.Degree; 18 19 //省略其他 20 } 21 } 22 23 protected void BtnSave_Click(object sender, EventArgs e) 24 { 25 26 student.Name = txtName.Text; 27 student.Sex = ddlSex.SelectedValue; 28 student.Age = int.Parse(txtAge.Text); 29 student.Degree = ddlDegree.SelectedValue; 30 //省略其他 31 32 service.Save(student); 33 } 34 }
想象一下,如果1個表有幾十上百個字段,這樣賦值是多么繁瑣的事情呀。
下面,我就跟大家講一下,如果利用反射實現ASP.NET控件與實體之間的綁定,如果你還不熟悉反射,園子里關於反射的文章也比較多,可以去找。
正文:
一、下面先看一下利用反射后的代碼:

1 public partial class TestEdit : Page 2 { 3 private readonly StudentService service = new StudentService(); 4 private Student student = new Student(); 5 6 protected void Page_Load(object sender, EventArgs e) 7 { 8 if (!IsPostBack && !string.IsNullOrEmpty(Request["ID"])) 9 { 10 student = service.GetStudentById(Request["ID"]); 11 ExtensionService.BindObjectToControls(student, this); 12 } 13 } 14 15 protected void BtnSave_Click(object sender, EventArgs e) 16 { 17 ExtensionService.BindControlsToObject(student, this); 18 service.Save(student); 19 } 20 }
通過前后代碼的對比,是不是簡潔了很多?
二、開始搭建我們的程序
說明:為了簡單介紹這個例子,沒有用ORM技術,直接用sql操作Access數據庫
(1)、項目結構:
DBTest.accdb:為access數據庫,有一個表TBL_Student,結構如下
DBHelper.cs:操作數據庫幫助類
ExtensionService.cs:關鍵類,封裝反射相關方法
Student.cs:實體類
StudentService.cs:Student服務類,操作Student實體
TestEdit.aspx:測試頁面
(2)關鍵代碼講解
1、ExtensionService類主要包含2個方法,直接上代碼

1 public static class ExtensionService 2 { 3 /// <summary> 4 /// 將控件值綁定到業務對象 5 /// </summary> 6 /// <param name="obj">業務對象</param> 7 /// <param name="container">窗體或控件容器</param> 8 public static void BindControlsToObject(object obj, Control container) 9 { 10 if (obj == null) return; 11 Type objType = obj.GetType(); 12 13 PropertyInfo[] objPropertyArray = objType.GetProperties(); 14 15 foreach (PropertyInfo propertyInfo in objPropertyArray) 16 { 17 //根據對象屬性去查找控件 18 Control control = container.FindControl(propertyInfo.Name); 19 20 if (control == null) continue; 21 22 // ListControl是CheckBoxList、DropDownList、ListBox 和 RadioButtonList 的基類 23 if (control is ListControl) 24 { 25 var listControl = (ListControl)control; 26 if (listControl.SelectedItem != null) 27 { 28 var stringBuilder = new StringBuilder(); 29 for (int i = 0; i < listControl.Items.Count; i++) 30 { 31 if (listControl.Items[i].Selected) 32 { 33 stringBuilder.Append(listControl.Items[i].Value).Append(","); 34 } 35 } 36 37 Type propertyType = propertyInfo.PropertyType; 38 39 if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 40 { 41 //判斷是否為 System.Nullable 類型 42 propertyType = propertyType.GetGenericArguments()[0]; 43 44 if (string.IsNullOrEmpty(stringBuilder.ToString())) 45 { 46 propertyInfo.SetValue(obj, null, null); 47 continue; 48 } 49 } 50 object objValue = Convert.ChangeType(stringBuilder.ToString().Trim(','), propertyType); 51 propertyInfo.SetValue(obj, objValue, null); 52 } 53 } 54 else 55 { 56 Type controlType = control.GetType(); 57 PropertyInfo[] controlPropertyArray = controlType.GetProperties(); 58 59 GetControlProperty(obj, propertyInfo, control, controlPropertyArray); 60 61 } 62 } 63 } 64 65 /// <summary> 66 /// 將對象值綁定到頁面控件(進行中) 67 /// </summary> 68 /// <param name="obj">業務對象</param> 69 /// <param name="container">窗體或控件容器</param> 70 public static void BindObjectToControls(object obj, Control container) 71 { 72 if (obj == null) return; 73 Type objType = obj.GetType(); 74 75 PropertyInfo[] objPropertyArray = objType.GetProperties(); 76 foreach (PropertyInfo propertyInfo in objPropertyArray) 77 { 78 //根據對象屬性去查找控件 79 Control control = container.FindControl(propertyInfo.Name); 80 81 if (control == null) continue; 82 83 if (control is ListControl) 84 { 85 var listControl = (ListControl)control; 86 string propertyValue = propertyInfo.GetValue(obj, null).ToString(); 87 string[] values = propertyValue.Split(','); 88 if (values.Length == 0) continue; 89 90 foreach (string value in values) 91 { 92 ListItem listItem = listControl.Items.FindByValue(value); 93 if (listItem != null) 94 { 95 listItem.Selected = true; 96 } 97 } 98 } 99 else 100 { 101 Type controlType = control.GetType(); 102 PropertyInfo[] controlPropertyArray = controlType.GetProperties(); 103 SetControlProperty(obj, propertyInfo, control, controlPropertyArray); 104 105 } 106 } 107 } 108 109 /// <summary> 110 /// 將實體對象的屬性值賦值給頁面控件 111 /// </summary> 112 /// <param name="obj"></param> 113 /// <param name="objProperty"></param> 114 /// <param name="control"></param> 115 /// <param name="controlPropertyArray"></param> 116 private static void SetControlProperty(object obj, PropertyInfo objProperty, Control control, IEnumerable<PropertyInfo> controlPropertyArray) 117 { 118 Dictionary<string, Type> list = GetPropertyList(); 119 120 foreach (var dict in list) 121 { 122 // 在整個控件屬性中進行迭代,檢查控件匹配名稱和類型的屬性 123 var propertys = from p in controlPropertyArray 124 where p.Name == dict.Key && p.PropertyType == dict.Value 125 select p; 126 127 if (propertys.Count() == 0) 128 continue; 129 130 PropertyInfo controlProperty = propertys.First(); 131 132 controlProperty.SetValue(control, Convert.ChangeType(objProperty.GetValue(obj, null), dict.Value), null); 133 134 } 135 136 } 137 138 /// <summary> 139 /// 獲取頁面控件的值,並賦值給實體對象 140 /// </summary> 141 /// <param name="obj"></param> 142 /// <param name="objProperty"></param> 143 /// <param name="control"></param> 144 /// <param name="controlPropertyArray"></param> 145 private static void GetControlProperty(object obj, PropertyInfo objProperty, Control control, IEnumerable<PropertyInfo> controlPropertyArray) 146 { 147 //控件值屬性集合及其類型 148 Dictionary<string, Type> list = GetPropertyList(); 149 150 foreach (var dict in list) 151 { 152 // 檢查控件匹配名稱和類型的屬性 153 var propertys = from p in controlPropertyArray 154 where p.Name == dict.Key && p.PropertyType == dict.Value 155 select p; 156 157 if (propertys.Count() == 0) 158 continue; 159 160 PropertyInfo controlProperty = propertys.First(); 161 // 將控件的屬性設置為 162 // 業務對象屬性值 163 Type propertyType = objProperty.PropertyType; 164 165 try 166 { 167 //判斷是否為 System.Nullable 類型 168 if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 169 { 170 propertyType = propertyType.GetGenericArguments()[0]; 171 172 if (string.IsNullOrEmpty(controlProperty.GetValue(control, null).ToString())) 173 { 174 //當屬性的類型為 System.Nullable,且值為空/null時,設置屬性值為null 175 objProperty.SetValue(obj, null, null); 176 177 //賦值成功時,退出循環 178 break; 179 } 180 } 181 182 object objValue = Convert.ChangeType(controlProperty.GetValue(control, null), propertyType); 183 objProperty.SetValue(obj, objValue, null); 184 //賦值成功時,退出循環 185 break; 186 187 } 188 catch (Exception e) 189 { 190 throw new Exception(e.Message); 191 } 192 } 193 } 194 195 private static Dictionary<string, Type> GetPropertyList() 196 { 197 var list = new Dictionary<string, Type>(); 198 list.Add("Checked", typeof(bool)); 199 list.Add("Value", typeof(String)); 200 list.Add("Text", typeof(String)); 201 return list; 202 } 203 }
如果不了解反射的人,建議先去學習反射相關內容
BindControlsToObject(object obj, Control container)將控件值綁定到業務對象,代碼相關地方都有注釋,這里就不介紹了。
BindObjectToControls(object obj, Control container)將對象值綁定到頁面控件
2、TestEdit.aspx頁面

1 <table border="0"> 2 <tr> 3 <td> 4 用戶名 5 </td> 6 <td> 7 <asp:TextBox runat="server" ID="Name"></asp:TextBox> 8 </td> 9 </tr> 10 <tr> 11 <td> 12 性別 13 </td> 14 <td> 15 <asp:RadioButtonList ID="Sex" runat="server"> 16 <asp:ListItem Value="男" Selected="True" Text="男"></asp:ListItem> 17 <asp:ListItem Value="女" Text="女"></asp:ListItem> 18 </asp:RadioButtonList> 19 </td> 20 </tr> 21 <tr> 22 <td> 23 學位 24 </td> 25 <td> 26 <asp:DropDownList runat="server" ID="Degree"> 27 <asp:ListItem Value="小學" Text="小學"></asp:ListItem> 28 <asp:ListItem Value="初中" Text="初中"></asp:ListItem> 29 <asp:ListItem Value="高中" Text="高中"></asp:ListItem> 30 <asp:ListItem Value="大學" Text="大學"></asp:ListItem> 31 </asp:DropDownList> 32 </td> 33 </tr> 34 <tr> 35 <td> 36 愛好 37 </td> 38 <td> 39 <asp:CheckBoxList runat="server" ID="Hobby"> 40 <asp:ListItem Value="籃球">籃球</asp:ListItem> 41 <asp:ListItem Value="排球">排球</asp:ListItem> 42 <asp:ListItem Value="奶茶">奶茶</asp:ListItem> 43 </asp:CheckBoxList> 44 </td> 45 </tr> 46 <tr> 47 <td> 48 年齡 49 </td> 50 <td> 51 <asp:TextBox runat="server" ID="Age"></asp:TextBox> 52 </td> 53 </tr> 54 <tr> 55 <td colspan="2"> 56 <asp:Button runat="server" ID="BtnSave" Text="保存" OnClick="BtnSave_Click" /> 57 </td> 58 </tr> 59 </table>
需注意的是,控件的ID要與綁定對象的屬性一樣,如:<asp:TextBox runat="server" ID="Name"></asp:TextBox>,Name為Student的屬性。
后台代碼:

1 public partial class TestEdit : Page 2 { 3 private readonly StudentService service = new StudentService(); 4 private Student student = new Student(); 5 6 protected void Page_Load(object sender, EventArgs e) 7 { 8 if (!IsPostBack && !string.IsNullOrEmpty(Request["ID"])) 9 { 10 student = service.GetStudentById(Request["ID"]); 11 12 //將對象值綁定到頁面控件 13 ExtensionService.BindObjectToControls(student, this); 14 } 15 } 16 17 protected void BtnSave_Click(object sender, EventArgs e) 18 { 19 //將控件值綁定到業務對象 20 ExtensionService.BindControlsToObject(student, this); 21 service.Save(student); 22 } 23 }
終於把相關的代碼寫完了O(∩_∩)O哈哈~,下面進行測試
3、測試
打開TestEdit.aspx,錄入相關信息,如下圖:
保存成功,Student表多了一條記錄,如下:
最后,在地址欄輸入http://localhost:4500/TestEdit.aspx?ID=7,回車,剛才錄入的數據就出來了
結束語:
第一次寫博客,希望各位大牛指點。
作者:pengjunshe
出處:http://www.cnblogs.com/pengjunshe/archive/2012/08/03/2621419.html