具有基本实体参数的FluentValidation自定义扩展方法

时间:2020-09-28 22:47:14

标签: c# fluentvalidation

我正在使用FluentValidation进行服务器验证,其中一项验证使用带有参数的自定义扩展方法。所述方法将需要从根对象(实体)获取更多参数。

当前代码为:

RuleFor(entity => entity.A).CustomExtension("test")

...

public static IRuleBuilder<T, string> CustomExtension<T>(this IRuleBuilder<T, string> builder, string someValue){

我需要对此进行更改,以便...

RuleFor(entity => entity.A).CustomExtension(entity.PropertyB) //<- basically need to pass a entity property as variable

public static IRuleBuilder<T, string> CustomExtension<T>(this IRuleBuilder<T, string> builder, string propertyA){
}

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

在构造验证器时,您无权访问要验证的实例。可能有几种方法可以执行,这取决于您要实施的规则类型。

我正在考虑的两种方式是利用现有的custom validators(提供实例进行验证)(直接或通过上下文)。前者仅向您提供实例传递给验证器的信息,后者还为您提供context,您可以使用它在运行时向验证器提供数据。

让我们假设您可以使用Must扩展来创建自定义验证器,这意味着我们正在研究前一种情况。必须具有一些重载,其中之一提供了正在作为Func lambda一部分进行验证的实例。以下LINQPad示例显示了如何利用它来创建自己的扩展:

void Main()
{
    var validator = new MyValidator();

    var myEntity1 = new MyEntity();
    myEntity1.A = Guid.NewGuid();
    myEntity1.B = myEntity1.A;

    var validateResult1 = validator.Validate(myEntity1);
    Console.WriteLine("Expected result: no errors");
    Console.WriteLine(validateResult1.Errors.Select(x => x.ErrorMessage));

    var myEntity2 = new MyEntity();
    myEntity2.A = Guid.NewGuid();
    myEntity2.B = Guid.NewGuid();

    var validateResult2 = validator.Validate(myEntity2);
    Console.WriteLine("Expected result: 3 errors");
    Console.WriteLine(validateResult2.Errors.Select(x => x.ErrorMessage));
}

public class MyEntity
{
    public Guid A { get; set; }
    public Guid B { get; set; }
}

public class MyValidator : AbstractValidator<MyEntity>
{
    public MyValidator()
    {
        RuleFor(x => x.A).Equal(x => x.B).WithMessage("Error via equal");
        RuleFor(x => x.A).Must((myEntityInstance, valueOfA) => myEntityInstance.B.Equals(valueOfA)).WithMessage("Error via normal must");
        RuleFor(x => x.A).CustomExtension(x => x.B).WithMessage("Error via custom extension");
    }
}

public static class Extensions
{
    public static IRuleBuilderOptions<T, TProperty> CustomExtension<T, TProperty, TCompareTo>
        (this IRuleBuilder<T, TProperty> ruleBuilder, Func<T, TCompareTo> propertyToCompareTo)
    {
        return ruleBuilder.Must((myEntityInstance, valueOfA) => propertyToCompareTo(myEntityInstance).Equals(valueOfA));
    }
}

结果:

enter image description here

在不知道您的自定义扩展将要做什么的情况下,这有点虚构,但是它确实展示了一种获取实例以在您自己的扩展中运行时进行验证的方法。