Skip to content

[mono][reflection] ArgumentNullException calling GetCustomAttributes on user-defined subtype of ParameterInfo #94488

Description

@lambdageek

The following code works with .NET 8.0 CoreCLR, but throws with Mono:

Program.cs:

usingSystem.Reflection;publicclassP{publicstaticvoidMain(){varpropi=typeof(P).GetProperty("Foo");varpi=newRetrofit.PropertyAsParameterInfo(propi!);IEnumerable<Attribute>cattrs=pi.GetCustomAttributes();Console.WriteLine($"Got {cattrs.Count()} attributes");foreach(varcattrincattrs){Console.WriteLine(cattr);}}[Flarg][Blarg]publicintFoo{get;set;}// public static void Foo([Flarg][Blarg]int i) {}}[AttributeUsage(AttributeTargets.Parameter|AttributeTargets.Property)]publicclassFlargAttribute:Attribute{}[AttributeUsage(AttributeTargets.Parameter|AttributeTargets.Property)]publicclassBlargAttribute:Attribute{}

PropertyAsParameterInfo.cs:

usingSystem.Reflection;usingSystem.Diagnostics;usingSystem.Diagnostics.CodeAnalysis;usingSystem.Runtime.CompilerServices;namespaceRetrofit;internalsealedclassPropertyAsParameterInfo:ParameterInfo{privatereadonlyPropertyInfo_underlyingProperty;privatereadonlyParameterInfo?_constructionParameterInfo;publicPropertyAsParameterInfo(PropertyInfopropertyInfo){Debug.Assert(propertyInfo!=null,"PropertyInfo must be provided.");AttrsImpl=(ParameterAttributes)propertyInfo.Attributes;NameImpl=propertyInfo.Name;MemberImpl=propertyInfo;ClassImpl=propertyInfo.PropertyType;// It is not a real parameter in the delegate, so,// not defining a real position.PositionImpl=-1;_underlyingProperty=propertyInfo;}publicoverrideboolHasDefaultValue=>_constructionParameterInfois not null&&_constructionParameterInfo.HasDefaultValue;publicoverrideobject?DefaultValue=>_constructionParameterInfo?.DefaultValue;publicoverrideintMetadataToken=>_underlyingProperty.MetadataToken;publicoverrideobject?RawDefaultValue=>_constructionParameterInfo?.RawDefaultValue;publicoverrideobject[]GetCustomAttributes(TypeattributeType,boolinherit){varconstructorAttributes=_constructionParameterInfo?.GetCustomAttributes(attributeType,inherit);if(constructorAttributes==null||constructorAttributesis{Length:0}){return_underlyingProperty.GetCustomAttributes(attributeType,inherit);}varpropertyAttributes=_underlyingProperty.GetCustomAttributes(attributeType,inherit);varmergedAttributes=newAttribute[constructorAttributes.Length+propertyAttributes.Length];Array.Copy(constructorAttributes,mergedAttributes,constructorAttributes.Length);Array.Copy(propertyAttributes,0,mergedAttributes,constructorAttributes.Length,propertyAttributes.Length);returnmergedAttributes;}publicoverrideobject[]GetCustomAttributes(boolinherit){varconstructorAttributes=_constructionParameterInfo?.GetCustomAttributes(inherit);if(constructorAttributes==null||constructorAttributesis{Length:0}){return_underlyingProperty.GetCustomAttributes(inherit);}varpropertyAttributes=_underlyingProperty.GetCustomAttributes(inherit);// Since the constructors attributes should take priority we will add them first,// as we usually call it as First() or FirstOrDefault() in the argument creationvarmergedAttributes=newobject[constructorAttributes.Length+propertyAttributes.Length];Array.Copy(constructorAttributes,mergedAttributes,constructorAttributes.Length);Array.Copy(propertyAttributes,0,mergedAttributes,constructorAttributes.Length,propertyAttributes.Length);returnmergedAttributes;}publicoverrideIList<CustomAttributeData>GetCustomAttributesData(){varattributes=newList<CustomAttributeData>(_constructionParameterInfo?.GetCustomAttributesData()??Array.Empty<CustomAttributeData>());attributes.AddRange(_underlyingProperty.GetCustomAttributesData());returnattributes.AsReadOnly();}publicoverrideType[]GetOptionalCustomModifiers()=>_underlyingProperty.GetOptionalCustomModifiers();publicoverrideType[]GetRequiredCustomModifiers()=>_underlyingProperty.GetRequiredCustomModifiers();publicoverrideboolIsDefined(TypeattributeType,boolinherit){return(_constructionParameterInfois not null&&_constructionParameterInfo.IsDefined(attributeType,inherit))||_underlyingProperty.IsDefined(attributeType,inherit);}}

repro.csproj:

<ProjectSdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroupCondition="false">
<UseMonoRuntime>true</UseMonoRuntime>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>

Expected output:

$ dotnet runGot 2 attributesFlargAttributeBlargAttribute

Actual output

$ dotnet runUnhandled Exception:System.ArgumentNullException: Value cannot be null. (Parameter 'attributeType') at System.Reflection.CustomAttribute.GetCustomAttributes(ICustomAttributeProvider obj, Type attributeType, Boolean inherit) at System.Reflection.RuntimePropertyInfo.GetCustomAttributes(Type attributeType, Boolean inherit) at Retrofit.PropertyAsParameterInfo.GetCustomAttributes(Type attributeType, Boolean inherit) in /private/tmp/parma/PropertyAsParameterInfo.cs:line 42 at System.Reflection.CustomAttribute.GetCustomAttributesBase(ICustomAttributeProvider obj, Type attributeType, Boolean inheritedOnly) at System.Reflection.CustomAttribute.GetCustomAttributes(ICustomAttributeProvider obj, Type attributeType, Boolean inherit) at System.Reflection.CustomAttribute.GetCustomAttributes(ICustomAttributeProvider obj, Boolean inherit) at System.Attribute.GetCustomAttributes(ParameterInfo element) at System.Reflection.CustomAttributeExtensions.GetCustomAttributes(ParameterInfo element) at P.Main() in /private/tmp/parma/Program.cs:line 9[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentNullException: Value cannot be null. (Parameter 'attributeType') at System.Reflection.CustomAttribute.GetCustomAttributes(ICustomAttributeProvider obj, Type attributeType, Boolean inherit) at System.Reflection.RuntimePropertyInfo.GetCustomAttributes(Type attributeType, Boolean inherit) at Retrofit.PropertyAsParameterInfo.GetCustomAttributes(Type attributeType, Boolean inherit) in /private/tmp/parma/PropertyAsParameterInfo.cs:line 42 at System.Reflection.CustomAttribute.GetCustomAttributesBase(ICustomAttributeProvider obj, Type attributeType, Boolean inheritedOnly) at System.Reflection.CustomAttribute.GetCustomAttributes(ICustomAttributeProvider obj, Type attributeType, Boolean inherit) at System.Reflection.CustomAttribute.GetCustomAttributes(ICustomAttributeProvider obj, Boolean inherit) at System.Attribute.GetCustomAttributes(ParameterInfo element) at System.Reflection.CustomAttributeExtensions.GetCustomAttributes(ParameterInfo element) at P.Main() in /private/tmp/parma/Program.cs:line 9

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions