private static bool ValidateValue(object value, ValidationContext validationContext,
                                   List <ValidationResult> validationResults, IEnumerable <ValidationAttribute> validationAttributes,
                                   string memberPath)
 {
     if (validationResults == null)
     {
         Validator.ValidateValue(value, validationContext, validationAttributes);
     }
     else
     {
         // todo, needs to be array aware
         List <ValidationResult> currentResults = new List <ValidationResult>();
         if (!Validator.TryValidateValue(value, validationContext, currentResults, validationAttributes))
         {
             // transform the validation results by applying the member path to the results
             if (!string.IsNullOrEmpty(memberPath))
             {
                 currentResults = ValidationUtilities.ApplyMemberPath(currentResults, memberPath).ToList();
             }
             validationResults.AddRange(currentResults);
             return(false);
         }
     }
     return(true);
 }
        private static bool ValidateProperty(object value, ValidationContext validationContext,
                                             List <ValidationResult> validationResults, string memberPath)
        {
            if (validationResults == null)
            {
                Validator.ValidateProperty(value, validationContext);
            }
            else
            {
                List <ValidationResult> currentResults = new List <ValidationResult>();
                if (!Validator.TryValidateProperty(value, validationContext, currentResults))
                {
                    // transform the validation results by applying the member path to the results
                    if (memberPath.Length > 0)
                    {
                        currentResults = ValidationUtilities.ApplyMemberPath(currentResults, memberPath).ToList();
                    }
                    validationResults.AddRange(currentResults);
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// This method recursively validates an object, first validating all properties, then
        /// validating the type. This method implements the classic Try pattern. However it serves
        /// as code sharing for the validation pattern where an exception is thrown on first error.
        /// </summary>
        /// <param name="instance">The object to validate.</param>
        /// <param name="memberPath">The dotted path of the member.</param>
        /// <param name="validationContext">The validation context.</param>
        /// <param name="validationResults">The collection in which the validation results will be
        /// stored. The collection can be <c>null</c>.</param>
        /// <returns><c>True</c> if the object was successfully validated with no errors.</returns>
        /// <exception cref="ValidationException">When <paramref name="validationResults"/> is
        /// <c>null</c> and the object has a validation error.</exception>
        private static bool ValidateObjectRecursive(object instance, string memberPath,
                                                    ValidationContext validationContext, List <ValidationResult> validationResults)
        {
            MetaType metaType = MetaType.GetMetaType(instance.GetType());

            if (!metaType.RequiresValidation)
            {
                return(true);
            }

            // First validate all properties
            bool hasValidationErrors = false;

            foreach (MetaMember metaMember in metaType.Members.Where(m => m.RequiresValidation || m.IsComplex))
            {
                ValidationContext propertyValidationContext = ValidationUtilities.CreateValidationContext(instance, validationContext);
                propertyValidationContext.MemberName = metaMember.Member.Name;

                // Form the current member path, appending the current
                // member name if it is complex.
                string currMemberPath = memberPath;
                if (metaMember.IsComplex)
                {
                    if (currMemberPath.Length > 0)
                    {
                        currMemberPath += ".";
                    }
                    currMemberPath += metaMember.Member.Name;
                }

                object value = metaMember.GetValue(instance);

                // first validate the property itself
                if (metaMember.RequiresValidation)
                {
                    hasValidationErrors |= !ValidationUtilities.ValidateProperty(value, propertyValidationContext, validationResults, currMemberPath);
                }

                // for complex members, in addition to property level validation we need to
                // do deep validation recursively
                if (value != null && metaMember.IsComplex)
                {
                    if (!metaMember.IsCollection)
                    {
                        hasValidationErrors |= !ValidateObjectRecursive(value, currMemberPath, validationContext, validationResults);
                    }
                    else
                    {
                        hasValidationErrors |= !ValidateComplexCollection((IEnumerable)value, currMemberPath, validationContext, validationResults);
                    }
                }
            }

            // Only proceed to Type level validation if there are no property validation errors
            if (hasValidationErrors)
            {
                return(false);
            }

            // Next perform Type level validation without validating properties, since we've already validated all properties.
            // Note that we can't use Validator.ValidateObject specifying 'validateAllProperties' since even when specifying false,
            // that API will validate RequiredAttribute.
            ValidationContext context = ValidationUtilities.CreateValidationContext(instance, validationContext);

            if (metaType.ValidationAttributes.Any())
            {
                hasValidationErrors |= !ValidationUtilities.ValidateValue(instance, context, validationResults, metaType.ValidationAttributes, memberPath);
            }

#if !SILVERLIGHT
            // Only proceed to IValidatableObject validation if there are no errors
            if (hasValidationErrors)
            {
                return(false);
            }

            // Test for IValidatableObject implementation and run the validation if applicable
            // Note : this interface doesn't exist in Silverlight
            IValidatableObject validatable = instance as IValidatableObject;
            if (validatable != null)
            {
                IEnumerable <ValidationResult> results = validatable.Validate(context);

                if (!string.IsNullOrEmpty(memberPath))
                {
                    results = ValidationUtilities.ApplyMemberPath(results, memberPath);
                }

                foreach (ValidationResult result in results.Where(r => r != ValidationResult.Success))
                {
                    validationResults.Add(result);
                    hasValidationErrors = true;
                }
            }
#endif

            return(!hasValidationErrors);
        }