最近在做新加坡的一個項目,自己做了Tab控件,寫了很多共通的東西。包括WebForm仿MVC ModelBinder功能。今天起了個早,寫微博跟大家分享下,也請大家提出寶貴的意見。
去年學過Asp.Net MVC,里面有個非常有意思的功能,就是ModelBinder。它的表現形式是一方面VS會根據具體的某個Model類型生成相應的頁面,另一方面VS也能將頁面控件的值自動綁定到后台Model里(本人只知道怎么用,具體的原理說明不是很清楚,哪位博友可以分享這方面的文章)。當時覺得很好、很強大。在我接觸的寥寥無幾的幾個項目中基本上是使用的WebForm模式。最初的做法就是手動的給服務器端控件復制或者將服務器端控件的值付給Model,這樣很繁瑣,做起來很煩,也很無趣。感覺自己就像coding的機器一樣。
后來我想到了Asp.Net的反射技術,又查閱了關於Reflection的文章,於是寫出了下面的兩個靜態方法。這兩個方法放在工具類里面。
第一個方法是將Model的值自動付給服務器端控件,代碼如下:
/// <summary> /// bind the properties to the page controls automatically /// @copyright gates.li /// </summary> /// <param name="listType">the type</param> /// <param name="page">the page object</param> public static void ModelAutoBindControls(IModel model,Page page) { Type listType = model.GetType(); //Get element properties and add datatable columns PropertyInfo[] properties = listType.GetProperties(); foreach (PropertyInfo property in properties) { string propertyName = property.Name; Control c = page.FindControl("tb" + propertyName); if (c != null) { TextBox tb = c as TextBox; if (tb != null) tb.Text = property.GetValue(model, null) == null ? "" : property.GetValue(model, null).ToString(); } else { c = page.FindControl("lb" + propertyName); Label label = c as Label; if (label != null) label.Text = property.GetValue(model, null) == null ? "" : property.GetValue(model, null).ToString(); } } }
第二個方法是將服務器端控件的值自動綁定到后台Model上,代碼如下:
/// <summary> /// bind the values of the page controls to the model automatically /// @copyright gates.li /// </summary> /// <param name="model"></param> /// <param name="page"></param> public static void ControlsAutoBindModel(IModel model, Page page) { Type listType = model.GetType(); //Get element properties and add datatable columns PropertyInfo[] properties = listType.GetProperties(); foreach (PropertyInfo property in properties) { string propertyName = property.Name; Control c = page.FindControl("tb" + propertyName); if (c != null) { TextBox tb = c as TextBox; if (tb != null) { property.SetValue(model, tb.Text.Trim(), null); } } } }
大家仔細看上面的兩個方法會發現IModel接口,這是我公司系統架構的體現。它是所有實體類的一個基類,具體代碼如下:
public interface IModel { string validatemessage { get; set; } bool validate(); }
我們項目中的所有Model類是使用代碼生成器生成,它們會自動實現該接口。
上面兩個方法的原理很簡單:兩個遍歷,一個約定。
兩個遍歷:
第一個遍歷:傳進去的Model的屬性的遍歷。
第二個遍歷:頁對象Page中Control的遍歷。
一個約定:命名規則的約定
服務器端的TextBox控件命名規則是”tb”+Model的屬性名。
服務器端的Label控件的名字是以”lb”+Model的屬性名。
下次有機會分享自己開發的Tab Control。/tx