开发日志:通过反射验证对象属性值

本系列主旨是记录本人在项目开发和语言的学习中总结的小技巧,自知能力有限,不足登大雅之堂,但本着学习和交流的态度,希望各位同仁给与批评和指正。
在此不胜感激!!
转载请注明出处:http://suchenge.cnblogs.com

数据交互是WEB交互的核心功能,用户在Web页面的表单中提交数据,程序接受数据后进行相应的逻辑运算后将数据写入数据库中,在这样的应用中无论是考虑到应用系统的安全还是用户数据的完整,我们都将对用户提交的数据信息进行相应的验证。

 

比如一个用户注册的交互应用:

开发日志:通过反射验证对象属性值

一般会在Model层建立一个注册类

  
    
public class Register
{
public string Account { get ; set ; }
public string Password { get ; set ; }
public string Email { get ; set ; }
}

 

在UI层将页面提交来的数据对应赋予Register类实例化后的对象的属性,之后将对象传递给BLL层进行数据库的操作

 

代码
   
     
Register register = new Register();
register.Account
= HttpContext.Current.Request[ " txtAccount " ].Trim();
register.Password
= HttpContext.Current.Request[ " txtPassword " ].Trim();
register.Email
= HttpContext.Current.Request[ " txtEmail " ].Trim();

 

在这里,我们暂不谈数据的安全性,只讨论数据的完整性,在这样的应用中Register类中的Account和Password属性,作为用户今后登录的重要依据,是必填的,通常情况下,我们会在将参数赋值给对象属性前先进行判断是否为空的操作

 

  
    
string account = string .Empty;
if ( ! string .IsNullOrEmpty(HttpContext.Current.Request[ " txtAccount " ]))
{
account
= HttpContext.Current.Request[ " txtAccount " ].Trim();
}
register.Account
= account;

 

但是,当一个需要赋值的对象的属性非常多时,我们的判断工作将是灾难性的。

还好,.Net为我们提供了Attribute类(字面上解释应该叫做“属性”,但我叫它“修饰”,因为它和类的“Property”同名)

我们可以通过建立一个验证用的Attribute对象VerifyAttribute,并给Register类的属性加上VerifyAttribute型的修饰,记录下属性的规则,比如类型、是否可以为空,最大值以及最小值等,并建立一个通过对象属性修饰(Attribute)验证对象属性规则的类Verify,在Register对象个属性赋值好后,通过Verify的验证过程,返回验证信息。

 

代码
   
     
/// <summary>
/// 实体属性验证设置特性对象
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false , AllowMultiple = true )]
public abstract class VerifyAttribute : Attribute
{
/// <summary>
/// 说明
/// </summary>
protected string _Explain;

/// <summary>
/// 是否可以为空
/// </summary>
protected bool _NotNull;

/// <summary>
/// 正则表达式
/// </summary>
protected string _RegexExpressions;

/// <summary>
/// 获取说明
/// </summary>
public string Explain
{
get { return _Explain; }
}

/// <summary>
/// 获取是否可以为空值
/// </summary>
public bool NotNULL
{
get { return _NotNull; }
}

/// <summary>
/// 获取验证正则表达式
/// </summary>
public string RegexExpressions
{
get { return _RegexExpressions; }
}

/// <summary>
/// 为内部字段赋值
/// </summary>
/// <param name="explain"> 属性说明 </param>
/// <param name="notnull"> 是否不可为空 </param>
/// <param name="regexexpressions"> 正则表达式,为空不验证 </param>
protected void GetParam( string explain, bool notnull, string regexexpressions)
{
_Explain
= explain;
_NotNull
= notnull;
_RegexExpressions
= regexexpressions;
}
}

 

代码
   
     
/// <summary>
/// 实体字符类型属性验证设置特性对象
/// </summary>
public class VerifyString : VerifyAttribute
{
/// <summary>
/// 最大长度
/// </summary>
protected int _MaxLength;

/// <summary>
/// 获取最大长度
/// </summary>
public int MaxLength
{
get { return _MaxLength; }
}

/// <summary>
/// 为实体字符类型属性设置验证特性
/// </summary>
/// <param name="explain"> 属性说明 </param>
/// <param name="notnull"> 是否可以为空 </param>
/// <param name="maxlength"> 属性值最大长度 </param>
public VerifyString( string explain, bool notnull, int maxlength)
{
_MaxLength
= maxlength;
GetParam(explain, notnull,
"" );
}

/// <summary>
/// 为实体字符类型属性设置验证特性
/// </summary>
/// <param name="explain"> 属性说明 </param>
/// <param name="notnull"> 是否可以为空 </param>
public VerifyString( string explain, bool notnull) {
_MaxLength
= 0 ;
GetParam(explain, notnull,
"" );
}

/// <summary>
/// 为实体字符类型属性设置验证特性
/// </summary>
/// <param name="explain"> 属性说明 </param>
/// <param name="notnull"> 是否可以为空 </param>
/// <param name="maxlength"> 属性值最大长度 </param>
/// <param name="regexexpressions"> 正则表达式,为空不验证 </param>
public VerifyString( string explain, bool notnull, int maxlength, string regexexpressions)
{
_MaxLength
= maxlength;
GetParam(explain, notnull, regexexpressions);
}
}

