diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs index dd855b65fdee93..67180ec563730d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs @@ -173,7 +173,7 @@ public override IList GetCustomAttributesData() internal RuntimeType GetRuntimeType() { return m_declaringType; } internal RuntimeModule GetRuntimeModule() { return RuntimeTypeHandle.GetModule(m_declaringType); } internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); } - public override bool IsCollectible => m_declaringType.IsCollectible; + public override bool IsCollectible => ReflectedTypeInternal.IsCollectible; #endregion #region MethodBase Overrides diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs index e09a405a4144c3..cdef2ad754f7a8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs @@ -129,7 +129,7 @@ public override IList GetCustomAttributesData() public override int MetadataToken => m_token; public override Module Module => GetRuntimeModule(); internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); } - public override bool IsCollectible => m_declaringType.IsCollectible; + public override bool IsCollectible => ReflectedTypeInternal.IsCollectible; #endregion #region EventInfo Overrides diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs index a314edaab2a15f..665fbd2076fe54 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs @@ -45,7 +45,7 @@ internal RuntimeType GetDeclaringTypeInternal() public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => HasSameMetadataDefinitionAsCore(other); public override Module Module => GetRuntimeModule(); - public override bool IsCollectible => m_declaringType.IsCollectible; + public override bool IsCollectible => ReflectedTypeInternal.IsCollectible; #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index 3a72a2e1174e4b..8b604ebd0f8797 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -319,7 +319,18 @@ internal void InvokePropertySetter(object? obj, BindingFlags invokeAttr, Binder? public override ParameterInfo ReturnParameter => FetchReturnParameter(); - public override bool IsCollectible => RuntimeMethodHandle.GetIsCollectible(new RuntimeMethodHandleInternal(m_handle)) != Interop.BOOL.FALSE; + public override bool IsCollectible + { + get + { + if (ReflectedTypeInternal.IsCollectible) + return true; + + bool isCollectible = RuntimeMethodHandle.GetIsCollectible(new RuntimeMethodHandleInternal(m_handle)) != Interop.BOOL.FALSE; + GC.KeepAlive(this); // We directly pass the native handle above - make sure this object stays alive for the call + return isCollectible; + } + } public override MethodInfo GetBaseDefinition() { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index 51b1f84864b1a9..7ebc2b7331b466 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -180,7 +180,7 @@ public override IList GetCustomAttributesData() public override Module Module => GetRuntimeModule(); internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); } - public override bool IsCollectible => m_declaringType.IsCollectible; + public override bool IsCollectible => ReflectedTypeInternal.IsCollectible; public override bool Equals(object? obj) => ReferenceEquals(this, obj) || diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/IsCollectibleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/IsCollectibleTests.cs index ae02eef2537ba1..eac1dda524f2a1 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/IsCollectibleTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Reflection/IsCollectibleTests.cs @@ -132,17 +132,10 @@ public void Assembly_IsCollectibleTrue_WhenUsingTestAssemblyLoadContext() }).Dispose(); } - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [InlineData("MyField")] - [InlineData("MyProperty")] - [InlineData("MyMethod")] - [InlineData("MyGenericMethod")] - [InlineData("MyStaticMethod")] - [InlineData("MyStaticField")] - [InlineData("MyStaticGenericMethod")] - public void MemberInfo_IsCollectibleFalse_WhenUsingAssemblyLoad(string memberName) + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void MemberInfo_IsCollectibleFalse_WhenUsingAssemblyLoad() { - RemoteExecutor.Invoke((marshalledName) => + RemoteExecutor.Invoke(() => { Type t1 = Type.GetType( "TestCollectibleAssembly.MyTestClass, TestCollectibleAssembly, Version=1.0.0.0", @@ -153,25 +146,18 @@ public void MemberInfo_IsCollectibleFalse_WhenUsingAssemblyLoad(string memberNam Assert.NotNull(t1); - var member = t1.GetMember(marshalledName).FirstOrDefault(); - - Assert.NotNull(member); + foreach (var member in t1.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + Assert.False(member.IsCollectible, member.ToString()); + } - Assert.False(member.IsCollectible); - }, memberName).Dispose(); + }).Dispose(); } - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [InlineData("MyStaticGenericField")] - [InlineData("MyStaticField")] - [InlineData("MyStaticGenericMethod")] - [InlineData("MyStaticMethod")] - [InlineData("MyGenericField")] - [InlineData("MyGenericProperty")] - [InlineData("MyGenericMethod")] - public void MemberInfoGeneric_IsCollectibleFalse_WhenUsingAssemblyLoad(string memberName) + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void MemberInfoGeneric_IsCollectibleFalse_WhenUsingAssemblyLoad() { - RemoteExecutor.Invoke((marshalledName) => + RemoteExecutor.Invoke(() => { Type t1 = Type.GetType( "TestCollectibleAssembly.MyGenericTestClass`1[System.Int32], TestCollectibleAssembly, Version=1.0.0.0", @@ -182,25 +168,18 @@ public void MemberInfoGeneric_IsCollectibleFalse_WhenUsingAssemblyLoad(string me Assert.NotNull(t1); - var member = t1.GetMember(marshalledName).FirstOrDefault(); - - Assert.NotNull(member); + foreach (var member in t1.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + Assert.False(member.IsCollectible, member.ToString()); + } - Assert.False(member.IsCollectible); - }, memberName).Dispose(); + }).Dispose(); } - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [InlineData("MyField")] - [InlineData("MyProperty")] - [InlineData("MyMethod")] - [InlineData("MyGenericMethod")] - [InlineData("MyStaticMethod")] - [InlineData("MyStaticField")] - [InlineData("MyStaticGenericMethod")] - public void MemberInfo_IsCollectibleTrue_WhenUsingAssemblyLoadContext(string memberName) + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void MemberInfo_IsCollectibleTrue_WhenUsingAssemblyLoadContext() { - RemoteExecutor.Invoke((marshalledName) => + RemoteExecutor.Invoke(() => { AssemblyLoadContext alc = new TestAssemblyLoadContext(); @@ -213,25 +192,18 @@ public void MemberInfo_IsCollectibleTrue_WhenUsingAssemblyLoadContext(string mem Assert.NotNull(t1); - var member = t1.GetMember(marshalledName).FirstOrDefault(); - - Assert.NotNull(member); + foreach (var member in t1.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + Assert.True(member.IsCollectible, member.ToString()); + } - Assert.True(member.IsCollectible); - }, memberName).Dispose(); + }).Dispose(); } - [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - [InlineData("MyStaticGenericField")] - [InlineData("MyStaticField")] - [InlineData("MyStaticGenericMethod")] - [InlineData("MyStaticMethod")] - [InlineData("MyGenericField")] - [InlineData("MyGenericProperty")] - [InlineData("MyGenericMethod")] - public void MemberInfoGeneric_IsCollectibleTrue_WhenUsingAssemblyLoadContext(string memberName) + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void MemberInfoGeneric_IsCollectibleTrue_WhenUsingAssemblyLoadContext() { - RemoteExecutor.Invoke((marshalledName) => + RemoteExecutor.Invoke(() => { AssemblyLoadContext alc = new TestAssemblyLoadContext(); @@ -244,12 +216,12 @@ public void MemberInfoGeneric_IsCollectibleTrue_WhenUsingAssemblyLoadContext(str Assert.NotNull(t1); - var member = t1.GetMember(marshalledName).FirstOrDefault(); + foreach (var member in t1.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + Assert.True(member.IsCollectible, member.ToString()); + } - Assert.NotNull(member); - - Assert.True(member.IsCollectible); - }, memberName).Dispose(); + }).Dispose(); } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] @@ -268,7 +240,16 @@ public void GenericWithCollectibleTypeParameter_IsCollectibleTrue_WhenUsingAssem Assert.NotNull(t1); - Assert.True(t1.IsCollectible); + foreach (var member in t1.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + if (member is Type) + { + continue; + } + + Assert.True(member.IsCollectible, member.ToString()); + } + }).Dispose(); } }