您还在为每次添加数据或者修改数据的时候,书写大量的代码判断输入是否合法而发愁吗?
如果是,我这里可以为您提供一个好的解决方案。先看我列出的一个实体类例子:
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; } }
思路很清晰吧?上面的这个方法就是我们的约定,因为有人说过:约定胜于配置。我觉得这几个方法足可以应付日常的开发了。您觉得呢?