Quantcast
Channel: Fluent Validation for .NET
Viewing all articles
Browse latest Browse all 1917

New Post: Collection Validation & Parent Context

$
0
0

I'm a GitHub rookie but I'll try creating a pull request this week to incorporate this into the existing ChildCollectionValidatorAdaptor and extensions... but for now this seems to do the trick (based from ChildCollectionValidatorAdaptor):

 

publicclass ParentChildCollectionValidatorAdaptor<T,TCollectionElement> : NoopPropertyValidator
{privatereadonly Func<T, IValidator<TCollectionElement>> validatorFactory;public Func<object, bool> Predicate { get; set; }public ParentChildCollectionValidatorAdaptor(Func<T, IValidator<TCollectionElement>> validatorFactory)
    {this.validatorFactory = validatorFactory;
    }publicoverride IEnumerable<ValidationFailure> Validate(PropertyValidatorContext context)
    {if (context.Rule.Member == null)
        {thrownew InvalidOperationException(string.Format("Nested validators can only be used with Member Expressions."));
        }var parent = (T)context.ParentContext.InstanceToValidate;var validator = validatorFactory.Invoke(parent);var collection = context.PropertyValue as IEnumerable;if (collection == null)
        {yieldbreak;
        }int count = 0;var predicate = Predicate ?? (x => true);foreach (var element in collection)
        {if (element == null || !(predicate(element)))
            {
                count++;continue;
            }var newContext = new ValidationContext(element, context.ParentContext.PropertyChain, context.ParentContext.Selector);
            newContext.PropertyChain.Add(context.Rule.Member);
            newContext.PropertyChain.AddIndexer(count++);var results = validator.Validate(newContext).Errors;foreach (var result in results)
            {yieldreturn result;
            }
        }
    }
}publicstaticclass ParentChildCollectionValidatorAdaptorExtensions
{publicstatic CollectionValidatorExtensions.ICollectionValidatorRuleBuilder<T, TCollectionElement> SetCollectionValidator<T, TCollectionElement>(this IRuleBuilder<T, IEnumerable<TCollectionElement>> ruleBuilder, Func<T, IValidator<TCollectionElement>> validatorFactory)
    {var adaptor = new ParentChildCollectionValidatorAdaptor<T, TCollectionElement>(validatorFactory);
        ruleBuilder.SetValidator(adaptor);returnnew CollectionValidatorRuleBuilder<T, TCollectionElement>(ruleBuilder, adaptor);
    }privateclass CollectionValidatorRuleBuilder<T,TCollectionElement> : CollectionValidatorExtensions.ICollectionValidatorRuleBuilder<T, TCollectionElement>
    {privatereadonly IRuleBuilder<T, IEnumerable<TCollectionElement>> ruleBuilder;privatereadonly ParentChildCollectionValidatorAdaptor<T, TCollectionElement> adaptor;public CollectionValidatorRuleBuilder(IRuleBuilder<T, IEnumerable<TCollectionElement>> ruleBuilder, ParentChildCollectionValidatorAdaptor<T, TCollectionElement> adaptor)
        {this.ruleBuilder = ruleBuilder;this.adaptor = adaptor;
        }public IRuleBuilderOptions<T, IEnumerable<TCollectionElement>> SetValidator(IPropertyValidator validator)
        {return ruleBuilder.SetValidator(validator);
        }public IRuleBuilderOptions<T, IEnumerable<TCollectionElement>> SetValidator(IValidator validator)
        {return ruleBuilder.SetValidator(validator);
        }public IRuleBuilderOptions<T, IEnumerable<TCollectionElement>> SetValidator(IValidator<IEnumerable<TCollectionElement>> validator)
        {return ruleBuilder.SetValidator(validator);
        }public IRuleBuilderOptions<T, IEnumerable<TCollectionElement>> Configure(Action<PropertyRule> configurator)
        {return ((IRuleBuilderOptions<T, IEnumerable<TCollectionElement>>)ruleBuilder).Configure(configurator);
        }public CollectionValidatorExtensions.ICollectionValidatorRuleBuilder<T, TCollectionElement> Where(Func<TCollectionElement, bool> predicate)
        {if (predicate == null) thrownew ArgumentNullException("predicate","Cannot pass null to Where");
            adaptor.Predicate = x => predicate((TCollectionElement)x);returnthis;
        }
    }
}

 

Usage:

 

publicclass WorkDayValidator : AbstractValidator<WorkDay>
{public WorkDayValidator()
    {
        RuleFor(workDay => workDay.Date).NotNull();
        RuleFor(workDay => workDay.WorkItems).SetCollectionValidator(workDay => new WorkItemValidator(workDay));
    }
}

Cheers,
mike 


Viewing all articles
Browse latest Browse all 1917

Trending Articles