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

FluentValidation Custom Extension Method with Parameters from Base Entity

我正在使用 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){
}

非常感谢任何帮助!

您无权访问要在验证器构造期间进行验证的实例。可能有几种方法可以做到这一点,这可能取决于您要实施的规则类型。

我想到的两种方法是利用现有的 custom validators that provide the instance to validate (directly or via context). The former gives you just that, the instance passed to the validator, the latter additionally gives you a 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));
    }
}

结果:

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