Skip to content

ValidatableModel should accept custom validation #12

@MartinJSoles

Description

@MartinJSoles

Let users inject an iValidator object in an alternate constructor that can perform the same operations as the ComponentModel.DataAnnotations.Validator class. This would allow someone to hook in some other validation framework such as FluentValidation. The default constructor could use a static implementation that simply delegates the validation methods to the DataAnnotations.Validator static methods.

    public interface IValidator
    {
        bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults);
        bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, bool validateAllProperties);
        bool TryValidateProperty(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults);
        bool TryValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes);
        void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext);
        void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, bool validateAllProperties);
        void ValidateProperty(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext);
        void ValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes);


    }

    public class DefaultValidator : IValidator
    {
        public bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults)
        {
            return Validator.TryValidateObject(instance, validationContext, validationResults);
        }

        public bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults, bool validateAllProperties)
        {
            return Validator.TryValidateObject(instance, validationContext, validationResults, validateAllProperties);
        }

        public bool TryValidateProperty(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults)
        {
            return Validator.TryValidateProperty(value, validationContext, validationResults);
        }

        public bool TryValidateValue(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults, IEnumerable<ValidationAttribute> validationAttributes)
        {
            return Validator.TryValidateValue(value, validationContext, validationResults, validationAttributes);
        }

        public void ValidateObject(object instance, ValidationContext validationContext)
        {
            Validator.ValidateObject(instance, validationContext);
        }

        public void ValidateObject(object instance, ValidationContext validationContext, bool validateAllProperties)
        {
            Validator.ValidateObject(instance, validationContext, validateAllProperties);
        }

        public void ValidateProperty(object value, ValidationContext validationContext)
        {
            Validator.ValidateProperty(value, validationContext);
        }

        public void ValidateValue(object value, ValidationContext validationContext, IEnumerable<ValidationAttribute> validationAttributes)
        {
            Validator.ValidateValue(value, validationContext, validationAttributes);
        }
    }

In the ValidatableModel class, make these additions / changes:

        private IValidator validator;
        private static DefaultValidator _defaultValidator = new DefaultValidator();

        public void ctor()
            {
            this.validator = _defaultValidator;
            }

        public void ctor(IValidator validator)
        {
            this.validator = validator;
        }

        public bool Validate()
        {
            var validationResults = new List<ValidationResult>();

            this.validator.TryValidateObject(this, new ValidationContext(this), validationResults, true);

            UpdateErrors(validationResults);

            return !HasErrors;
        }

This puts the onus on those of us that need to use an alternate validation framework to add a class that implements this new interface while still allowing for a default implementation that uses the built-in functionality.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions