现在的位置: 首页 > 综合 > 正文

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

2012年05月09日 ⁄ 综合 ⁄ 共 5905字 ⁄ 字号 评论关闭

本系列主旨是记录本人在项目开发和语言的学习中总结的小技巧,自知能力有限,不足登大雅之堂,但本着学习和交流的态度,希望各位同仁给与批评和指正。
在此不胜感激!!
转载请注明出处: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/>请正确填写邮箱”
}

 

 

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

抱歉!评论已关闭.