利用反射實現頁面控件與實體之間的綁定


前言:

     在項目開發過程中,有一項任務是我們要反復執行的:獲取窗體控件的值,然后賦值到實體,再把實體值保存到數據庫;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