利用反射实现页面控件与实体之间的绑定


前言:

     在项目开发过程中,有一项任务是我们要反复执行的:获取窗体控件的值,然后赋值到实体,再把实体值保存到数据库;load的时候,还有获取实体,再把实体属性值赋值到控件。如下所示:

 1、获取窗体控件的值,然后赋值到实体

View Code
 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控件与实体之间的绑定,如果你还不熟悉反射,园子里关于反射的文章也比较多,可以去找。

 

正文:

    一、下面先看一下利用反射后的代码:   

View Code
 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个方法,直接上代码

View Code
  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页面

View Code
 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的属性。

后台代码:

View Code
 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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM