通过自定义Attribute及泛型extension封装数据验证过程

时间:2023-06-01 18:28:44

需求来源:

在日常工作中,业务流程往往就是大量持续的数据流转、加工、展现过程,在这个过程中,不可避免的就是数据验证的工作。数据验证工作是个很枯燥的重复劳动,没有什么技术含量,需要的就是对业务流程的准确理解以及细心耐心。在实际生产环境中,经常出现业务BUG最终检查是由于数据验证不到位,最终导致加工数据的结果不合理。整个排查过程也是费时费力,因此,希望能够提供便捷的数据验证方式。

在System.ComponentModel.DataAnnotations命名空间中,微软定义了一系列的Attribute,用于数据验证工作,功能很全面,但也有一些需求(如GreaterThan,LessThan)需要自定义实现,因此考虑根据实际项目需求,定制化一套需要的数据验证Attribute,并提供一个泛型extension验证方法,这样可以随时按需对当前对象实例进行数据验证。

实现过程:

实现非常简单,两个步骤:

1:按需自定义数据验证Attribute,如下实现了Range及LessThan:

[AttributeUsage(AttributeTargets.Property)]
    public class RangeAttribute : Attribute
    {
        public double Min { get; set; }
        public double Max { get; set; }
        public string ErrorMsg { get; set; }

        public RangeAttribute(int minValue, int maxValue, string errorMessage = "Argument out of range")
        {
            Min = minValue;
            Max = maxValue;
            ErrorMsg = errorMessage;
        }
    }

[AttributeUsage(AttributeTargets.Property)]
    public class LessThanAttribute : Attribute
    {
        public double Threshold { get; set; }
        public string ErrorMsg { get; set; }

        public LessThanAttribute(double threshold, string errorMessage = "Argument must less than the threshold")
        {
            Threshold = threshold;
            ErrorMsg = errorMessage;
        }
    }

2:实现泛型extension:

public static void Validate<T>(this T obj)
{
   //TODO: Validate Attribute Handle
}

具体代码较长,为精简版面就不全部贴出了。

(实现在https://github.com/cerasumat/Utilities/tree/master/CeraSumat.Utilities/Validation路径下的Validater.cs文件可以找到)

如何使用:

如下例,定义一个Student类,并按需加入数据验证Attribute,实例化该类后,调用实例的Validate()方法,即可便捷地进行数据验证:

        public class Student
        {
            [MaxLength()]
            [NotEqual("JiaK")]
            public string Name { get; set; }

            [Range(, )]
            [NotEqual()]
            [LessThan(3.5)]
            public int Id { get; set; }
        }
        static void Main(string[] args)
        {
            , Name = "Jiak"};
            s.Validate();
        }