예제 #1
0
        private static bool ValidateInternal(object obj, string path, ValidateAttribute validation, IList <ValidationError> validationErrors)
        {
            if (ReferenceEquals(obj, null))
            {
                if (validation.Required)
                {
                    validationErrors.Add(new ValidationError(path, "Property is required, found null"));
                    return(false);
                }

                // If object is null, we cannot do anything else.
                return(true);
            }

            var objType = obj.GetType();

            if (AlwaysValidTypes.Contains(objType) || PortableTypeInfo.IsEnum(objType))
            {
                return(true);
            }

            var isValueType = PortableTypeInfo.IsValueType(objType);

            // Check whether this type is nullable.
            if (validation.Required && isValueType && PortableTypeInfo.IsGenericType(objType) && objType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                var nullableProps        = PortableTypeInfo.GetPublicProperties(objType);
                var nullableHasValueProp = nullableProps.First(p => p.Name == nameof(Nullable <bool> .HasValue));

                if ((bool)PortableTypeInfo.GetPublicPropertyValue(obj, nullableHasValueProp))
                {
                    validationErrors.Add(new ValidationError(path, "Property is required, found null"));
                    return(false);
                }

                var nullableValueProp = nullableProps.First(p => p.Name == nameof(Nullable <bool> .Value));
                var nullableValue     = PortableTypeInfo.GetPublicPropertyValue(obj, nullableValueProp);
                return(ValidateInternal(nullableValue, path, validation, validationErrors));
            }

            var collection = obj as ICollection;

            if (collection != null)
            {
                var c = collection.Count;
                if (c < validation.CollectionItemsMinCount)
                {
                    validationErrors.Add(new ValidationError(path, $"Minimum item count is {validation.CollectionItemsMinCount}, found {c}"));
                }
                if (c > validation.CollectionItemsMaxCount)
                {
                    validationErrors.Add(new ValidationError(path, $"Maximum item count is {validation.CollectionItemsMaxCount}, found {c}"));
                }
            }

            var enumerable = obj as IEnumerable;

            if (enumerable != null && validation.Enumerable)
            {
                var itemValidation = new ValidateAttribute {
                    Required = validation.EnumerableItemsRequired
                };
                var index = 0;
                foreach (var item in enumerable)
                {
                    var indexedNewPath = $"{path}[{index++}]";
                    ValidateInternal(item, indexedNewPath, itemValidation, validationErrors);
                }
            }

            if (PortableTypeInfo.IsClass(objType) || isValueType)
            {
                var props    = PortableTypeInfo.GetPublicProperties(objType);
                var reqProps = from p in props
                               from a in PortableTypeInfo.GetCustomAttributes(p, false)
                               let v = a as ValidateAttribute
                                       where v != null
                                       select new { PropertyInfo = p, Validation = v };

#if !(NETSTD10 || NETSTD11) && FAST_MEMBER
                var typeAccessor = Reflection.FastMember.TypeAccessor.Create(objType);
#endif

                foreach (var rp in reqProps)
                {
                    var propertyInfo = rp.PropertyInfo;

#if !(NETSTD10 || NETSTD11) && FAST_MEMBER
                    var propertyValue = PortableTypeInfo.GetPublicPropertyValue(typeAccessor, obj, propertyInfo);
#else
                    var propertyValue = PortableTypeInfo.GetPublicPropertyValue(obj, propertyInfo);
#endif

                    var newPath = $"{path}.{propertyInfo.Name}";
                    ValidateInternal(propertyValue, newPath, rp.Validation, validationErrors);
                }

                return(validationErrors.Count == 0);
            }

            // Non dovrei mai finire qui!
            return(true);
        }
예제 #2
0
        private static bool ValidateInternal(object obj, string path, ValidateAttribute validation, IList<ValidationError> validationErrors)
        {
            if (ReferenceEquals(obj, null))
            {
                if (validation.Required)
                {
                    validationErrors.Add(new ValidationError { Path = path, Reason = "Property is required, found null" });
                    return false;
                }

                // If object is null, we cannot do anything else.
                return true;
            }

            var objType = obj.GetType();

            if (AlwaysValidTypes.Contains(objType) || PortableTypeInfo.IsEnum(objType))
            {
                return true;
            }

            var isValueType = PortableTypeInfo.IsValueType(objType);

            // Check whether this type is nullable.
            if (validation.Required && isValueType && PortableTypeInfo.IsGenericType(objType) && objType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                var nullableProps = PortableTypeInfo.GetPublicProperties(objType);
                var nullableHasValueProp = nullableProps.First(p => p.Name == nameof(Nullable<bool>.HasValue));

                if ((bool) PortableTypeInfo.GetPublicPropertyValue(obj, nullableHasValueProp))
                {
                    validationErrors.Add(new ValidationError { Path = path, Reason = "Property is required, found null" });
                    return false;
                }

                var nullableValueProp = nullableProps.First(p => p.Name == nameof(Nullable<bool>.Value));
                var nullableValue = PortableTypeInfo.GetPublicPropertyValue(obj, nullableValueProp);
                return ValidateInternal(nullableValue, path, validation, validationErrors);
            }

            var collection = obj as ICollection;
            if (collection != null)
            {
                var c = collection.Count;
                if (c < validation.CollectionItemsMinCount)
                {
                    validationErrors.Add(new ValidationError { Path = path, Reason = $"Minimum item count is {validation.CollectionItemsMinCount}, found {c}" });
                }
                if (c > validation.CollectionItemsMaxCount)
                {
                    validationErrors.Add(new ValidationError { Path = path, Reason = $"Maximum item count is {validation.CollectionItemsMaxCount}, found {c}" });
                }
            }

            var enumerable = obj as IEnumerable;
            if (enumerable != null && validation.Enumerable)
            {
                var itemValidation = new ValidateAttribute { Required = validation.EnumerableItemsRequired };
                var index = 0;
                foreach (var item in enumerable)
                {
                    var indexedNewPath = $"{path}[{index++}]";
                    ValidateInternal(item, indexedNewPath, itemValidation, validationErrors);
                }
            }

            if (PortableTypeInfo.IsClass(objType) || isValueType)
            {
                var props = PortableTypeInfo.GetPublicProperties(objType);
                var reqProps = from p in props
                               from a in PortableTypeInfo.GetCustomAttributes(p, false)
                               let v = a as ValidateAttribute
                               where v != null
                               select new { PropertyInfo = p, Validation = v };

#if !(PORTABLE || NETSTD11 || NETSTD13)
                var typeAccessor = Reflection.FastMember.TypeAccessor.Create(objType);
#endif

                foreach (var rp in reqProps)
                {
                    var propertyInfo = rp.PropertyInfo;

#if (PORTABLE || NETSTD11 || NETSTD13)
                    var propertyValue = PortableTypeInfo.GetPublicPropertyValue(obj, propertyInfo);
#else
                    var propertyValue = PortableTypeInfo.GetPublicPropertyValue(typeAccessor, obj, propertyInfo);
#endif

                    var newPath = $"{path}.{propertyInfo.Name}";
                    ValidateInternal(propertyValue, newPath, rp.Validation, validationErrors);
                }

                return validationErrors.Count == 0;
            }

            // Non dovrei mai finire qui!
            return true;
        }