diff --git a/src/libraries/System.Reflection/tests/ParameterInfoTests.cs b/src/libraries/System.Reflection/tests/ParameterInfoTests.cs index e67e982064e6a..b5acc81f999c0 100644 --- a/src/libraries/System.Reflection/tests/ParameterInfoTests.cs +++ b/src/libraries/System.Reflection/tests/ParameterInfoTests.cs @@ -229,6 +229,22 @@ public void CustomAttributesTest(Type attrType) Assert.True(prov.IsDefined(attrType, true)); } + [Theory] + [InlineData(0, true, 30)] + [InlineData(1, false, -1)] + [InlineData(2, true, 50)] + public void CustomAttributesInheritanceTest(int paramIndex, bool exists, int expectedMyAttributeValue) + { + ParameterInfo parameterInfo = GetParameterInfo(typeof(DerivedParameterInfoMetadata), "VirtualMethodWithCustomAttributes", paramIndex); + CustomAttributeData attribute = parameterInfo.CustomAttributes.SingleOrDefault(a => a.AttributeType.Equals(typeof(MyAttribute))); + Assert.Equal(exists, attribute != null); + + ICustomAttributeProvider prov = parameterInfo as ICustomAttributeProvider; + MyAttribute myAttribute = prov.GetCustomAttributes(typeof(MyAttribute), true).SingleOrDefault() as MyAttribute; + Assert.Equal(exists, myAttribute != null); + Assert.Equal(expectedMyAttributeValue, exists ? myAttribute.Value : expectedMyAttributeValue); + } + [Fact] public void VerifyGetCustomAttributesData() { @@ -345,6 +361,7 @@ public void Foo2([CustomBindingFlags(Value = BindingFlags.IgnoreCase)] BindingFl public void Foo3([CustomBindingFlags(Value = BindingFlags.DeclaredOnly)] BindingFlags bf = BindingFlags.FlattenHierarchy ) { } public void MethodWithCustomAttribute([My(2)]string str, int iValue, long lValue) { } + public virtual void VirtualMethodWithCustomAttributes([My(3)]int val1, [My(4)]int val2, int val3) { } public void Method1(string str, int iValue, long lValue) { } public void Method2() { } @@ -372,6 +389,11 @@ public void MethodWithNullableEnum(AttributeTargets? arg = AttributeTargets.All) public int MethodWithOptionalDefaultOutInMarshalParam([MarshalAs(UnmanagedType.LPWStr)][Out][In] string str = "") { return 1; } } + public class DerivedParameterInfoMetadata : ParameterInfoMetadata + { + override public void VirtualMethodWithCustomAttributes([My(30)]int val1, int val2, [My(50)]int val3) { } + } + public class GenericClass { public void GenericMethod(T t) { } @@ -380,7 +402,8 @@ public void GenericMethod(T t) { } private class MyAttribute : Attribute { - internal MyAttribute(int i) { } + public int Value {get; private set;} + internal MyAttribute(int i) { Value = i;} } internal sealed class CustomBindingFlagsAttribute : UsableCustomConstantAttribute diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index 43cc6a6245429..ded562df410b1 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -181,14 +181,20 @@ int MetadataToken override object[] GetCustomAttributes(bool inherit) { - return CustomAttribute.GetCustomAttributes(this, inherit); + // It is documented that the inherit flag is ignored. + // Attribute.GetCustomAttributes is to be used to search + // inheritance chain. + return CustomAttribute.GetCustomAttributes(this, false); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { - return CustomAttribute.GetCustomAttributes(this, attributeType, inherit); + // It is documented that the inherit flag is ignored. + // Attribute.GetCustomAttributes is to be used to search + // inheritance chain. + return CustomAttribute.GetCustomAttributes(this, attributeType, false); } internal static object? GetDefaultValueImpl(ParameterInfo pinfo)