diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 07ec361a0f7d7..18428b0eb34ad 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -624,15 +624,18 @@ public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? bind throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, "this"); } - public override object[] GetCustomAttributes(Type attributeType, bool inherit) + public override object[] GetCustomAttributes(Type attributeType!!, bool inherit) { - if (attributeType == null) - throw new ArgumentNullException(nameof(attributeType)); + if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) + throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); - if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) - return new object[] { new MethodImplAttribute((MethodImplOptions)GetMethodImplementationFlags()) }; - else - return Array.Empty(); + bool includeMethodImplAttribute = attributeType.IsAssignableFrom(typeof(MethodImplAttribute)); + object[] result = CustomAttribute.CreateAttributeArrayHelper(attributeRuntimeType, includeMethodImplAttribute ? 1 : 0); + if (includeMethodImplAttribute) + { + result[0] = new MethodImplAttribute((MethodImplOptions)GetMethodImplementationFlags()); + } + return result; } public override object[] GetCustomAttributes(bool inherit) diff --git a/src/libraries/System.Runtime/tests/System/Attributes.cs b/src/libraries/System.Runtime/tests/System/Attributes.cs index 3dda3f56b3566..6d504c0eeecdb 100644 --- a/src/libraries/System.Runtime/tests/System/Attributes.cs +++ b/src/libraries/System.Runtime/tests/System/Attributes.cs @@ -17,6 +17,8 @@ using System.Reflection; using System.Linq; using System.Diagnostics; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Xunit; @@ -220,14 +222,34 @@ public static void GetCustomAttributes_Interface() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + public static void GetCustomAttributes_DynamicMethod() + { + var dynamicMethod = new DynamicMethod("test", typeof(void), Type.EmptyTypes); + dynamicMethod.GetILGenerator().Emit(OpCodes.Ret); + var action = (Action)dynamicMethod.CreateDelegate(typeof(Action)); + + Attribute[] attributes = Attribute.GetCustomAttributes(action.Method, typeof(NameableAttribute)); + Assert.Empty(attributes); + Assert.IsType(attributes); + + attributes = Attribute.GetCustomAttributes(action.Method); + Assert.Equal(1, attributes.Length); + Assert.IsType(attributes[0]); + + attributes = Attribute.GetCustomAttributes(action.Method, typeof(MethodImplAttribute)); + Assert.Equal(1, attributes.Length); + Assert.IsType(attributes); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForType() { GenericAttributesTestHelper(t => Attribute.GetCustomAttributes(typeof(HasGenericAttribute), t)); } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForField() { FieldInfo field = typeof(HasGenericAttribute).GetField(nameof(HasGenericAttribute.Field), BindingFlags.NonPublic | BindingFlags.Instance); @@ -235,7 +257,7 @@ public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForField } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForConstructor() { ConstructorInfo method = typeof(HasGenericAttribute).GetConstructor(Type.EmptyTypes); @@ -243,7 +265,7 @@ public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForConst } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForMethod() { MethodInfo method = typeof(HasGenericAttribute).GetMethod(nameof(HasGenericAttribute.Method)); @@ -251,7 +273,7 @@ public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForMetho } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForParameter() { ParameterInfo parameter = typeof(HasGenericAttribute).GetMethod(nameof(HasGenericAttribute.Method)).GetParameters()[0]; @@ -259,7 +281,7 @@ public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForParam } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForProperty() { PropertyInfo property = typeof(HasGenericAttribute).GetProperty(nameof(HasGenericAttribute.Property)); @@ -267,7 +289,7 @@ public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForPrope } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56887)", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/56887", TestRuntimes.Mono)] public static void GetCustomAttributesWorksWithOpenAndClosedGenericTypesForEvent() { EventInfo @event = typeof(HasGenericAttribute).GetEvent(nameof(HasGenericAttribute.Event)); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 0fb360164f4f2..21ee166a5a63b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -247,16 +247,17 @@ public override object[] GetCustomAttributes(bool inherit) return new object[] { new MethodImplAttribute((MethodImplOptions)GetMethodImplementationFlags()) }; } - public override object[] GetCustomAttributes(Type attributeType, - bool inherit) + public override object[] GetCustomAttributes(Type attributeType!!, bool inherit) { - if (attributeType == null) - throw new ArgumentNullException(nameof(attributeType)); - if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute))) - return new object[] { new MethodImplAttribute((MethodImplOptions)GetMethodImplementationFlags()) }; - else - return Array.Empty(); + { + // avoid calling CreateInstance() in the common case where the type is Attribute + object[] result = attributeType == typeof(Attribute) ? new Attribute[1] : (object[])Array.CreateInstance(attributeType, 1); + result[0] = new MethodImplAttribute((MethodImplOptions)GetMethodImplementationFlags()); + return result; + } + + return (object[])Array.CreateInstance(attributeType.IsValueType || attributeType.ContainsGenericParameters ? typeof(object) : attributeType, 0); } public DynamicILInfo GetDynamicILInfo()