diff --git a/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs index de1aefbe31c0f5..3e1e24968c4899 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs @@ -418,7 +418,7 @@ private static void AddAttributesToList(List attributeList, Attribute } } - private static AttributeUsageAttribute InternalGetAttributeUsage(Type type) + internal static AttributeUsageAttribute InternalGetAttributeUsage(Type type) { // Check if the custom attributes is Inheritable object[] obj = type.GetCustomAttributes(typeof(AttributeUsageAttribute), false); @@ -433,6 +433,8 @@ private static AttributeUsageAttribute InternalGetAttributeUsage(Type type) SR.Format(SR.Format_AttributeUsage, type)); } + [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", + Justification = "Array.CreateInstance is only used with reference types (attribute types) here.")] private static Attribute[] CreateAttributeArrayHelper(Type elementType, int elementCount) => elementType.ContainsGenericParameters ? new Attribute[elementCount] : (Attribute[])Array.CreateInstance(elementType, elementCount); #endregion diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs index 7f8b412546d139..3e07c1f29f4e93 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs @@ -193,21 +193,6 @@ public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle return fieldInfo; } - public static EventInfo GetImplicitlyOverriddenBaseClassEvent(EventInfo e) - { - return e.GetImplicitlyOverriddenBaseClassMember(EventPolicies.Instance); - } - - public static MethodInfo GetImplicitlyOverriddenBaseClassMethod(MethodInfo m) - { - return m.GetImplicitlyOverriddenBaseClassMember(MethodPolicies.Instance); - } - - public static PropertyInfo GetImplicitlyOverriddenBaseClassProperty(PropertyInfo p) - { - return p.GetImplicitlyOverriddenBaseClassMember(PropertyPolicies.Instance); - } - private static RuntimeFieldInfo GetFieldInfo(RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle) { RuntimeTypeInfo contextTypeInfo = declaringTypeHandle.GetRuntimeTypeInfoForRuntimeTypeHandle(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs deleted file mode 100644 index f904fe769abeea..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs +++ /dev/null @@ -1,250 +0,0 @@ -// 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.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Reflection; - -using Internal.Reflection.Augments; - -//================================================================================================================== -// Dependency note: -// This class must depend only on the CustomAttribute properties that return IEnumerable. -// All of the other custom attribute api route back here so calls to them will cause an infinite recursion. -//================================================================================================================== - -namespace Internal.Reflection.Extensions.NonPortable -{ - internal static class CustomAttributeInheritanceRules - { - //============================================================================================================================== - // Api helpers: Computes the effective set of custom attributes for various Reflection elements and returns them - // as CustomAttributeData objects. - //============================================================================================================================== - public static IEnumerable GetMatchingCustomAttributes(this Assembly element, Type optionalAttributeTypeFilter, bool skipTypeValidation = false) - { - return AssemblyCustomAttributeSearcher.Default.GetMatchingCustomAttributes(element, optionalAttributeTypeFilter, inherit: false, skipTypeValidation: skipTypeValidation); - } - - public static IEnumerable GetMatchingCustomAttributes(this Module element, Type optionalAttributeTypeFilter, bool skipTypeValidation = false) - { - return ModuleCustomAttributeSearcher.Default.GetMatchingCustomAttributes(element, optionalAttributeTypeFilter, inherit: false, skipTypeValidation: skipTypeValidation); - } - - public static IEnumerable GetMatchingCustomAttributes(this ParameterInfo element, Type optionalAttributeTypeFilter, bool inherit, bool skipTypeValidation = false) - { - return ParameterCustomAttributeSearcher.Default.GetMatchingCustomAttributes(element, optionalAttributeTypeFilter, inherit, skipTypeValidation: skipTypeValidation); - } - - public static IEnumerable GetMatchingCustomAttributes(this MemberInfo element, Type optionalAttributeTypeFilter, bool inherit, bool skipTypeValidation = false) - { - { - Type? type = element as Type; - if (type != null) - return TypeCustomAttributeSearcher.Default.GetMatchingCustomAttributes(type, optionalAttributeTypeFilter, inherit, skipTypeValidation: skipTypeValidation); - } - { - ConstructorInfo? constructorInfo = element as ConstructorInfo; - if (constructorInfo != null) - return ConstructorCustomAttributeSearcher.Default.GetMatchingCustomAttributes(constructorInfo, optionalAttributeTypeFilter, inherit: false, skipTypeValidation: skipTypeValidation); - } - { - MethodInfo? methodInfo = element as MethodInfo; - if (methodInfo != null) - return MethodCustomAttributeSearcher.Default.GetMatchingCustomAttributes(methodInfo, optionalAttributeTypeFilter, inherit, skipTypeValidation: skipTypeValidation); - } - { - FieldInfo? fieldInfo = element as FieldInfo; - if (fieldInfo != null) - return FieldCustomAttributeSearcher.Default.GetMatchingCustomAttributes(fieldInfo, optionalAttributeTypeFilter, inherit: false, skipTypeValidation: skipTypeValidation); - } - { - PropertyInfo? propertyInfo = element as PropertyInfo; - if (propertyInfo != null) - return PropertyCustomAttributeSearcher.Default.GetMatchingCustomAttributes(propertyInfo, optionalAttributeTypeFilter, inherit, skipTypeValidation: skipTypeValidation); - } - { - EventInfo? eventInfo = element as EventInfo; - if (eventInfo != null) - return EventCustomAttributeSearcher.Default.GetMatchingCustomAttributes(eventInfo, optionalAttributeTypeFilter, inherit, skipTypeValidation: skipTypeValidation); - } - - ArgumentNullException.ThrowIfNull(element); - - throw new NotSupportedException(); // Shouldn't get here. - } - - - - - //============================================================================================================================== - // Searcher class for Assemblies. - //============================================================================================================================== - private sealed class AssemblyCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(Assembly element) - { - return element.CustomAttributes; - } - - public static readonly AssemblyCustomAttributeSearcher Default = new AssemblyCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for Modules. - //============================================================================================================================== - private sealed class ModuleCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(Module element) - { - return element.CustomAttributes; - } - - public static readonly ModuleCustomAttributeSearcher Default = new ModuleCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for TypeInfos. - //============================================================================================================================== - private sealed class TypeCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(Type element) - { - return element.CustomAttributes; - } - - public sealed override Type GetParent(Type e) - { - Type? baseType = e.BaseType; - if (baseType == null) - return null; - - // Optimization: We shouldn't have any public inheritable attributes on Object or ValueType so don't bother scanning this one. - // Since many types derive directly from Object, this should a lot of type. - if (baseType == typeof(object) || baseType == typeof(ValueType)) - return null; - - return baseType; - } - - public static readonly TypeCustomAttributeSearcher Default = new TypeCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for FieldInfos. - //============================================================================================================================== - private sealed class FieldCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(FieldInfo element) - { - return element.CustomAttributes; - } - - public static readonly FieldCustomAttributeSearcher Default = new FieldCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for ConstructorInfos. - //============================================================================================================================== - private sealed class ConstructorCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(ConstructorInfo element) - { - return element.CustomAttributes; - } - - public static readonly ConstructorCustomAttributeSearcher Default = new ConstructorCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for MethodInfos. - //============================================================================================================================== - private sealed class MethodCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(MethodInfo element) - { - return element.CustomAttributes; - } - - public sealed override MethodInfo GetParent(MethodInfo e) - { - return ReflectionAugments.GetImplicitlyOverriddenBaseClassMethod(e); - } - - public static readonly MethodCustomAttributeSearcher Default = new MethodCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for PropertyInfos. - //============================================================================================================================== - private sealed class PropertyCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(PropertyInfo element) - { - return element.CustomAttributes; - } - - public sealed override PropertyInfo GetParent(PropertyInfo e) - { - return ReflectionAugments.GetImplicitlyOverriddenBaseClassProperty(e); - } - - public static readonly PropertyCustomAttributeSearcher Default = new PropertyCustomAttributeSearcher(); - } - - - //============================================================================================================================== - // Searcher class for EventInfos. - //============================================================================================================================== - private sealed class EventCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(EventInfo element) - { - return element.CustomAttributes; - } - - public sealed override EventInfo GetParent(EventInfo e) - { - return ReflectionAugments.GetImplicitlyOverriddenBaseClassEvent(e); - } - - public static readonly EventCustomAttributeSearcher Default = new EventCustomAttributeSearcher(); - } - - //============================================================================================================================== - // Searcher class for ParameterInfos. - //============================================================================================================================== - private sealed class ParameterCustomAttributeSearcher : CustomAttributeSearcher - { - protected sealed override IEnumerable GetDeclaredCustomAttributes(ParameterInfo element) - { - return element.CustomAttributes; - } - - public sealed override ParameterInfo GetParent(ParameterInfo e) - { - MethodInfo? method = e.Member as MethodInfo; - if (method == null) - return null; // This is a constructor parameter. - MethodInfo? methodParent = new MethodCustomAttributeSearcher().GetParent(method); - if (methodParent == null) - return null; - - if (e.Position >= 0) - { - return methodParent.GetParametersAsSpan()[e.Position]; - } - else - { - Debug.Assert(e.Position == -1); - return methodParent.ReturnParameter; - } - } - - public static readonly ParameterCustomAttributeSearcher Default = new ParameterCustomAttributeSearcher(); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs deleted file mode 100644 index 2e2e5ebdf95bd9..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeSearcher.cs +++ /dev/null @@ -1,203 +0,0 @@ -// 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.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; - -//================================================================================================================== -// Dependency note: -// This class must depend only on the CustomAttribute properties that return IEnumerable. -// All of the other custom attribute api route back here so calls to them will cause an infinite recursion. -//================================================================================================================== - -namespace Internal.Reflection.Extensions.NonPortable -{ - // - // Common logic for computing the effective set of custom attributes on a reflection element of type E where - // E is a MemberInfo, ParameterInfo, Assembly or Module. - // - // This class is only used by the CustomAttributeExtensions class - hence, we bake in the CustomAttributeExtensions behavior of - // filtering out WinRT attributes. - // - internal abstract class CustomAttributeSearcher - where E : class - { - // - // Returns the effective set of custom attributes on a reflection element. - // - public IEnumerable GetMatchingCustomAttributes(E element, Type optionalAttributeTypeFilter, bool inherit, bool skipTypeValidation = false) - { - // Do all parameter validation here before we enter the iterator function (so that exceptions from validations - // show up immediately rather than on the first MoveNext()). - ArgumentNullException.ThrowIfNull(element); - - bool typeFilterKnownToBeSealed = false; - if (!skipTypeValidation) - { - ArgumentNullException.ThrowIfNull(optionalAttributeTypeFilter, "type"); - if (!(optionalAttributeTypeFilter == typeof(Attribute) || - optionalAttributeTypeFilter.IsSubclassOf(typeof(Attribute)))) - throw new ArgumentException(SR.Argument_MustHaveAttributeBaseClass); - - typeFilterKnownToBeSealed = optionalAttributeTypeFilter.IsSealed; - } - - Func passesFilter; - if (optionalAttributeTypeFilter == null) - { - passesFilter = - delegate (Type actualType) - { - return true; - }; - } - else if (optionalAttributeTypeFilter.IsGenericTypeDefinition) - { - passesFilter = - delegate (Type actualType) - { - if (actualType.IsConstructedGenericType && actualType.GetGenericTypeDefinition() == optionalAttributeTypeFilter) - { - return true; - } - - if (!typeFilterKnownToBeSealed) - { - for (Type? type = actualType.BaseType; type != null; type = type.BaseType) - { - if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == optionalAttributeTypeFilter) - { - return true; - } - } - } - - return false; - }; - } - else - { - passesFilter = - delegate (Type actualType) - { - if (optionalAttributeTypeFilter.Equals(actualType)) - return true; - if (typeFilterKnownToBeSealed) - return false; - return optionalAttributeTypeFilter.IsAssignableFrom(actualType); - }; - } - - return GetMatchingCustomAttributesIterator(element, passesFilter, inherit); - } - - // - // Subclasses should override this to compute the "parent" of the element for the purpose of finding "inherited" custom attributes. - // Return null if no parent. - // - public virtual E GetParent(E e) - { - return null; - } - - - // - // Main iterator. - // - private IEnumerable GetMatchingCustomAttributesIterator(E element, Func passesFilter, bool inherit) - { - ListBuilder immediateResults = default; - foreach (CustomAttributeData cad in GetDeclaredCustomAttributes(element)) - { - if (passesFilter(cad.AttributeType)) - { - yield return cad; - - if (inherit) - immediateResults.Add(cad); - } - } - if (inherit) - { - // Because the "inherit" parameter defaults to "true", we probably get here for a lot of elements that - // don't actually have any inheritance chains. Try to avoid doing any unnecessary setup for the inheritance walk - // unless we have to. - element = GetParent(element); - if (element != null) - { - // This dictionary serves two purposes: - // - Let us know which attribute types we've encountered at lower levels so we can block them from appearing twice in the results - // if appropriate. - // - // - Cache the results of retrieving the usage attribute. - // - LowLevelDictionary encounteredTypes = new LowLevelDictionary(11); - - for (int i = 0; i < immediateResults.Count; i++) - { - Type attributeType = immediateResults[i].AttributeType; - TypeUnificationKey attributeTypeKey = new TypeUnificationKey(attributeType); - if (!encounteredTypes.TryGetValue(attributeTypeKey, out _)) - encounteredTypes.Add(attributeTypeKey, null); - } - - do - { - foreach (CustomAttributeData cad in GetDeclaredCustomAttributes(element)) - { - Type attributeType = cad.AttributeType; - if (!passesFilter(attributeType)) - continue; - AttributeUsageAttribute? usage; - TypeUnificationKey attributeTypeKey = new TypeUnificationKey(attributeType); - if (!encounteredTypes.TryGetValue(attributeTypeKey, out usage)) - { - // Type was not encountered before. Only include it if it is inheritable. - usage = GetAttributeUsage(attributeType); - encounteredTypes.Add(attributeTypeKey, usage); - if (usage.Inherited) - yield return cad; - } - else - { - usage ??= GetAttributeUsage(attributeType); - encounteredTypes[attributeTypeKey] = usage; - // Type was encountered at a lower level. Only include it if its inheritable AND allowMultiple. - if (usage.Inherited && usage.AllowMultiple) - yield return cad; - } - } - } - while ((element = GetParent(element)) != null); - } - } - } - - // - // Internal helper to compute the AttributeUsage. This must be coded specially to avoid an infinite recursion. - // - private static AttributeUsageAttribute GetAttributeUsage(Type attributeType) - { - // This is only invoked when the seacher is called with "inherit: true", thus calling the searcher again - // with "inherit: false" will not cause infinite recursion. - // - // Legacy: Why aren't we checking the parent types? Answer: Although AttributeUsageAttribute is itself marked inheritable, desktop Reflection - // treats it as *non*-inheritable for the purpose of deciding whether another attribute class is inheritable. - // - AttributeUsageAttribute? usage = attributeType.GetCustomAttribute(inherit: false); - if (usage == null) - return new AttributeUsageAttribute(AttributeTargets.All) { AllowMultiple = false, Inherited = true }; - return usage; - } - - // - // Subclasses must implement this to call the element-specific CustomAttributes property. - // - protected abstract IEnumerable GetDeclaredCustomAttributes(E element); - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index f33fe581600a32..3fe5d8b22b0f2c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -64,6 +64,7 @@ + @@ -139,16 +140,13 @@ - - - @@ -166,6 +164,8 @@ + + @@ -407,7 +407,6 @@ - @@ -439,7 +438,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs deleted file mode 100644 index b68c2234d88fac..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs +++ /dev/null @@ -1,157 +0,0 @@ -// 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.Reflection; - -using Internal.LowLevelLinq; -using Internal.Reflection.Extensions.NonPortable; - -namespace System -{ - public abstract partial class Attribute - { - public static Attribute GetCustomAttribute(Assembly element, Type attributeType) - { - return OneOrNull(element.GetMatchingCustomAttributes(attributeType)); - } - public static Attribute GetCustomAttribute(Assembly element, Type attributeType, bool inherit) => GetCustomAttribute(element, attributeType); // "inherit" is meaningless for assemblies - - public static Attribute GetCustomAttribute(MemberInfo element, Type attributeType) => GetCustomAttribute(element, attributeType, inherit: true); - public static Attribute GetCustomAttribute(MemberInfo element, Type attributeType, bool inherit) - { - return OneOrNull(element.GetMatchingCustomAttributes(attributeType, inherit)); - } - - public static Attribute GetCustomAttribute(Module element, Type attributeType) - { - return OneOrNull(element.GetMatchingCustomAttributes(attributeType)); - } - public static Attribute GetCustomAttribute(Module element, Type attributeType, bool inherit) => GetCustomAttribute(element, attributeType); // "inherit" is meaningless for modules - - public static Attribute GetCustomAttribute(ParameterInfo element, Type attributeType) => CustomAttributeExtensions.GetCustomAttribute(element, attributeType, inherit: true); - public static Attribute GetCustomAttribute(ParameterInfo element, Type attributeType, bool inherit) - { - return OneOrNull(element.GetMatchingCustomAttributes(attributeType, inherit)); - } - - public static Attribute[] GetCustomAttributes(Assembly element) - { - IEnumerable matches = element.GetMatchingCustomAttributes(null, skipTypeValidation: true); - return matches.Select(m => m.Instantiate()).ToArray(); - } - public static Attribute[] GetCustomAttributes(Assembly element, bool inherit) => GetCustomAttributes(element); // "inherit" is meaningless for assemblies - public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType) - { - return Instantiate(element.GetMatchingCustomAttributes(attributeType), attributeType); - } - public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType, bool inherit) => GetCustomAttributes(element, attributeType); // "inherit" is meaningless for modules - - public static Attribute[] GetCustomAttributes(MemberInfo element) => GetCustomAttributes(element, inherit: true); - public static Attribute[] GetCustomAttributes(MemberInfo element, bool inherit) - { - IEnumerable matches = element.GetMatchingCustomAttributes(null, inherit, skipTypeValidation: true); - return matches.Select(m => m.Instantiate()).ToArray(); - } - public static Attribute[] GetCustomAttributes(MemberInfo element, Type attributeType) => GetCustomAttributes(element, attributeType, inherit: true); - public static Attribute[] GetCustomAttributes(MemberInfo element, Type attributeType, bool inherit) - { - return Instantiate(element.GetMatchingCustomAttributes(attributeType, inherit), attributeType); - } - - public static Attribute[] GetCustomAttributes(Module element) - { - IEnumerable matches = element.GetMatchingCustomAttributes(null, skipTypeValidation: true); - return matches.Select(m => m.Instantiate()).ToArray(); - } - public static Attribute[] GetCustomAttributes(Module element, bool inherit) => GetCustomAttributes(element); // "inherit" is meaningless for assemblies - public static Attribute[] GetCustomAttributes(Module element, Type attributeType) - { - return Instantiate(element.GetMatchingCustomAttributes(attributeType), attributeType); - } - public static Attribute[] GetCustomAttributes(Module element, Type attributeType, bool inherit) => GetCustomAttributes(element, attributeType); // "inherit" is meaningless for modules - - public static Attribute[] GetCustomAttributes(ParameterInfo element) => GetCustomAttributes(element, inherit: true); - public static Attribute[] GetCustomAttributes(ParameterInfo element, bool inherit) - { - IEnumerable matches = element.GetMatchingCustomAttributes(null, inherit, skipTypeValidation: true); - return matches.Select(m => m.Instantiate()).ToArray(); - } - public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType) => GetCustomAttributes(element, attributeType, inherit: true); - public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType, bool inherit) - { - return Instantiate(element.GetMatchingCustomAttributes(attributeType, inherit), attributeType); - } - - public static bool IsDefined(Assembly element, Type attributeType) - { - IEnumerable matches = element.GetMatchingCustomAttributes(attributeType); - return matches.Any(); - } - public static bool IsDefined(Assembly element, Type attributeType, bool inherit) => IsDefined(element, attributeType); // "inherit" is meaningless for assemblies - - public static bool IsDefined(MemberInfo element, Type attributeType) => IsDefined(element, attributeType, inherit: true); - public static bool IsDefined(MemberInfo element, Type attributeType, bool inherit) - { - IEnumerable matches = element.GetMatchingCustomAttributes(attributeType, inherit); - return matches.Any(); - } - - public static bool IsDefined(Module element, Type attributeType) - { - IEnumerable matches = element.GetMatchingCustomAttributes(attributeType); - return matches.Any(); - } - public static bool IsDefined(Module element, Type attributeType, bool inherit) => IsDefined(element, attributeType); // "inherit" is meaningless for modules - - public static bool IsDefined(ParameterInfo element, Type attributeType) => IsDefined(element, attributeType, inherit: true); - public static bool IsDefined(ParameterInfo element, Type attributeType, bool inherit) - { - IEnumerable matches = element.GetMatchingCustomAttributes(attributeType, inherit); - return matches.Any(); - } - - //============================================================================================================================== - // Helper for the GetCustomAttribute() family. - //============================================================================================================================== - private static Attribute OneOrNull(IEnumerable results) - { - IEnumerator enumerator = results.GetEnumerator(); - if (!enumerator.MoveNext()) - return null; - CustomAttributeData result = enumerator.Current; - if (enumerator.MoveNext()) - throw ThrowHelper.GetAmbiguousMatchException(result); - return result.Instantiate(); - } - - //============================================================================================================================== - // Helper for the GetCustomAttributes() methods that take a specific attribute type. For desktop compatibility, - // we return a freshly allocated array of the specific attribute type even though the api's return type promises only an Attribute[]. - // There are known store apps that cast the results of apis and expect the cast to work. - //============================================================================================================================== - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", - Justification = "Arrays of reference types are safe to create.")] - private static Attribute[] Instantiate(IEnumerable cads, Type actualElementType) - { - ArrayBuilder attributes = default; - foreach (CustomAttributeData cad in cads) - { - Attribute instantiatedAttribute = cad.Instantiate(); - attributes.Add(instantiatedAttribute); - } - - if (actualElementType.ContainsGenericParameters) - { - return attributes.ToArray(); - } - else - { - Attribute[] result = (Attribute[])Array.CreateInstance(actualElementType, attributes.Count); - attributes.CopyTo(result); - return result; - } - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs index 99292670fa8aaa..23f2153a92b0a9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs @@ -170,6 +170,22 @@ internal Type GetTypeCore(string fullName, bool throwOnError, bool ignoreCase) // Types that derive from RuntimeAssembly must implement the following public surface area members public abstract override IEnumerable CustomAttributes { get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object)); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType); + } + public abstract override IEnumerable DefinedTypes { [RequiresUnreferencedCode("Types might be removed")] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs index 3faf9f9633e3d3..2731753ab57dca 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeInfos; namespace System.Reflection.Runtime.BindingFlagSupport @@ -17,13 +16,6 @@ internal sealed class ConstructorPolicies : MemberPolicies public ConstructorPolicies() : base(MemberTypeIndex.Constructor) { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Reflection implementation")] - public sealed override IEnumerable GetDeclaredMembers(Type type) - { - return type.GetConstructors(DeclaredOnlyLookup); - } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) { Debug.Assert(reflectedType.Equals(type)); // Constructor queries are always performed as if BindingFlags.DeclaredOnly are set so the reflectedType should always be the declaring type. @@ -47,8 +39,6 @@ public sealed override void GetMemberAttributes(ConstructorInfo member, out Meth isNewSlot = false; } - public sealed override bool ImplicitlyOverrides(ConstructorInfo? baseMember, ConstructorInfo? derivedMember) => false; - public sealed override bool IsSuppressedByMoreDerivedMember(ConstructorInfo member, ConstructorInfo[] priorMembers, int startIndex, int endIndex) { return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs index ddbd29557ec946..e7d8dbe776cfda 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeInfos; namespace System.Reflection.Runtime.BindingFlagSupport @@ -17,13 +16,6 @@ internal sealed class EventPolicies : MemberPolicies public EventPolicies() : base(MemberTypeIndex.Event) { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Reflection implementation")] - public sealed override IEnumerable GetDeclaredMembers(Type type) - { - return type.GetEvents(DeclaredOnlyLookup); - } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredEvents(optionalNameFilter, reflectedType); @@ -67,13 +59,6 @@ public sealed override bool IsSuppressedByMoreDerivedMember(EventInfo member, Ev return false; } - public sealed override bool ImplicitlyOverrides(EventInfo? baseMember, EventInfo? derivedMember) - { - MethodInfo? baseAccessor = GetAccessorMethod(baseMember!); - MethodInfo? derivedAccessor = GetAccessorMethod(derivedMember!); - return MethodPolicies.Instance.ImplicitlyOverrides(baseAccessor, derivedAccessor); - } - public sealed override bool OkToIgnoreAmbiguity(EventInfo m1, EventInfo m2) { return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs index e60e8d7711137d..3b38d5199f05f1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeInfos; namespace System.Reflection.Runtime.BindingFlagSupport @@ -17,13 +16,6 @@ internal sealed class FieldPolicies : MemberPolicies public FieldPolicies() : base(MemberTypeIndex.Field) { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Reflection implementation")] - public sealed override IEnumerable GetDeclaredMembers(Type type) - { - return type.GetFields(DeclaredOnlyLookup); - } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredFields(optionalNameFilter, reflectedType); @@ -40,8 +32,6 @@ public sealed override void GetMemberAttributes(FieldInfo member, out MethodAttr isNewSlot = false; } - public sealed override bool ImplicitlyOverrides(FieldInfo baseMember, FieldInfo derivedMember) => false; - public sealed override bool IsSuppressedByMoreDerivedMember(FieldInfo member, FieldInfo[] priorMembers, int startIndex, int endIndex) { return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs index b15bd39962428b..18e4390d44a3e9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs @@ -24,11 +24,6 @@ public MemberPolicies(int index) // Subclasses for specific MemberInfo types must override these: //================================================================================================================= - // - // Returns all of the directly declared members on the given Type. - // - public abstract IEnumerable GetDeclaredMembers(Type type); - // // Returns all of the directly declared members on the given TypeInfo whose name matches optionalNameFilter. If optionalNameFilter is null, // returns all directly declared members. @@ -42,14 +37,6 @@ public MemberPolicies(int index) // public abstract void GetMemberAttributes(M member, out MethodAttributes visibility, out bool isStatic, out bool isVirtual, out bool isNewSlot); - // - // Policy to decide whether "derivedMember" is a virtual override of "baseMember." Used to implement MethodInfo.GetBaseDefinition(), - // parent chain traversal for discovering inherited custom attributes, and suppressing lookup results in the Type.Get*() api family. - // - // Does not consider explicit overrides (methodimpls.) Does not consider "overrides" of interface methods. - // - public abstract bool ImplicitlyOverrides(M baseMember, M derivedMember); - // // Policy to decide how BindingFlags should be reinterpreted for a given member type. // This is overridden for nested types which all match on any combination Instance | Static and are never inherited. @@ -189,8 +176,6 @@ private static bool GenericMethodAwareAreParameterTypesEqual(Type t1, Type t2) return false; } - protected const BindingFlags DeclaredOnlyLookup = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; - // // This returns a fixed value from 0 to MemberIndex.Count-1 with each possible type of M // being assigned a unique index (see the MemberTypeIndex for possible values). This is useful diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs index 0ab6d3af53181d..f41dd1d3d90c3c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeInfos; namespace System.Reflection.Runtime.BindingFlagSupport @@ -17,13 +16,6 @@ internal sealed class MethodPolicies : MemberPolicies public MethodPolicies() : base(MemberTypeIndex.Method) { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Reflection implementation")] - public sealed override IEnumerable GetDeclaredMembers(Type type) - { - return type.GetMethods(DeclaredOnlyLookup); - } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredMethods(optionalNameFilter, reflectedType); @@ -40,10 +32,10 @@ public sealed override void GetMemberAttributes(MethodInfo member, out MethodAtt isNewSlot = (0 != (methodAttributes & MethodAttributes.NewSlot)); } - public sealed override bool ImplicitlyOverrides(MethodInfo? baseMember, MethodInfo? derivedMember) + public static bool ImplicitlyOverrides(MethodInfo baseMember, MethodInfo derivedMember) { // TODO (https://github.com/dotnet/corert/issues/1896) Comparing signatures is fragile. The runtime and/or toolchain should have a way of sharing this info. - return AreNamesAndSignaturesEqual(baseMember!, derivedMember!); + return AreNamesAndSignaturesEqual(baseMember, derivedMember); } // diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs index 1e4a74bfc26f03..c1ab1ddb45c4b1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeInfos; namespace System.Reflection.Runtime.BindingFlagSupport @@ -27,13 +26,6 @@ internal sealed class NestedTypePolicies : MemberPolicies public NestedTypePolicies() : base(MemberTypeIndex.NestedType) { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Reflection implementation")] - public sealed override IEnumerable GetDeclaredMembers(Type type) - { - return type.GetNestedTypes(DeclaredOnlyLookup); - } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) { Debug.Assert(reflectedType.Equals(type)); // NestedType queries are always performed as if BindingFlags.DeclaredOnly are set so the reflectedType should always be the declaring type. @@ -53,8 +45,6 @@ public sealed override void GetMemberAttributes(Type member, out MethodAttribute visibility = member.IsNestedPublic ? MethodAttributes.Public : MethodAttributes.Private; } - public sealed override bool ImplicitlyOverrides(Type baseMember, Type derivedMember) => false; - public sealed override bool IsSuppressedByMoreDerivedMember(Type member, Type[] priorMembers, int startIndex, int endIndex) { return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs index 230c24b65c3b56..faab1886e42523 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeInfos; namespace System.Reflection.Runtime.BindingFlagSupport @@ -17,13 +16,6 @@ internal sealed class PropertyPolicies : MemberPolicies public PropertyPolicies() : base(MemberTypeIndex.Property) { } - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Reflection implementation")] - public sealed override IEnumerable GetDeclaredMembers(Type type) - { - return type.GetProperties(DeclaredOnlyLookup); - } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredProperties(optionalNameFilter, reflectedType); @@ -54,13 +46,6 @@ public sealed override void GetMemberAttributes(PropertyInfo member, out MethodA isNewSlot = (0 != (methodAttributes & MethodAttributes.NewSlot)); } - public sealed override bool ImplicitlyOverrides(PropertyInfo? baseMember, PropertyInfo? derivedMember) - { - MethodInfo? baseAccessor = GetAccessorMethod(baseMember!); - MethodInfo? derivedAccessor = GetAccessorMethod(derivedMember!); - return MethodPolicies.Instance.ImplicitlyOverrides(baseAccessor, derivedAccessor); - } - // // Desktop compat: Properties hide properties in base types if they share the same vtable slot, or // have the same name, return type, signature and hasThis value. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs index 056a827ec344ae..095fdb7bbe083b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.General; namespace System.Reflection.Runtime.BindingFlagSupport @@ -146,15 +147,15 @@ public static bool QualifiesBasedOnParameterCount(this MethodBase methodBase, Bi // - MethodImpls ignored. (I didn't say it made sense, this is just how the desktop api we're porting behaves.) // - Implemented interfaces ignores. (I didn't say it made sense, this is just how the desktop api we're porting behaves.) // - public static M GetImplicitlyOverriddenBaseClassMember(this M member, MemberPolicies policies) where M : MemberInfo + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "Reflection implementation")] + public static MethodInfo? GetImplicitlyOverriddenBaseClassMember(this MethodInfo member) { - bool isVirtual; - bool isNewSlot; - policies.GetMemberAttributes(member, out _, out _, out isVirtual, out isNewSlot); - if (isNewSlot || !isVirtual) + if (!member.IsVirtual || (member.Attributes & MethodAttributes.NewSlot) != 0) { return null; } + string name = member.Name; Type type = member.DeclaringType!; for (; ; ) @@ -165,19 +166,17 @@ public static M GetImplicitlyOverriddenBaseClassMember(this M member, MemberP return null; } type = baseType; - foreach (M candidate in policies.GetDeclaredMembers(type)) + foreach (MethodInfo candidate in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (candidate.Name != name) { continue; } - bool isCandidateVirtual; - policies.GetMemberAttributes(member, out _, out _, out isCandidateVirtual, out _); - if (!isCandidateVirtual) + if (!candidate.IsVirtual) { continue; } - if (!policies.ImplicitlyOverrides(candidate, member)) + if (!MethodPolicies.ImplicitlyOverrides(candidate, member)) { continue; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs index 288456a6a42e12..a06e4ed5e54bd8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs @@ -132,6 +132,22 @@ protected RuntimeEventInfo WithDebugName() // Types that derive from RuntimeEventInfo must implement the following public surface area members public abstract override EventAttributes Attributes { get; } public abstract override IEnumerable CustomAttributes { get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object), inherit: false); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType, inherit: false); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType, inherit: false); + } + public abstract override bool Equals(object obj); public abstract override int GetHashCode(); public abstract override Type EventHandlerType { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs index 1672c9843b2bf5..b5380af2e9fa0d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs @@ -70,6 +70,22 @@ public sealed override IEnumerable CustomAttributes } } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object), inherit); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType, inherit); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType, inherit); + } + public sealed override Type DeclaringType { get diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs index 946ba3cb736cd2..1a7852021baaa1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs @@ -136,35 +136,6 @@ public static BinderBundle ToBinderBundle(this Binder binder, BindingFlags invok return new BinderBundle(binder, cultureInfo); } - // Helper for ICustomAttributeProvider.GetCustomAttributes(). The result of this helper is returned directly to apps - // so it must always return a newly allocated array. Unlike most of the newer custom attribute apis, the attribute type - // need not derive from System.Attribute. (In particular, it can be an interface or System.Object.) - [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", - Justification = "Array.CreateInstance is only used with reference types here and is therefore safe.")] - public static object[] InstantiateAsArray(this IEnumerable cads, Type actualElementType) - { - ArrayBuilder attributes = default; - foreach (CustomAttributeData cad in cads) - { - object instantiatedAttribute = cad.Instantiate(); - attributes.Add(instantiatedAttribute); - } - - if (actualElementType.ContainsGenericParameters || actualElementType.IsValueType) - { - // This is here for desktop compatibility. ICustomAttribute.GetCustomAttributes() normally returns an array of the - // exact attribute type requested except in two cases: when the passed in type is an open type and when - // it is a value type. In these two cases, it returns an array of type Object[]. - return attributes.ToArray(); - } - else - { - object[] result = (object[])Array.CreateInstance(actualElementType, attributes.Count); - attributes.CopyTo(result); - return result; - } - } - private static object? GetRawDefaultValue(IEnumerable customAttributes) { foreach (CustomAttributeData attributeData in customAttributes) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs deleted file mode 100644 index 37b4d540818397..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// -// The older-style CustomAttribute-related members on the various Reflection types. The implementation dependency -// stack on .Net Native differs from that of CoreClr due to the difference in development history. -// -// - IEnumerable xInfo.get_CustomAttributes is at the very bottom of the dependency stack. -// -// - CustomAttributeExtensions layers on top of that (primarily because it's the one with the nice generic methods.) -// -// - Everything else is a thin layer over one of these two. -// -// - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Reflection.Runtime.General; - -using Internal.LowLevelLinq; -using Internal.Reflection.Extensions.NonPortable; - - -namespace System.Reflection.Runtime.Assemblies -{ - internal partial class RuntimeAssemblyInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this).ToArray(); // inherit is meaningless for Assemblies - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, skipTypeValidation: true); // inherit is meaningless for Assemblies - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, skipTypeValidation: true); // inherit is meaningless for Assemblies - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.MethodInfos -{ - internal abstract partial class RuntimeConstructorInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this, inherit).ToArray(); - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.EventInfos -{ - internal abstract partial class RuntimeEventInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this, inherit: false).ToArray(); // Desktop compat: for events, this form of the api ignores "inherit" - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: false, skipTypeValidation: true); // Desktop compat: for events, this form of the api ignores "inherit" - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: false, skipTypeValidation: true); // Desktop compat: for events, this form of the api ignores "inherit" - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.FieldInfos -{ - internal abstract partial class RuntimeFieldInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this, inherit).ToArray(); - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.MethodInfos -{ - internal abstract partial class RuntimeMethodInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this, inherit).ToArray(); - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.Modules -{ - internal abstract partial class RuntimeModule - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this).ToArray(); // inherit is meaningless for Modules - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, skipTypeValidation: true); // inherit is meaningless for Modules - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, skipTypeValidation: true); // inherit is meaningless for Modules - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.ParameterInfos -{ - internal abstract partial class RuntimeParameterInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this, inherit: false).ToArray(); // Desktop compat: for parameters, this form of the api ignores "inherit" - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: false, skipTypeValidation: true); // Desktop compat: for parameters, this form of the api ignores "inherit" - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: false, skipTypeValidation: true); // Desktop compat: for parameters, this form of the api ignores "inherit" - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.PropertyInfos -{ - internal abstract partial class RuntimePropertyInfo - { - public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public sealed override object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this, inherit: false).ToArray(); // Desktop compat: for properties, this form of the api ignores "inherit" - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: false, skipTypeValidation: true); // Desktop compat: for properties, this form of the api ignores "inherit" - return cads.InstantiateAsArray(attributeType); - } - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.GetMatchingCustomAttributes(attributeType, inherit: false, skipTypeValidation: true); // Desktop compat: for properties, this form of the api ignores "inherit" - return cads.Any(); - } - } -} - -namespace System.Reflection.Runtime.TypeInfos -{ - internal abstract partial class RuntimeTypeInfo - { - public IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); - public object[] GetCustomAttributes(bool inherit) => CustomAttributeExtensions.GetCustomAttributes(this.ToType(), inherit).ToArray(); - - public object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.ToType().GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.InstantiateAsArray(attributeType); - } - - public bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - IEnumerable cads = this.ToType().GetMatchingCustomAttributes(attributeType, inherit: inherit, skipTypeValidation: true); - return cads.Any(); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs index da530bc1d1f6d8..edc0057a7eaacc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs @@ -112,7 +112,7 @@ internal abstract partial class RuntimeEventInfo } } -namespace System.Reflection.Runtime.MethodInfos +namespace System.Reflection { internal abstract partial class RuntimeMethodInfo { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs index 1ed8e75c7d7d82..aba81ae94caf8a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Reflection.Runtime.General; using System.Reflection.Runtime.ParameterInfos; using Internal.Reflection.Core.Execution; @@ -32,6 +33,22 @@ public sealed override bool ContainsGenericParameters public abstract override Type DeclaringType { get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object), inherit); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType, inherit); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType, inherit); + } + [RequiresUnreferencedCode("Trimming may change method bodies. For example it can change some instructions, remove branches or local variables.")] public sealed override MethodBody GetMethodBody() { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs index 9812c65b0590cb..2695b75ba9cac2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.Assemblies; +using System.Reflection.Runtime.General; using System.Runtime.Serialization; namespace System.Reflection.Runtime.Modules @@ -26,6 +27,22 @@ protected RuntimeModule() public abstract override IEnumerable CustomAttributes { get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object)); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType); + } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public sealed override string FullyQualifiedName { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs index e74dbeb571ba47..246c4129accfea 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using System.Reflection.Runtime.General; namespace System.Reflection.Runtime.ParameterInfos { @@ -24,6 +25,22 @@ protected RuntimeParameterInfo(MemberInfo member, int position) public abstract override object DefaultValue { get; } public abstract override object RawDefaultValue { get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object)); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType); + } + public sealed override bool Equals(object obj) { if (!(obj is RuntimeParameterInfo other)) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs index 1665d354582f73..9dafa5f95dca8b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs @@ -284,6 +284,22 @@ protected RuntimePropertyInfo WithDebugName() // Types that derive from RuntimePropertyInfo must implement the following public surface area members public abstract override PropertyAttributes Attributes { get; } public abstract override IEnumerable CustomAttributes { get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object), inherit: false); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType, inherit: false); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType, inherit: false); + } + public abstract override bool Equals(object obj); public abstract override int GetHashCode(); public abstract override int MetadataToken { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs index c15c37507ff0fa..f88a751624872a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs @@ -104,6 +104,22 @@ public Type? BaseType public abstract IEnumerable CustomAttributes { get; } + public object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(ToType(), typeof(object), inherit); + + public object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(ToType(), attributeType, inherit); + } + + public IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(ToType(), attributeType, inherit); + } + // // Left unsealed as generic parameter types must override. // diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs new file mode 100644 index 00000000000000..f98920096185db --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs @@ -0,0 +1,192 @@ +// 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.Reflection.Runtime.General; +using System.Reflection.Runtime.MethodInfos; + +using Internal.LowLevelLinq; +using Internal.Reflection.Augments; +using Internal.Reflection.Extensions.NonPortable; + +namespace System.Reflection +{ + internal static class RuntimeCustomAttribute + { + internal static object[] GetCustomAttributes(Assembly element, Type attributeType) => + Instantiate(GetMatchingCustomAttributes(element, attributeType, inherit: false), attributeType); + + internal static object[] GetCustomAttributes(MemberInfo element, Type attributeType, bool inherit) => + Instantiate(GetMatchingCustomAttributes(element, attributeType, inherit), attributeType); + + internal static object[] GetCustomAttributes(Module element, Type attributeType) => + Instantiate(GetMatchingCustomAttributes(element, attributeType, inherit: false), attributeType); + + internal static object[] GetCustomAttributes(ParameterInfo element, Type attributeType) => + Instantiate(GetMatchingCustomAttributes(element, attributeType, inherit: false), attributeType); + + internal static bool IsDefined(Assembly element, Type attributeType) => + Any(GetMatchingCustomAttributes(element, attributeType, inherit: false)); + + internal static bool IsDefined(MemberInfo element, Type attributeType, bool inherit) => + Any(GetMatchingCustomAttributes(element, attributeType, inherit)); + + internal static bool IsDefined(Module element, Type attributeType) => + Any(GetMatchingCustomAttributes(element, attributeType, inherit: false)); + + internal static bool IsDefined(ParameterInfo element, Type attributeType) => + Any(GetMatchingCustomAttributes(element, attributeType, inherit: false)); + + private static bool Any(IEnumerable attributes) + { + using IEnumerator enumerator = attributes.GetEnumerator(); + return enumerator.MoveNext(); + } + + private static IEnumerable GetMatchingCustomAttributes(object element, Type attributeType, bool inherit) + { + Func passesFilter = CreateFilter(attributeType); + ListBuilder immediateResults = default; + + foreach (CustomAttributeData attribute in GetDeclaredCustomAttributes(element)) + { + if (passesFilter(attribute.AttributeType)) + { + yield return attribute; + + if (inherit) + immediateResults.Add(attribute); + } + } + + if (!inherit) + yield break; + + object? parent = GetParent(element); + if (parent is null) + yield break; + + LowLevelDictionary encounteredTypes = + new LowLevelDictionary(11); + + for (int i = 0; i < immediateResults.Count; i++) + { + TypeUnificationKey attributeTypeKey = new TypeUnificationKey(immediateResults[i].AttributeType); + if (!encounteredTypes.TryGetValue(attributeTypeKey, out _)) + encounteredTypes.Add(attributeTypeKey, null); + } + + do + { + foreach (CustomAttributeData attribute in GetDeclaredCustomAttributes(parent)) + { + Type actualAttributeType = attribute.AttributeType; + if (!passesFilter(actualAttributeType)) + continue; + + TypeUnificationKey attributeTypeKey = new TypeUnificationKey(actualAttributeType); + if (!encounteredTypes.TryGetValue(attributeTypeKey, out AttributeUsageAttribute? usage)) + { + usage = Attribute.InternalGetAttributeUsage(actualAttributeType); + encounteredTypes.Add(attributeTypeKey, usage); + if (usage.Inherited) + yield return attribute; + } + else + { + usage ??= Attribute.InternalGetAttributeUsage(actualAttributeType); + encounteredTypes[attributeTypeKey] = usage; + if (usage.Inherited && usage.AllowMultiple) + yield return attribute; + } + } + } + while ((parent = GetParent(parent)) is not null); + } + + private static Func CreateFilter(Type attributeType) + { + bool attributeTypeIsSealed = attributeType.IsSealed; + + if (attributeType.IsGenericTypeDefinition) + { + return actualType => + { + if (actualType.IsConstructedGenericType && actualType.GetGenericTypeDefinition() == attributeType) + return true; + + if (!attributeTypeIsSealed) + { + for (Type? type = actualType.BaseType; type is not null; type = type.BaseType) + { + if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == attributeType) + return true; + } + } + + return false; + }; + } + + return actualType => + attributeType.Equals(actualType) || + (!attributeTypeIsSealed && attributeType.IsAssignableFrom(actualType)); + } + + private static IEnumerable GetDeclaredCustomAttributes(object element) + { + return element switch + { + Assembly assembly => assembly.CustomAttributes, + MemberInfo member => member.CustomAttributes, + Module module => module.CustomAttributes, + ParameterInfo parameter => parameter.CustomAttributes, + _ => throw new NotSupportedException() + }; + } + + private static object? GetParent(object element) + { + if (element is Type type) + { + Type? baseType = type.BaseType; + return baseType == typeof(object) || baseType == typeof(ValueType) ? null : baseType; + } + + if (element is RuntimeMethodInfo method) + return method.GetParentDefinition(); + + return null; + } + + private static object[] Instantiate(IEnumerable customAttributes, Type actualElementType) + { + ArrayBuilder attributes = default; + foreach (CustomAttributeData customAttribute in customAttributes) + { + attributes.Add(customAttribute.Instantiate()); + } + + object[] result = CreateAttributeArrayHelper(actualElementType, attributes.Count); + attributes.CopyTo(result); + return result; + } + + [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", + Justification = "Array.CreateInstance is only used with reference types here and is therefore safe.")] + private static object[] CreateAttributeArrayHelper(Type attributeType, int elementCount) + { + if (attributeType == typeof(Attribute) || + (attributeType.ContainsGenericParameters && attributeType.IsSubclassOf(typeof(Attribute)))) + { + return new Attribute[elementCount]; + } + + if (attributeType.IsValueType || attributeType.ContainsGenericParameters) + return new object[elementCount]; + + return (object[])Array.CreateInstance(attributeType, elementCount); + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs rename to src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 19c08ded663d40..b6b2014c238415 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -16,7 +16,7 @@ using Internal.Reflection.Core.Execution; using Internal.Runtime.Augments; -namespace System.Reflection.Runtime.MethodInfos +namespace System.Reflection { // // Abstract base class for RuntimeNamedMethodInfo, RuntimeConstructedGenericMethodInfo. @@ -89,6 +89,22 @@ public abstract override IEnumerable CustomAttributes get; } + public sealed override object[] GetCustomAttributes(bool inherit) => RuntimeCustomAttribute.GetCustomAttributes(this, typeof(object), inherit); + + public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.GetCustomAttributes(this, attributeType, inherit); + } + + public sealed override IList GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection(); + + public sealed override bool IsDefined(Type attributeType, bool inherit) + { + ArgumentNullException.ThrowIfNull(attributeType); + return RuntimeCustomAttribute.IsDefined(this, attributeType, inherit); + } + public sealed override Type DeclaringType { get @@ -101,6 +117,9 @@ public sealed override Type DeclaringType public abstract override int GetHashCode(); + internal RuntimeMethodInfo? GetParentDefinition() + => (RuntimeMethodInfo?)this.GetImplicitlyOverriddenBaseClassMember(); + public sealed override MethodInfo GetBaseDefinition() { // This check is for compatibility. Yes, it happens before we normalize constructed generic methods back to their backing definition. @@ -116,8 +135,8 @@ public sealed override MethodInfo GetBaseDefinition() while (true) { - MethodInfo next = method.GetImplicitlyOverriddenBaseClassMember(MethodPolicies.Instance); - if (next == null) + MethodInfo? next = method.GetImplicitlyOverriddenBaseClassMember(); + if (next is null) return ((RuntimeMethodInfo)method).WithReflectedTypeSetToDeclaringType; method = next; diff --git a/src/libraries/System.Reflection.Context/tests/CustomReflectionContext.Examples.cs b/src/libraries/System.Reflection.Context/tests/CustomReflectionContext.Examples.cs index 053c20aabc373d..f6a197c4bd0559 100644 --- a/src/libraries/System.Reflection.Context/tests/CustomReflectionContext.Examples.cs +++ b/src/libraries/System.Reflection.Context/tests/CustomReflectionContext.Examples.cs @@ -39,7 +39,6 @@ protected override IEnumerable GetCustomAttributes(MemberInfo member, IE public class CustomReflectionContextExamples { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/73356", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public static void AddCustomAttribute() { #region Snippet2 diff --git a/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs b/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs index b23d5a7cbfe46e..a7c8a3a551aebd 100644 --- a/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs +++ b/src/libraries/System.Reflection.Context/tests/CustomReflectionContextTests.cs @@ -31,7 +31,6 @@ public void MapType_Null_Throws() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/73356", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] [ActiveIssue("https://github.com/mono/mono/issues/15191", TestRuntimes.Mono)] public void MapType_MemberAttributes_Success() { @@ -47,7 +46,6 @@ public void MapType_MemberAttributes_Success() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/73356", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] [ActiveIssue("https://github.com/mono/mono/issues/15191", TestRuntimes.Mono)] public void MapType_ParameterAttributes_Success() {