首页 > 其他 > 详细

数据验证随想(续)

时间:2014-06-28 14:00:04      阅读:379      评论:0      收藏:0      [点我收藏+]

梳理需求

  关于这个想法,想看看历史背景的,请移步 《数据验证随想》

  今天要说的是这个组件在项目中的应用,以及后期对它的改善。在原来的想法中,希望做的大而全,结果越往后做,发现有点过度设计,写完代码后,楼主自己都懒得用。与其这么麻烦,还不如直接几个 if 判断完事。

  既然如此,只能将问题简单化。认真梳理一下楼主的需求:

  1. 部分参数是必需的,验证失败,中断,并返回该错误信息。

  2. 部分参数是非必需的。验证失败就直接忽略。这个需求来自于,表单里部分值是可以空的,或者传递了意外的值,试图忽略它。

  3. 验证成功后的参数,最好是能直接使用,而且类型都是转换后的。

解决方案

  先看看代码上是怎么调用的。

            var v = ValidateHelp.BeginEntity<PumpCodeEntity>()
                .IsNullOrEmpty(form["tybh"], "统一编号", "未找到需要修改的数据")
                .IsInt(form["zldm"], "指令代码", "指令代码错误")
                .IsInt(form["sfyx"], "是否有效", "有效指令错误");
            if (v.IsInValid) //数据无效
            {
                return new ResultDTO() { Message = v.Message};
            }
            ......

  其中form是MVC的FormCollection对象,没用过的理解成HttpRequest也成。

  PumpCodeEntity 是实体对象,呃,其中 “统一编号、指令代码、是否有效” 是这个对象的属性。为什么它会是中文,这个有项目背景,重点不是它啦。

  大家可以看到,其中有3个验证方法,方法带有3个参数,分别是:

  待验证的值 

  Key名或属性名(验证成功存储在Dictionary中, 或通过反射存储在对象中)

  错误消息提示  当未传递错误信息参数时,表示当前验证的参数是非必需的。由于在验证参数时,尝试对参数做了类型转换,故验证成功后,参数的类型是正确的,将参数存储到Dictionary<string,object>中,或者是对象的属性中。

  因此增加检测条件时,只需要增加一个类型的判断方法即可。代码中已经内置了检测整数、浮点数、双精度、时间、正则等。

  详细代码如下:

