using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
using System.Linq;
using System.Reflection;
{
if (!_typeStoreItems.TryGetValue(type, out TypeStoreItem? item))
{
- var attributes = TypeDescriptor.GetAttributes(type).Cast<Attribute>();
+ AttributeCollection attributes = TypeDescriptor.GetAttributes(type);
item = new TypeStoreItem(type, attributes);
_typeStoreItems[type] = item;
}
/// </summary>
private abstract class StoreItem
{
- internal StoreItem(IEnumerable<Attribute> attributes)
+ internal StoreItem(AttributeCollection attributes)
{
ValidationAttributes = attributes.OfType<ValidationAttribute>();
DisplayAttribute = attributes.OfType<DisplayAttribute>().SingleOrDefault();
private readonly Type _type;
private Dictionary<string, PropertyStoreItem>? _propertyStoreItems;
- internal TypeStoreItem([DynamicallyAccessedMembers(DynamicallyAccessedTypes)] Type type, IEnumerable<Attribute> attributes)
+ internal TypeStoreItem([DynamicallyAccessedMembers(DynamicallyAccessedTypes)] Type type, AttributeCollection attributes)
: base(attributes)
{
_type = type;
var properties = TypeDescriptor.GetProperties(_type);
foreach (PropertyDescriptor property in properties)
{
- var item = new PropertyStoreItem(property.PropertyType, GetExplicitAttributes(property).Cast<Attribute>());
+ var item = new PropertyStoreItem(property.PropertyType, GetExplicitAttributes(property));
propertyStoreItems[property.Name] = item;
}
[RequiresUnreferencedCode("The Type of propertyDescriptor.PropertyType cannot be statically discovered.")]
private AttributeCollection GetExplicitAttributes(PropertyDescriptor propertyDescriptor)
{
- List<Attribute> attributes = new List<Attribute>(propertyDescriptor.Attributes.Cast<Attribute>());
- IEnumerable<Attribute> typeAttributes = TypeDescriptor.GetAttributes(propertyDescriptor.PropertyType).Cast<Attribute>();
+ AttributeCollection propertyDescriptorAttributes = propertyDescriptor.Attributes;
+ List<Attribute> attributes = new List<Attribute>(propertyDescriptorAttributes.Count);
+ foreach (Attribute attribute in propertyDescriptorAttributes)
+ {
+ attributes.Add(attribute);
+ }
+
+ AttributeCollection typeAttributes = TypeDescriptor.GetAttributes(propertyDescriptor.PropertyType);
bool removedAttribute = false;
foreach (Attribute attr in typeAttributes)
{
}
}
}
- return removedAttribute ? new AttributeCollection(attributes.ToArray()) : propertyDescriptor.Attributes;
+ return removedAttribute ? new AttributeCollection(attributes.ToArray()) : propertyDescriptorAttributes;
}
}
/// </summary>
private sealed class PropertyStoreItem : StoreItem
{
- internal PropertyStoreItem(Type propertyType, IEnumerable<Attribute> attributes)
+ internal PropertyStoreItem(Type propertyType, AttributeCollection attributes)
: base(attributes)
{
Debug.Assert(propertyType != null);
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
using System.Linq;
-using System.Reflection;
namespace System.ComponentModel.DataAnnotations
{
public static bool TryValidateValue(object value, ValidationContext validationContext,
ICollection<ValidationResult>? validationResults, IEnumerable<ValidationAttribute> validationAttributes)
{
+ ArgumentNullException.ThrowIfNull(validationAttributes);
+
var result = true;
var breakOnFirstError = validationResults == null;
var attributes = _store.GetPropertyValidationAttributes(validationContext);
- GetValidationErrors(value, validationContext, attributes, false).FirstOrDefault()
- ?.ThrowValidationException();
+ List<ValidationError> errors = GetValidationErrors(value, validationContext, attributes, false);
+ if (errors.Count > 0)
+ {
+ errors[0].ThrowValidationException();
+ }
}
/// <summary>
throw new ArgumentException(SR.Validator_InstanceMustMatchValidationContextInstance, nameof(instance));
}
- GetObjectValidationErrors(instance, validationContext, validateAllProperties, false).FirstOrDefault()?.ThrowValidationException();
+ List<ValidationError> errors = GetObjectValidationErrors(instance, validationContext, validateAllProperties, false);
+ if (errors.Count > 0)
+ {
+ errors[0].ThrowValidationException();
+ }
}
/// <summary>
public static void ValidateValue(object value, ValidationContext validationContext,
IEnumerable<ValidationAttribute> validationAttributes)
{
- if (validationContext == null)
+ ArgumentNullException.ThrowIfNull(validationContext);
+ ArgumentNullException.ThrowIfNull(validationAttributes);
+
+ List<ValidationError> errors = GetValidationErrors(value, validationContext, validationAttributes, false);
+ if (errors.Count > 0)
{
- throw new ArgumentNullException(nameof(validationContext));
+ errors[0].ThrowValidationException();
}
-
- GetValidationErrors(value, validationContext, validationAttributes, false).FirstOrDefault()?.ThrowValidationException();
}
/// <summary>
/// <see cref="ValidationContext.ObjectInstance" /> on <paramref name="validationContext" />.
/// </exception>
[RequiresUnreferencedCode(ValidationContext.InstanceTypeNotStaticallyDiscovered)]
- private static IEnumerable<ValidationError> GetObjectValidationErrors(object instance,
+ private static List<ValidationError> GetObjectValidationErrors(object instance,
ValidationContext validationContext, bool validateAllProperties, bool breakOnFirstError)
{
Debug.Assert(instance != null);
breakOnFirstError));
// We only proceed to Step 2 if there are no errors
- if (errors.Any())
+ if (errors.Count > 0)
{
return errors;
}
errors.AddRange(GetValidationErrors(instance, validationContext, attributes, breakOnFirstError));
// We only proceed to Step 3 if there are no errors
- if (errors.Any())
+ if (errors.Count > 0)
{
return errors;
}
if (results != null)
{
- foreach (var result in results.Where(r => r != ValidationResult.Success))
+ foreach (ValidationResult result in results)
{
- errors.Add(new ValidationError(null, instance, result));
+ if (result != ValidationResult.Success)
+ {
+ errors.Add(new ValidationError(null, instance, result));
+ }
}
}
}
}
else
{
- // only validate the Required attributes
- var reqAttr = attributes.OfType<RequiredAttribute>().FirstOrDefault();
- if (reqAttr != null)
+ // only validate the first Required attribute
+ foreach (ValidationAttribute attribute in attributes)
{
- // Note: we let the [Required] attribute do its own null testing,
- // since the user may have subclassed it and have a deeper meaning to what 'required' means
- var validationResult = reqAttr.GetValidationResult(property.Value, property.Key);
- if (validationResult != ValidationResult.Success)
+ if (attribute is RequiredAttribute reqAttr)
{
- errors.Add(new ValidationError(reqAttr, property.Value, validationResult!));
+ // Note: we let the [Required] attribute do its own null testing,
+ // since the user may have subclassed it and have a deeper meaning to what 'required' means
+ var validationResult = reqAttr.GetValidationResult(property.Value, property.Key);
+ if (validationResult != ValidationResult.Success)
+ {
+ errors.Add(new ValidationError(reqAttr, property.Value, validationResult!));
+ }
+ break;
}
}
}
- if (breakOnFirstError && errors.Any())
+ if (breakOnFirstError && errors.Count > 0)
{
break;
}
/// </param>
/// <returns>The collection of validation errors.</returns>
/// <exception cref="ArgumentNullException">When <paramref name="validationContext" /> is null.</exception>
- private static IEnumerable<ValidationError> GetValidationErrors(object? value,
+ private static List<ValidationError> GetValidationErrors(object? value,
ValidationContext validationContext, IEnumerable<ValidationAttribute> attributes, bool breakOnFirstError)
{
if (validationContext == null)
ValidationError? validationError;
// Get the required validator if there is one and test it first, aborting on failure
- var required = attributes.OfType<RequiredAttribute>().FirstOrDefault();
- if (required != null)
+ RequiredAttribute? required = null;
+ foreach (ValidationAttribute attribute in attributes)
{
- if (!TryValidate(value, validationContext, required, out validationError))
+ required = attribute as RequiredAttribute;
+ if (required is not null)
{
- errors.Add(validationError);
- return errors;
+ if (!TryValidate(value, validationContext, required, out validationError))
+ {
+ errors.Add(validationError);
+ return errors;
+ }
+ break;
}
}
// Iterate through the rest of the validators, skipping the required validator
- foreach (var attr in attributes)
+ foreach (ValidationAttribute attr in attributes)
{
if (attr != required)
{