Skip to content

Commit

Permalink
Ignore inherit param for ParameterInfo.GetCustomAttributes (#57769)
Browse files Browse the repository at this point in the history
It is documented that the inherit flag is ignored.
Attribute.GetCustomAttributes is to be used to search
inheritance chain.

This change is only for the Mono classlib implementation.
CoreCLR already has this behavior.

Adding a test to verify behavior.
  • Loading branch information
bholmes authored Aug 20, 2021
1 parent 6cc686f commit 1be8fd8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
25 changes: 24 additions & 1 deletion src/libraries/System.Reflection/tests/ParameterInfoTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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() { }
Expand Down Expand Up @@ -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<T>
{
public void GenericMethod(T t) { }
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 1be8fd8

Please sign in to comment.