bubuko.com,布布扣
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Text.RegularExpressions;
  6 using CheckHandle = System.Func<Core.Data.ValidateHelp, string, string, string, Core.Data.ValidateHelp>;
  7 namespace Core.Data
  8 {
  9     public class ValidateHelp
 10     {
 11         #region 属性
 12         //数据容器字典
 13         public Dictionary<string, object> Data { get; protected set; }
 14         //数据容器实体
 15         public Object Entity { get; protected set; }
 16         //错误信息
 17         public string Message { get; protected set; }
 18         /// <summary>
 19         /// true:数据无效 false:数据有效
 20         /// </summary>
 21         private bool isInValid;
 22         /// <summary>
 23         /// true:数据无效 false:数据有效
 24         /// </summary>
 25         public bool IsInValid { get { return isInValid; } }
 26         #endregion
 27 
 28         #region 字段
 29 
 30         //数据容器实体类型
 31         protected Type EntityType;
 32         //验证委托缓存
 33         private static Dictionary<string, CheckHandle> checkHandlers = new Dictionary<string, CheckHandle>();
 34 
 35         #endregion
 36 
 37         #region 静态方法 得到对象实例
 38         public static ValidateHelp Begin()
 39         {
 40             var v = new ValidateHelp();
 41             v.Data = new Dictionary<string, object>();
 42             return v;
 43         }
 44 
 45         public static ValidateHelp BeginEntity<T>()
 46         {
 47             var v = new ValidateHelp();
 48             v.EntityType = typeof(T);
 49             v.Entity = Activator.CreateInstance(v.EntityType);
 50             return v;
 51         }
 52         #endregion
 53 
 54         #region 私有辅助方法
 55         private ValidateHelp()
 56         {
 57         }
 58 
 59 
 60         private static ValidateHelp Error(ValidateHelp v, string msg)
 61         {
 62             //没有错误信息 默认不修改验证结果
 63             if (msg == null || msg.Length == 0)
 64             {
 65                 return v;
 66             }
 67             v.isInValid = true;
 68             v.Message = msg;
 69             return v;
 70         }
 71 
 72         private static ValidateHelp Success(ValidateHelp v, object value, string propertyName)
 73         {
 74             if (v.IsInValid) return v;
 75             if (propertyName != null && propertyName.Length > 0)
 76             {
 77                 if (v.Data != null)
 78                 {
 79                     v.Data[propertyName] = value;
 80                 }
 81                 else if (v.Entity != v)
 82                 {
 83                     var p = v.Entity.GetType().GetProperty(propertyName);
 84                     //为对象属性赋值
 85                     p.SetValue(v.Entity, value, null);
 86                 }
 87             }
 88             return v;
 89         }
 90 
 91         private ValidateHelp Check(string[] args, CheckHandle fun)
 92         {
 93             if (args == null || args.Length == 0 || args.Length > 3)
 94             {
 95                 throw new Exception("验证参数错误");
 96             }
 97             //如果之前验证失败,就直接返回
 98             if (isInValid) return this;
 99             var value = args[0];
100             var propertyName = args.Length > 1 ? args[1] : null;
101             var msg = args.Length > 2 ? args[2] : null;
102             return fun(this, value, propertyName, msg);
103         }
104 
105         #endregion
106 
107         #region 公有辅助方法
108         public object this[string key]
109         {
110             get
111             {
112                 object o;
113                 if (Data.TryGetValue(key, out o)) return o;
114                 return null;
115             }
116         }
117         #endregion
118 
119         #region 验证方法
120         public virtual ValidateHelp IsNullOrEmpty(params string[] args)
121         {
122             CheckHandle handler;
123             if (!checkHandlers.TryGetValue("IsNullOrEmpty", out handler))
124             {
125                 handler = (scope, s, p, m) =>
126                 {
127                     if (s == null || s.Length == 0)
128                     {
129                         return Error(scope, m);
130                     }
131                     return Success(scope, s, p);
132                 };
133                 checkHandlers["IsNullOrEmpty"] = handler;
134             };
135             return Check(args, handler);
136         }
137         public virtual ValidateHelp IsInt(params string[] args)
138         {
139             CheckHandle handler;
140             if (!checkHandlers.TryGetValue("IsInt", out handler))
141             {
142                 handler = (scope, s, p, m) =>
143                 {
144                     int i;
145                     if (!int.TryParse(s, out i))
146                     {
147                         return Error(scope, m);
148                     }
149                     return Success(scope, i, p);
150                 };
151                 checkHandlers["IsInt"] = handler;
152             };
153             return Check(args, handler);
154         }
155 
156         public virtual ValidateHelp IsDouble(params string[] args)
157         {
158             CheckHandle handler;
159             if (!checkHandlers.TryGetValue("IsDouble", out handler))
160             {
161                 handler = (scope, s, p, m) =>
162                 {
163                     double i;
164                     if (!double.TryParse(s, out i))
165                     {
166                         return Error(scope, m);
167                     }
168                     return Success(scope, i, p);
169                 };
170                 checkHandlers["IsDouble"] = handler;
171             };
172             return Check(args, handler);
173         }
174 
175         public virtual ValidateHelp IsLong(params string[] args)
176         {
177             CheckHandle handler;
178             if (!checkHandlers.TryGetValue("IsLong", out handler))
179             {
180                 handler = (scope, s, p, m) =>
181                 {
182                     long i;
183                     if (!long.TryParse(s, out i))
184                     {
185                         return Error(scope, m);
186                     }
187                     return Success(scope, i, p);
188                 };
189                 checkHandlers["IsLong"] = handler;
190             };
191             return Check(args, handler);
192         }
193 
194         public virtual ValidateHelp IsFloat(params string[] args)
195         {
196             CheckHandle handler;
197             if (!checkHandlers.TryGetValue("IsFloat", out handler))
198             {
199                 handler = (scope, s, p, m) =>
200                 {
201                     float i;
202                     if (!float.TryParse(s, out i))
203                     {
204                         return Error(scope, m);
205                     }
206                     return Success(scope, i, p);
207                 };
208                 checkHandlers["IsFloat"] = handler;
209             };
210             return Check(args, handler);
211         }
212 
213         public virtual ValidateHelp IsBool(params string[] args)
214         {
215             CheckHandle handler;
216             if (!checkHandlers.TryGetValue("IsBool", out handler))
217             {
218                 handler = (scope, s, p, m) =>
219                 {
220                     bool i;
221                     if (!bool.TryParse(s, out i))
222                     {
223                         return Error(scope, m);
224                     }
225                     return Success(scope, i, p);
226                 };
227                 checkHandlers["IsBool"] = handler;
228             };
229             return Check(args, handler);
230         }
231 
232         public virtual ValidateHelp IsDateTime(params string[] args)
233         {
234             CheckHandle handler;
235             if (!checkHandlers.TryGetValue("IsDateTime", out handler))
236             {
237                 handler = (scope, s, p, m) =>
238                 {
239                     DateTime i;
240                     if (!DateTime.TryParse(s, out i))
241                     {
242                         return Error(scope, m);
243                     }
244                     return Success(scope, i, p);
245                 };
246                 checkHandlers["IsDateTime"] = handler;
247             };
248             return Check(args, handler);
249         }
250 
251         public virtual ValidateHelp IsEnum<T>(params string[] args) where T : struct
252         {
253             CheckHandle handler;
254             if (!checkHandlers.TryGetValue("IsEnum", out handler))
255             {
256                 handler = (scope, s, p, m) =>
257                 {
258                     T i;
259                     if (!Enum.TryParse(s, true, out i))
260                     {
261                         return Error(scope, m);
262                     }
263                     return Success(scope, i, p);
264                 };
265                 checkHandlers["IsEnum"] = handler;
266             };
267             return Check(args, handler);
268         }
269 
270         public virtual ValidateHelp IsRegex(string pattern, params string[] args)
271         {
272             CheckHandle handler;
273             if (!checkHandlers.TryGetValue(pattern, out handler))
274             {
275                 handler = (scope, s, p, m) =>
276                 {
277                     if (!Regex.IsMatch(s, pattern))
278                     {
279                         return Error(scope, m);
280                     }
281                     return Success(scope, s, p);
282                 };
283                 checkHandlers[pattern] = handler;
284             };
285             return Check(args, handler);
286         }
287 
288         public virtual ValidateHelp IsChar(params string[] args)
289         {
290             return IsRegex(@"^[A-Za-z]+$", args);
291         }
292 
293         public virtual ValidateHelp IsNumber(params string[] args)
294         {
295             return IsRegex(@"^\d+$", args);
296         }
297 
298         public virtual ValidateHelp IsChinese(params string[] args)
299         {
300             return IsRegex(@"^[\u4e00-\u9fa5]+$", args);
301         }
302 
303         public virtual ValidateHelp IsEmail(params string[] args)
304         {
305             return IsRegex(@"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$", args);
306         }
307 
308         public virtual ValidateHelp IsIP(params string[] args)
309         {
310             return IsRegex(@"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$", args);
311         }
312 
313         public virtual ValidateHelp IsUrl(params string[] args)
314         {
315             return IsRegex(@"^([a-zA-z]+://)?(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$", args);
316         }
317 
318         public virtual ValidateHelp IsPhone(params string[] args)
319         {
320             return IsRegex(@"((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)", args);
321         }
322         #endregion
323     }
324 }
ValidateHelp.cs

  其中验证方法使用了委托,用字典缓存委托。

最后

  有个问题,一直找不到好的方式解决,比如验证了10个参数,第1个的时候就验证失败,除了抛出异常,楼主暂时想不到什么方法可以中断后面的验证,但是抛异常带来的代码量非常大,因此折衷方案是,在具体的验证逻辑中,若已经验证失败,则直接跳过。

  将属性值赋值到实体上,使用的方式是反射,这一块可以优化一下,可以看看  《[源码]Literacy 快速反射读写对象属性,字段》 。使用反射的时候,属性名是大小写敏感的,而这个Literacy是可以设置大小写不敏感。

  示例项目是临时写的,验证代码在Default.aspx.cs里。

  示例下载

  

数据验证随想(续),布布扣,bubuko.com

数据验证随想(续)

原文:http://www.cnblogs.com/codealone/p/3798408.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!