public IEnumerable <RuleDescription> GetNestedRules(string propertyName, PropertyRule rule, ChildValidatorAdaptor childValidator, IRuleBuilder ruleBuilder) { //HACK: I hate this explicit defintion. var coreDocumentationType = typeof(DocBuilder); const string methodIdentifier = "Document"; var getRulesMethodDefinition = coreDocumentationType.ExtractMethodInfo(new[] { methodIdentifier })[methodIdentifier]; // Create the generic method instance of Document() getRulesMethodDefinition = getRulesMethodDefinition.MakeGenericMethod(childValidator.ValidatorType.GetTypeInfo().BaseType.GenericTypeArguments[0]); //Parameter 1 = Validator instance derived from AbstractValidator<T>, Parameter 2 = boolean (documentNested) var parameterArray = new object[] { childValidator.GetValidator(_fluentValidationHelper.BuildPropertyValidatorContext(rule, propertyName)), true }; //Invoke extension method with validator instance var documentationInstance = Activator.CreateInstance(coreDocumentationType, ruleBuilder); var nestedRules = getRulesMethodDefinition.Invoke(documentationInstance, parameterArray) as IEnumerable <RuleDescription>; if (nestedRules == null) { yield return(null); } foreach (var deepDocumentRule in nestedRules) { yield return(deepDocumentRule); } }
public string GetErrorMessage(IPropertyValidator validator, PropertyRule rule, string propertyName) { if (validator == null) { throw new ArgumentNullException(nameof(validator)); } if (rule == null) { throw new ArgumentNullException(nameof(rule)); } if (string.IsNullOrWhiteSpace(propertyName)) { throw new ArgumentNullException(nameof(propertyName)); } const string messagePreparationMethodIdentifier = "PrepareMessageFormatterForValidationError"; const string createValidationErrorMethodIdentifier = "CreateValidationError"; var validatorMethods = validator.GetType().ExtractMethodInfo(new[] { messagePreparationMethodIdentifier, createValidationErrorMethodIdentifier }); if (validatorMethods == null) { return(null); } //ValidatorContext is based on the type passed into the validator that is validated against, such as a 'Person' POCO var validatorContext = _fluentValidationHelper.BuildPropertyValidatorContext(rule, propertyName); //Force the validator to populate field parameter names that are used as part of the error response validatorMethods[messagePreparationMethodIdentifier].Invoke(validator, new object[] { validatorContext }); //With the parameter names completed, build the error using the Validator instance var validationFailure = validatorMethods[createValidationErrorMethodIdentifier].Invoke(validator, new object[] { validatorContext }) as ValidationFailure; return(validationFailure?.ErrorMessage); }