上面两个类VerifyString继承自VerifyAttribute类,主要是用作对String类型的属性的修饰,其中加入了可通过正则表达式进行验证的功能。

 

建立实现验证过程的对象

 

代码
   
     
/// <summary>
/// 实例属性数据格式验证对象
/// </summary>
public class Verify {

/// <summary>
/// 验证属性数据格式,并返回验证结果
/// </summary>
/// <typeparam name="T"> 必须继承自BaseObject </typeparam>
/// <param name="t"> 要验证的实例 </param>
/// <param name="separator"> 分割验证结果的自定义分隔符 </param>
/// <returns> 验证结果 </returns>
public static string VerificationDataToString < T > (T t, string separator)
{
System.Type type
= t.GetType();
StringBuilder strTmp
= new StringBuilder();
foreach (PropertyInfo P in type.GetProperties())
{
foreach (Attribute attr in P.GetCustomAttributes( true ))
{
VerifyAttribute vattr
= attr as VerifyAttribute;
string typename = vattr.GetType().ToString();
typename
= typename.Substring(typename.LastIndexOf( " . " ) + 1 );
object pv = P.GetValue(t, null );
if (vattr.NotNULL)
{
if (pv == null || pv.ToString() == "" )
{
strTmp.AppendFormat(
" {0}不得为空{1} " , vattr.Explain, separator);
}
}

switch (typename)
{
case " VerifyString " :
VerifyString vattrs
= (VerifyString) vattr;
if (pv != null )
{
if (vattrs.MaxLength > 0 )
{
if (pv.ToString().Length > vattrs.MaxLength)
{
strTmp.AppendFormat(
" {0}长度不得超过{1},现在是{2}{3} " ,
vattrs.Explain,
vattrs.MaxLength,
pv.ToString().Length,
separator);
}
}
}
break ;
case " VerifyDate " :

break ;
case " VerifyNumber " :

break ;
}
if (vattr.RegexExpressions != "" )
{
if (pv != null )
{
if ( ! TestRegex(pv.ToString(), vattr.RegexExpressions))
strTmp.AppendFormat(
" {0}不符合格式要求{1} " , vattr.Explain, separator);
}
}
}
}
if (strTmp.ToString().Length <= 0 ) return "" ;
else return strTmp.ToString().Substring( 0 , strTmp.ToString().LastIndexOf(separator));
}

/// <summary>
/// 通过正则检查字符中是否存在指定字符
/// </summary>
/// <param name="value"> 要检查的字符串 </param>
/// <param name="regex"> 正则表达式 </param>
/// <returns> 真or假 </returns>
private static bool TestRegex( string value, string regex)
{
return Regex.IsMatch(value, regex);
}

}

函数VerificationData(),接受一个泛型对象,并遍历对象的属性以及属性的修饰(Attribute),取出属性的值后根据修饰描述的规则进行验证判断,最后返回验证结果。

 

这样,我们修改之前的Register类,为其属性加上VerifyAttribute验证规则修饰

 

代码
   
     
public class Register
{
// 必填,长度不得超过50字符,启用正则验证规则"^[\w|@|.|_]{2,20}$"
[VerifyString( " 账户 " , true , 50 , RegularExpression.Account)]
public string Account { get ; set ; }

// 必填,长度不得超过50字符,启用正则验证规则"^[a-zA-Z0-9]{6,20}$"
[VerifyString( " 密码 " , true , 50 , RegularExpression.Password)]
public string Password { get ; set ; }

// 必填,长度不得超过150字符,启用正则验证规则"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"
[VerifyString( " 邮箱 " , true , 150 , RegularExpression.Email)]
public string Email { get ; set ; }
}

 

在实际应用中我们通过Verify对象的VerificationData函数返回验证结果

 

 

代码
   
     
string account = "" ;
string password = " $%123 " ;
string email = " ffssfs@fdfds " ;

string err = string .Empty;

Register register
= new Register();
register.Account
= account;
register.Password
= password;
register.Email
= email;

err
= Verify.VerificationData < Register > (register, " <br/> " );

if (err == string .Empty)
{
// 验证通过
}
else
{
HttpContext.Current.Response.Write(err);
err应该返回:“账号不能为空
<br/>请正确填写账号<br/>请正确填写密码<br/> 请正确填写邮箱”
}

 

 

代码是从之前的项目中拷贝过来的,没有再次经过测试,如果有问题请与我联系,非常感谢!!

你可能感兴趣的:(反射)