From: Eric Erhardt Date: Thu, 5 Aug 2021 03:40:07 +0000 (-0500) Subject: Remove some Linq usages in ComponentModel.Annotations (#56753) X-Git-Tag: accepted/tizen/unified/20220110.054933~640 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5bef921d41e1dc6832c61d2d6e7cae13dc35a2db;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Remove some Linq usages in ComponentModel.Annotations (#56753) * Remove some Linq usages in ComponentModel.Annotations Contributes to #56631 * PR feedback * fixup --- diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CompareAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CompareAttribute.cs index cd995d2..4e3b82c 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CompareAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CompareAttribute.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.Linq; using System.Reflection; namespace System.ComponentModel.DataAnnotations @@ -36,7 +36,7 @@ namespace System.ComponentModel.DataAnnotations { return new ValidationResult(SR.Format(SR.CompareAttribute_UnknownProperty, OtherProperty)); } - if (otherPropertyInfo.GetIndexParameters().Any()) + if (otherPropertyInfo.GetIndexParameters().Length > 0) { throw new ArgumentException(SR.Format(SR.Common_PropertyNotFound, validationContext.ObjectType.FullName, OtherProperty)); } @@ -60,11 +60,13 @@ namespace System.ComponentModel.DataAnnotations private string? GetDisplayNameForProperty(PropertyInfo property) { - var attributes = CustomAttributeExtensions.GetCustomAttributes(property, true); - var display = attributes.OfType().FirstOrDefault(); - if (display != null) + IEnumerable attributes = CustomAttributeExtensions.GetCustomAttributes(property, true); + foreach (Attribute attribute in attributes) { - return display.GetName(); + if (attribute is DisplayAttribute display) + { + return display.GetName(); + } } return OtherProperty; diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EnumDataTypeAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EnumDataTypeAttribute.cs index 18dd723..ab5c549 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EnumDataTypeAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EnumDataTypeAttribute.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Globalization; -using System.Linq; namespace System.ComponentModel.DataAnnotations { @@ -100,7 +99,7 @@ namespace System.ComponentModel.DataAnnotations } private static bool IsEnumTypeInFlagsMode(Type enumType) => - enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any(); + enumType.IsDefined(typeof(FlagsAttribute), false); private static string? GetUnderlyingTypeValueString(Type enumType, object enumValue) => Convert.ChangeType(enumValue, Enum.GetUnderlyingType(enumType), CultureInfo.InvariantCulture).ToString(); diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataPropertyDescriptorWrapper.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataPropertyDescriptorWrapper.cs index b3f21b8..1f3204b 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataPropertyDescriptorWrapper.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataPropertyDescriptorWrapper.cs @@ -1,10 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.ComponentModel; -using System.Linq; - namespace System.ComponentModel.DataAnnotations { internal sealed class MetadataPropertyDescriptorWrapper : PropertyDescriptor @@ -16,8 +12,15 @@ namespace System.ComponentModel.DataAnnotations : base(descriptor, newAttributes) { _descriptor = descriptor; - var readOnlyAttribute = newAttributes.OfType().FirstOrDefault(); - _isReadOnly = (readOnlyAttribute != null ? readOnlyAttribute.IsReadOnly : false); + + foreach (Attribute attribute in newAttributes) + { + if (attribute is ReadOnlyAttribute readOnlyAttribute) + { + _isReadOnly = readOnlyAttribute.IsReadOnly; + break; + } + } } public override void AddValueChanged(object component, EventHandler handler) { _descriptor.AddValueChanged(component, handler); } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs index 6fa0655..f7a2680 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.Linq; using System.Reflection; @@ -124,7 +123,7 @@ namespace System.ComponentModel.DataAnnotations { if (!_typeStoreItems.TryGetValue(type, out TypeStoreItem? item)) { - var attributes = TypeDescriptor.GetAttributes(type).Cast(); + AttributeCollection attributes = TypeDescriptor.GetAttributes(type); item = new TypeStoreItem(type, attributes); _typeStoreItems[type] = item; } @@ -153,7 +152,7 @@ namespace System.ComponentModel.DataAnnotations /// private abstract class StoreItem { - internal StoreItem(IEnumerable attributes) + internal StoreItem(AttributeCollection attributes) { ValidationAttributes = attributes.OfType(); DisplayAttribute = attributes.OfType().SingleOrDefault(); @@ -176,7 +175,7 @@ namespace System.ComponentModel.DataAnnotations private readonly Type _type; private Dictionary? _propertyStoreItems; - internal TypeStoreItem([DynamicallyAccessedMembers(DynamicallyAccessedTypes)] Type type, IEnumerable attributes) + internal TypeStoreItem([DynamicallyAccessedMembers(DynamicallyAccessedTypes)] Type type, AttributeCollection attributes) : base(attributes) { _type = type; @@ -224,7 +223,7 @@ namespace System.ComponentModel.DataAnnotations var properties = TypeDescriptor.GetProperties(_type); foreach (PropertyDescriptor property in properties) { - var item = new PropertyStoreItem(property.PropertyType, GetExplicitAttributes(property).Cast()); + var item = new PropertyStoreItem(property.PropertyType, GetExplicitAttributes(property)); propertyStoreItems[property.Name] = item; } @@ -243,8 +242,14 @@ namespace System.ComponentModel.DataAnnotations [RequiresUnreferencedCode("The Type of propertyDescriptor.PropertyType cannot be statically discovered.")] private AttributeCollection GetExplicitAttributes(PropertyDescriptor propertyDescriptor) { - List attributes = new List(propertyDescriptor.Attributes.Cast()); - IEnumerable typeAttributes = TypeDescriptor.GetAttributes(propertyDescriptor.PropertyType).Cast(); + AttributeCollection propertyDescriptorAttributes = propertyDescriptor.Attributes; + List attributes = new List(propertyDescriptorAttributes.Count); + foreach (Attribute attribute in propertyDescriptorAttributes) + { + attributes.Add(attribute); + } + + AttributeCollection typeAttributes = TypeDescriptor.GetAttributes(propertyDescriptor.PropertyType); bool removedAttribute = false; foreach (Attribute attr in typeAttributes) { @@ -259,7 +264,7 @@ namespace System.ComponentModel.DataAnnotations } } } - return removedAttribute ? new AttributeCollection(attributes.ToArray()) : propertyDescriptor.Attributes; + return removedAttribute ? new AttributeCollection(attributes.ToArray()) : propertyDescriptorAttributes; } } @@ -268,7 +273,7 @@ namespace System.ComponentModel.DataAnnotations /// private sealed class PropertyStoreItem : StoreItem { - internal PropertyStoreItem(Type propertyType, IEnumerable attributes) + internal PropertyStoreItem(Type propertyType, AttributeCollection attributes) : base(attributes) { Debug.Assert(propertyType != null); diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs index c702de8..3e40940 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs @@ -4,9 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.Linq; -using System.Reflection; namespace System.ComponentModel.DataAnnotations { @@ -190,6 +188,8 @@ namespace System.ComponentModel.DataAnnotations public static bool TryValidateValue(object value, ValidationContext validationContext, ICollection? validationResults, IEnumerable validationAttributes) { + ArgumentNullException.ThrowIfNull(validationAttributes); + var result = true; var breakOnFirstError = validationResults == null; @@ -224,8 +224,11 @@ namespace System.ComponentModel.DataAnnotations var attributes = _store.GetPropertyValidationAttributes(validationContext); - GetValidationErrors(value, validationContext, attributes, false).FirstOrDefault() - ?.ThrowValidationException(); + List errors = GetValidationErrors(value, validationContext, attributes, false); + if (errors.Count > 0) + { + errors[0].ThrowValidationException(); + } } /// @@ -289,7 +292,11 @@ namespace System.ComponentModel.DataAnnotations throw new ArgumentException(SR.Validator_InstanceMustMatchValidationContextInstance, nameof(instance)); } - GetObjectValidationErrors(instance, validationContext, validateAllProperties, false).FirstOrDefault()?.ThrowValidationException(); + List errors = GetObjectValidationErrors(instance, validationContext, validateAllProperties, false); + if (errors.Count > 0) + { + errors[0].ThrowValidationException(); + } } /// @@ -312,12 +319,14 @@ namespace System.ComponentModel.DataAnnotations public static void ValidateValue(object value, ValidationContext validationContext, IEnumerable validationAttributes) { - if (validationContext == null) + ArgumentNullException.ThrowIfNull(validationContext); + ArgumentNullException.ThrowIfNull(validationAttributes); + + List 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(); } /// @@ -399,7 +408,7 @@ namespace System.ComponentModel.DataAnnotations /// on . /// [RequiresUnreferencedCode(ValidationContext.InstanceTypeNotStaticallyDiscovered)] - private static IEnumerable GetObjectValidationErrors(object instance, + private static List GetObjectValidationErrors(object instance, ValidationContext validationContext, bool validateAllProperties, bool breakOnFirstError) { Debug.Assert(instance != null); @@ -415,7 +424,7 @@ namespace System.ComponentModel.DataAnnotations breakOnFirstError)); // We only proceed to Step 2 if there are no errors - if (errors.Any()) + if (errors.Count > 0) { return errors; } @@ -425,7 +434,7 @@ namespace System.ComponentModel.DataAnnotations 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; } @@ -437,9 +446,12 @@ namespace System.ComponentModel.DataAnnotations 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)); + } } } } @@ -477,21 +489,24 @@ namespace System.ComponentModel.DataAnnotations } else { - // only validate the Required attributes - var reqAttr = attributes.OfType().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; } @@ -547,7 +562,7 @@ namespace System.ComponentModel.DataAnnotations /// /// The collection of validation errors. /// When is null. - private static IEnumerable GetValidationErrors(object? value, + private static List GetValidationErrors(object? value, ValidationContext validationContext, IEnumerable attributes, bool breakOnFirstError) { if (validationContext == null) @@ -559,18 +574,23 @@ namespace System.ComponentModel.DataAnnotations ValidationError? validationError; // Get the required validator if there is one and test it first, aborting on failure - var required = attributes.OfType().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) {