前言:
在项目开发过程中,有一项任务是我们要反复执行的:获取窗体控件的值,然后赋值到实体,再把实体值保存到数据库;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