您還在為每次添加數據或者修改數據的時候,書寫大量的代碼判斷輸入是否合法而發愁嗎?
如果是,我這里可以為您提供一個好的解決方案。先看我列出的一個實體類例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Attributes; using System.Data; namespace Model { public class cms_article { [Model(Name = "ID", Empty = false, DataType = DbType.Int32, ErrorTip = "ID不能為空,且必須為整數", AutoIncrement = true, PrimaryKey = true)] public int ArticleID { get; set; } [Model(Name = "標題", Empty = false, DataType = DbType.String, MinLength = 2, MaxLength = 5, ErrorTip = "請為標題輸入2-5個字符,謝謝!")] public string ArticleTitle { get; set; } [Model(Name = "內容", Empty = false, DataType = DbType.String, Rule = @"^[\s\S]+$", ErrorTip = "內容不能為空")] public string ArticleContent { get; set; } [Model(Name = "發布日期", Empty = true, DataType = DbType.DateTime)] public DateTime ArticleDateTime { get; set; } [Model(Name = "所屬類別", Empty = false, DataType = DbType.Int32)] public int ClassID { get; set; } } }
看到這,知道我在唱哪出戲了吧?您可能會想到:特性(attribute)。對,就是它。我們可以巧用特性來處理大量的輸入判斷。如果您感興趣,繼續往下看吧。
有人也許會說,沒必要,我在客戶端用JS判斷就行了。大哥,省省吧。如果網站是面向互聯網的,您僅僅用JS判斷用戶的輸入,無疑是自掘墳墓。
******************************************************************************************
我們為什么要這么做?
試想,如果一個系統有幾十個,甚至幾百個表。您在進行添加或者修改的時候是不是要對用戶的輸入進行合法性的判斷?那是不是意味着每個Add()或者Update()方法里面都要寫很多判斷代碼??天呢,請原諒我,我沒有這么多時間來浪費我的青春了。。。那我們應該怎么做呢?這就是我們要解決的問題,也是我寫這篇文章的目的。
明白了我們要解決什么問題,下面的事情就好辦了。
我們如何做:
需要說明的是:您必須具備C#反射的知識,不然您是看不下去的。
還有,假設數據庫字段跟網頁的form表單元素是對應的,如果您不喜歡這么做,建議您不要往下看下去了,因為我覺得這是在浪費您的時間。
好,開始。我們先在大腦里,模擬用戶輸入數據,然后提交,然后在這里我們就要綁定Model了。
我們可以這么做:
//綁定Model Model.cms_article modelArticle = Lib.Model.Instance().BindModel<Model.cms_article>();
Model.cms_article是一個類型,比如:文章。BindModel是個靜態方法。
然后看BindModel方法:
/// <summary> /// 綁定Model /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public T BindModel<T>() where T : new() { T entity = new T(); PropertyInfo[] Properties = typeof(T).GetProperties();//獲取當前類型的所有屬性 //遍歷屬性集合 foreach (PropertyInfo Property in Properties) { //獲取屬性的值 string value = System.Web.HttpContext.Current.Request[Property.Name]; //獲取當前屬性所指定的特性 object[] attributes = Property.GetCustomAttributes(typeof(Attributes.ModelAttribute), false); if (attributes.Length > 0) { this.modelCheck.CheckInput(attributes[0] as Attributes.ModelAttribute, value); } //給實體賦值 if (value != null) { Property.SetValue(entity, Convert.ChangeType(value, (System.Nullable.GetUnderlyingType(Property.PropertyType) ?? Property.PropertyType)), null); } } return entity; }
先是根據反射獲取Model的所有屬性,遍歷循環
然后根據屬性獲取其所擁有的特性,如果當前屬性找到有特性存在,我們則遍歷所有特性。
在這里我不需要查找所有的特性,因為我知道我需要什么特性,所以我就取第一個特性attributes[0] as ModelAttribute。
再然后根據當前屬性所擁有的特性,對輸入的數據進行判斷。this.modelCheck.CheckInput(attributes[0] as Attributes.ModelAttribute, value);
/// <summary> /// 檢測輸入數據的合法性,統一在這里處理 /// </summary> /// <param name="modelAttribute"></param> /// <param name="value"></param> /// <returns></returns> public string CheckInput(Attributes.ModelAttribute modelAttribute, string value) { string str = string.Empty; //判斷是否允許為空,如果不允許為空 if (!modelAttribute.Empty) { this.CheckEmpty(modelAttribute, value); this.CheckType(modelAttribute, value); this.CheckLength(modelAttribute, value); this.CheckRule(modelAttribute, value); } else { if (!string.IsNullOrEmpty(value)) { this.CheckType(modelAttribute, value); this.CheckLength(modelAttribute, value); this.CheckRule(modelAttribute, value); } } return str; }
最后是利用我們所約定的規則進行判斷。
/// <summary> /// 檢測正則表達式 /// </summary> /// <param name="modelAttribute"></param> /// <param name="value"></param> private void CheckRule(Attributes.ModelAttribute modelAttribute, string value) { if (!string.IsNullOrEmpty(modelAttribute.Rule)) { if (!Common.RegexMatch(value, modelAttribute.Rule)) { Javascript.Alert(modelAttribute.ErrorTip, true); } } } /// <summary> /// 檢測長度 /// </summary> /// <param name="modelAttribute"></param> /// <param name="value"></param> private void CheckLength(Attributes.ModelAttribute modelAttribute, string value) { if (modelAttribute.MinLength > 0 || modelAttribute.MaxLength > 0) { if (value.Length < modelAttribute.MinLength || value.Length > modelAttribute.MaxLength) { Javascript.Alert(modelAttribute.ErrorTip, true); } } } /// <summary> /// 檢測是否為空 /// </summary> /// <param name="modelAttribute"></param> /// <param name="value"></param> private void CheckEmpty(Attributes.ModelAttribute modelAttribute, string value) { if (string.IsNullOrEmpty(value)) { Javascript.Alert(modelAttribute.ErrorTip, true); } } /// <summary> /// 判斷數據類型 /// </summary> /// <param name="modelAttribute"></param> /// <param name="value"></param> private void CheckType(Attributes.ModelAttribute modelAttribute, string value) { switch (modelAttribute.DataType) { case DbType.AnsiString: break; case DbType.AnsiStringFixedLength: break; case DbType.Binary: break; case DbType.Boolean: if (!Common.IsBool(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.Byte: break; case DbType.Currency: break; case DbType.Date: break; case DbType.DateTime: if (!Common.IsDateTime(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.DateTime2: break; case DbType.DateTimeOffset: break; case DbType.Decimal: if (!Common.IsDecimal(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.Double: if (!Common.IsDouble(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.Guid: break; case DbType.Int16: if (!Common.IsInt16(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.Int32: if (!Common.IsInt32(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.Int64: if (!Common.IsInt64(value)) { Javascript.Alert(modelAttribute.Name + "字段類型不對,謝謝!", true); } break; case DbType.Object: break; case DbType.SByte: break; case DbType.Single: break; case DbType.String: break; case DbType.StringFixedLength: break; case DbType.Time: break; case DbType.UInt16: break; case DbType.UInt32: break; case DbType.UInt64: break; case DbType.VarNumeric: break; case DbType.Xml: break; default: break; } }
思路很清晰吧?上面的這個方法就是我們的約定,因為有人說過:約定勝於配置。我覺得這幾個方法足可以應付日常的開發了。您覺得呢?