Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent Validation passing in a lambda expression

Im trying to build a lambda expression and pass this into rulefor. The code compiles, but when executing I get the follwing message..

"'FluentValidation.Internal.RuleBuilder' does not contain a definition for 'Length'"

This is the validation code is this. The aim is that in two validators i want the same validation rule to be applied again username or a-another property.

public class UserValidator : AbstractValidator<DTO.User>
{
    public UserValidator(DTO.User u)
    {

        foreach (PropertyInfo property in
                 this.GetType().BaseType
                     .GetGenericArguments()[0]
                     .GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {


            if (property.Name == "Username")
            {

                ParameterExpression parameter = Expression.Parameter(typeof(DTO.User), "p");
                Expression propertyAccess = Expression.Property(parameter, property);
                // Make it easier to call RuleFor without knowing TProperty
                dynamic lambda = Expression.Lambda(propertyAccess, parameter);

                RuleFor(lambda)
                    .Length(4, 9)
                    .WithMessage("Valid between 4 and 9 chars");

                //RuleFor(x => x.Username)
                //    .Length(4, 9)
                //    .WithMessage("Valid between 4 and 9 chars");
            }

        }
    }

Any help appreciated...

like image 794
Justdeserves Avatar asked Mar 12 '26 18:03

Justdeserves


1 Answers

I'm not sure if this is the kind of help you may be hoping for, but, what you're proposing is an unconventional use of the fluent framework. Your commented out code is the usual way to use this framework. This gives you the strong typing within the closed generic validator class (UserValidator) without the use of magic strings and reflection.

That said, if you really want to avoid the repetition of the code asserting the length then maybe you could do it using a helper which takes an expression as an argument:

public class User
{
    public string Username { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        this.ValidateName(x => x.Username);
        this.ValidateName(x => x.FirstName);
        this.ValidateName(x => x.LastName);
    }
}

public static class ValidationExtensions
{
    public static void ValidateName<TV>(this AbstractValidator<TV> validator, Expression<Func<TV, string>> property)
    {
        validator.RuleFor(property).Length(4, 9).WithMessage("Valid between 4 and 9 chars");
    }
}
like image 155
MarkG Avatar answered Mar 14 '26 08:03

MarkG