C#encapsulates FluentValidation. After using it, the entire article is still AbstractValidator. I really can't watch it anymore.

C#encapsulates FluentValidation. After using it, the entire article is still AbstractValidator. I really can't watch it anymore.

FluentValidation is a very powerful. NET framework for building strongly typed validation rules

最后更新 6/9/2022 10:12 PM
黑哥聊dotNet
预计阅读 5 分钟
分类
.NET
标签
.NET C# FluentValidation

storytelling

前几天看公司一个新项目使用了FluentValidation,大家都知道FluentValidation是一个非常强大的用于构建强类型验证规则的 .NET 框架,帮程序员解决了繁琐的校验问题,用起来非常爽,但我还是遇到了一件非常不爽的事情,如下代码所示:

public class UserInformationValidator : AbstractValidator<UserInformation>
{
 public UserInformationValidator()
 {
     RuleFor(o => o.UserName).Length(2, 20).WithMessage("姓名长度输入错误");
     RuleFor(o => o.Sex).Must(o=>o=="男"||o=="女").WithMessage("性别输入错误");
     RuleFor(o => o.Age).ExclusiveBetween(0, 200).WithMessage("年龄输入错误");
     RuleFor(o => o.Email).EmailAddress().WithMessage("邮箱输入错误");
  }
}


static void Main(string[] args)
{

    UserInformation userInformation = new UserInformation();
    userInformation.UserName = "";
    userInformation.Sex = "不男不女";
    userInformation.Age = 2200;
    userInformation.Email = "xxxxx";
    UserInformationValidator validationRules = new UserInformationValidator();
    var result=   validationRules.Validate(userInformation);
    if (!result.IsValid)
    {
      Console.WriteLine( string.Join(Environment.NewLine, result.Errors.Select(x => x.ErrorMessage).ToArray()));
    }

}

我们每验证一个对象,就要新建一个类型的验证器 ,如上的UserInformationValidator ,虽然这样写逻辑上没有任何问题,但我有洁癖哈,接下来我们试着封装一下,嘿嘿,用更少的代码做更多的事情。

installation

在创建任何验证器之前,您需要在项目中添加对 FluentValidation.dll 的引用。最简单的方法是使用 NuGet 包管理器dotnet CLI

Exploration of templated code encapsulation

Extract templated code into parent classes

仔细看上面的代码你会发现,我们每新建一个验证器,就必须要创建一个继承自AbstractValidator<T>的类,其中T是您希望验证的类的类型,封装一个验证器父类

public class CommonVaildator<T> : AbstractValidator<T>
{

}

Add verification rules

真正的业务逻辑是写在UserInformationValidator验证器里面的,而这块代码中只需要拿到RuleFor即可,其他的统一封装到父类中,对不对,我们按照这个思路代码,封装一个长度验证器规则

First let's look at the prototype of RuleFor

public IRuleBuilderInitial<T, TProperty> RuleFor<TProperty>(Expression<Func<T, TProperty>> expression)

它的参数是一个Func委托,那么Expression是什么呢?

Experssion是一种表达式树

表达式树是一种允许将lambda表达式表示为树状数据结构而不是可执行逻辑的代码。

在 C#中是Expression来定义的,它是一种语法树,或者说是一种数据结构。其主要用于存储需要计算、运算的一种结构,它只提供存储功能,不进行运算。通常Expression是配合Lambda一起使用,这里就不做过多的解释了!

Then we can easily encapsulate the length verifier rules!

public void LengthVaildator(Expression<Func<T, string>> expression, int min, int max, string Message)
{
    RuleFor(expression).Length(min, max).WithMessage(Message);
}

In the same way, we can also go on to encapsulate the ** predicate validator rules *** Mailbox validator rules ** and so on

public void MustVaildator(Expression<Func<T, string>> expression ,Func<T,string, bool> expression2, string Message)
{
    RuleFor(expression).Must(expression2).WithMessage(Message);
}
public void EmailAddressVaildator(Expression<Func<T, string>> expression, string Message)
{
    RuleFor(expression).EmailAddress().WithMessage(Message);
}

Packaging verification method

上面我们把验证器封装好了,那么将 var result= validationRules.Validate(userInformation);这种验证方法封装一下不是手到擒来,代码如下:

public static string ModelValidator<T>(T source, AbstractValidator<T> sourceValidator) where T : class
{
    var results = sourceValidator.Validate(source);
    if (!results.IsValid)
        return string.Join(Environment.NewLine, results.Errors.Select(x => x.ErrorMessage).ToArray());
    else
        return "";

}

Test encapsulated code

CommonVaildator<UserInformation> commonUserInformation = new CommonVaildator<UserInformation>();
commonUserInformation.LengthVaildator(o => o.UserName, 2, 30, "姓名长度输入错误");
commonUserInformation.MustVaildator(o => o.Sex, (user, _) => user.Sex =="男"||user.Sex=="女" , "性别输入错误");
commonUserInformation.ExclusiveBetweenVaildator(o=>o.Age,0, 200, "年龄输入错误");
commonUserInformation.EmailAddressVaildator(o => o.Email, "邮箱输入错误");
string msg= VaildatorHelper.ModelValidator(userInformation, commonUserInformation);
Console.WriteLine(msg);

Does the code look much simpler? I only encapsulate four verification rules here, and I won't encapsulate the rest here.

summary

The article comes from every detail in my work. This is also my impromptu packaging. If you have better packaging code, you are welcome to communicate. It is better to have fun alone than everyone else. This article will stop here, and I hope it will be helpful to you.

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 4/22/2026

Support for. NET by operating system versions (250707 update)

Use virtual machines and test machines to test the support of each version of the operating system for. NET. After installing the operating system, it is passed by measuring the corresponding running time of the installation and being able to run the Stardust Agent.

继续阅读
同分类 / 同标签 2/7/2026

Summary of experience in using AOT

From the very beginning of project creation, you should develop a good habit of conducting AOT release testing in a timely manner whenever new features are added or newer syntax is used.

继续阅读