雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

Attribute特性封装通用数据验证

2024-10-15 27

在接口接收数据或者数据库写入的时候一般都会进行数据验证。如果在接收到数据或者插入的时候对对象的每个属性进行检验,代码会很臃肿,而且无法复用,通过Attribute特性可以优雅地进行数据验证。

例如我们写一个特性验证属性不能为空,示例代码如下:

特性RequiredAttribute

public class RequiredAttribute:Attribute
{
}

public class User
{
    [Required]//非空校验特性标注
    public string NickName { get; set; }
    public int? Level { get; set; }
}

写一个扩展方法,对对象进行数据验证

//扩展方法
public static bool Validate(this object obj)
{
    var type = obj.GetType();
    foreach (var prop in type.GetProperties())
    {
        if (prop.IsDefined(typeof(RequiredAttribute), true))
        {
            var propValue = prop.GetValue(obj);
            if (propValue == null || string.IsNullOrWhiteSpace(propValue.ToString())) {
                return false;
            }
        }
    }
    return true;
}
//调用扩展方法进行数据验证
User user = new User()
{
    NickName = "Paul",
    Level = 1
};
//获得校验结果true or false,可以在适当的地方先进行校验再执行后续操作
var result = user.Validate()

像这样就能实现通过Attribute特性封装通用数据验证了,如果别的字段想要做验证,加上这个标签就可以了。原理就是这样,那么要加一些别的复杂的数据验证都可以通过增加Attribute特性来实现。

如果按照上面的写法,每次增加特性后,都要修改扩展方法,我们可以设计一下,让每个特性自己完成检验。定义一个抽象特性,然后每次要增加新的验证就继承它,并且重写它的验证方法。下面我再增加一个验证字符串长度的特性,然后通过更加优雅的方式是实现它,代码如下:

public abstract class AbstracValidateAttribute:Attribute
{
    public abstract bool Validate(object obj);
}
//验证非空
public class RequiredAttribute:AbstracValidateAttribute
{
    //重写验证方法
    public override bool Validate(object obj) {
        return (obj == null || string.IsNullOrWhiteSpace(obj.ToString())) ? false : true;
    }
}
//验证字符串长度
public class StringLengthAttribute:AbstracValidateAttribute
{
    private int _Min { get; set; }
    private int _Max { get; set; }
    public StringLengthAttribute(int min, int max) {
        _Min = min;
        _Max = max;
    }
    public override bool Validate(object obj)
    {
        if (obj == null || string.IsNullOrWhiteSpace(obj.ToString()))
            return false;
        var str = obj.ToString();
        return (str.Length < _Min || str.Length > _Max) ? false : true;
    }
}

public class User
{
    [Required]//非空校验特性标注
    [StringLength(1,10)]//字符串长度1-10
    public string NickName { get; set; }
    public int? Level { get; set; }
}

扩展方法修改为:

public static bool Validate(this object obj) {
    var type = obj.GetType();
    foreach (var prop in type.GetProperties()) {
        if (prop.IsDefined(typeof(AbstracValidateAttribute), true)) {
            var propValue = prop.GetValue(obj);
            var attributeArray = prop.GetCustomAttributes<AbstracValidateAttribute>();
            foreach (var item in attributeArray) {
                if (!item.Validate(propValue))
                    return false;
            }
        }
    }
    return true;
}

这样一来,以后再要加验证方式的时候,新增一个特性Attribute继承AbstracValidateAttribute,然后重写Validate方法,就可以自定义一个数据验证规则了。无需修改扩展方法,直接给属性加上特性标注即可。

更新于:1个月前
赞一波!

文章评论

评论问答