From 0e13c8a1160bcdc3b893bcf144e8426341384381 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 29 Jan 2021 11:04:42 -0600 Subject: [PATCH 01/10] Add API to find MethodInfo on instantiated generic type from generic type definition Fix #45771 --- .../src/System/RuntimeType.CoreCLR.cs | 95 +++++++++++++++++++ .../System.Private.CoreLib/src/System/Type.cs | 9 ++ .../System.Reflection/tests/TypeInfoTests.cs | 50 ++++++++++ .../System.Runtime/ref/System.Runtime.cs | 1 + 4 files changed, 155 insertions(+) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 1e2ece2cde5c8..bc0b4baac52c4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3068,6 +3068,101 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return compressMembers; } + + public override MemberInfo? GetMemberFromGenericMemberDefinition(MemberInfo member) + { + if (member is null) throw new ArgumentNullException(nameof(member)); + + return member.MemberType switch + { + MemberTypes.Method => GetMethodFromGenericMemberDefinition(member), + MemberTypes.Constructor => GetConstructorFromGenericMemberDefinition(member), + MemberTypes.Property => GetPropertyFromGenericMemberDefinition(member), + MemberTypes.Field => GetFieldFromGenericMemberDefinition(member), + MemberTypes.Event => GetEventFromGenericMemberDefinition(member), + _ => null + }; + } + + private MemberInfo? GetMethodFromGenericMemberDefinition(MemberInfo method) + { + RuntimeMethodInfo[] cache = Cache.GetMethodList(MemberListType.CaseSensitive, method.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeMethodInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(method)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetConstructorFromGenericMemberDefinition(MemberInfo constructor) + { + RuntimeConstructorInfo[] cache = Cache.GetConstructorList(MemberListType.CaseSensitive, constructor.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeConstructorInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(constructor)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetPropertyFromGenericMemberDefinition(MemberInfo property) + { + RuntimePropertyInfo[] cache = Cache.GetPropertyList(MemberListType.CaseSensitive, property.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimePropertyInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(property)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetFieldFromGenericMemberDefinition(MemberInfo field) + { + RuntimeFieldInfo[] cache = Cache.GetFieldList(MemberListType.CaseSensitive, field.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeFieldInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(field)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetEventFromGenericMemberDefinition(MemberInfo eventInfo) + { + RuntimeEventInfo[] cache = Cache.GetEventList(MemberListType.CaseSensitive, eventInfo.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeEventInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(eventInfo)) + { + return candidate; + } + } + + return null; + } #endregion #region Identity diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index ca57ed53988aa..6bc612bf5d414 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -226,6 +226,15 @@ public ConstructorInfo? TypeInitializer DynamicallyAccessedMemberTypes.PublicNestedTypes)] public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup); + /// + /// Searches for the constructed generic member that matches the specified generic member definition. + /// + /// + /// The representing the generic definition of the member. + /// + /// An object representing the member on the current constructed generic type that matches the specified generic definition, if found; otherwise, null. + public virtual MemberInfo? GetMemberFromGenericMemberDefinition(MemberInfo member) => throw new NotSupportedException(SR.NotSupported_SubclassOverride); + [DynamicallyAccessedMembers(GetAllMembers)] public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr); diff --git a/src/libraries/System.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs index 4e3603c2f3aa9..a86250d5c36eb 100644 --- a/src/libraries/System.Reflection/tests/TypeInfoTests.cs +++ b/src/libraries/System.Reflection/tests/TypeInfoTests.cs @@ -1565,6 +1565,23 @@ public void IsSZArray(Type type, bool expected) Assert.Equal(expected, type.GetTypeInfo().IsSZArray); } + [Fact] + public void GetMemberFromGenericMemberDefinition() + { + //System.Diagnostics.Debugger.Launch(); + Type openGenericType = typeof(TI_GenericTypeWithAllMembers<>); + Type closedGenericType = typeof(TI_GenericTypeWithAllMembers); + + BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; + foreach (MemberInfo openGenericMember in openGenericType.GetMembers(all)) + { + MemberInfo closedGenericMember = closedGenericType.GetMemberFromGenericMemberDefinition(openGenericMember); + Assert.True(closedGenericMember != null, openGenericMember.Name + " is null"); + Assert.NotNull(closedGenericMember); + Assert.True(closedGenericMember.HasSameMetadataDefinitionAs(openGenericMember)); + } + } + #pragma warning disable 0067, 0169 public static class ClassWithStaticConstructor { @@ -1815,6 +1832,39 @@ public abstract class AbstractBaseClass { } public abstract class AbstractSubClass : AbstractBaseClass { } public class AbstractSubSubClass : AbstractSubClass { } } + + public class TI_GenericTypeWithAllMembers + { + private static event EventHandler PrivateStaticEvent; + private static T PrivateStaticField; + private static T PrivateStaticProperty { get; set; } + private static T PrivateStaticMethod(T t) => default; + private static T PrivateStaticMethod(T t, T t2) => default; + + public static event EventHandler PublicStaticEvent; + public static T PublicStaticField; + public static T PublicStaticProperty { get; set; } + public static T PublicStaticMethod(T t) => default; + public static T PublicStaticMethod(T t, T t2) => default; + + static TI_GenericTypeWithAllMembers() { } + + public TI_GenericTypeWithAllMembers(T t) { } + private TI_GenericTypeWithAllMembers() { } + + public event EventHandler PublicInstanceEvent; + public T PublicInstanceField; + public T PublicInstanceProperty { get; set; } + public T PublicInstanceMethod(T t) => default; + public T PublicInstanceMethod(T t, T t2) => default; + + private event EventHandler PrivateInstanceEvent; + private T PrivateInstanceField; + private T PrivateInstanceProperty { get; set; } + private T PrivateInstanceMethod(T t) => default; + private T PrivateInstanceMethod(T t1, T t2) => default; + } + #pragma warning restore 0067, 0169 public class OutsideTypeInfoTests diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index ba30ccf66a0aa..651fe8a033983 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4470,6 +4470,7 @@ protected Type() { } public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.BindingFlags bindingAttr) { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; } + public virtual System.Reflection.MemberInfo? GetMemberFromGenericMemberDefinition(System.Reflection.MemberInfo member) { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] public System.Reflection.MemberInfo[] GetMembers() { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] From 5cce6528850ee19eb1f28d2f49d0cb41b01a3430 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 3 Jun 2021 15:19:44 -0500 Subject: [PATCH 02/10] * Rename to GetMemberWithSameMetadataDefinitionAs * Fix a bug for NestedType * Use new method libraries that were working around not having it --- .../src/System/RuntimeType.CoreCLR.cs | 39 ++++++++--- .../ComponentModel/NullableConverter.cs | 12 +--- .../src/System/Dynamic/Utils/TypeUtils.cs | 10 ++- .../System/Linq/Expressions/Compiler/ILGen.cs | 25 +++---- .../Compiler/LambdaCompiler.Binary.cs | 2 +- .../Compiler/LambdaCompiler.Expressions.cs | 12 ++-- .../Compiler/LambdaCompiler.Unary.cs | 4 +- .../Linq/Expressions/LambdaExpression.cs | 17 +---- .../System.Private.CoreLib/src/System/Type.cs | 2 +- .../InteropServices/JavaScript/Runtime.cs | 69 ++++++++----------- .../System.Reflection/tests/TypeInfoTests.cs | 14 ++-- .../Runtime/Serialization/ObjectManager.cs | 7 +- .../System.Runtime/ref/System.Runtime.cs | 2 +- 13 files changed, 100 insertions(+), 115 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index bc0b4baac52c4..cb7672608c8d8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3069,22 +3069,23 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return compressMembers; } - public override MemberInfo? GetMemberFromGenericMemberDefinition(MemberInfo member) + public override MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member) { if (member is null) throw new ArgumentNullException(nameof(member)); return member.MemberType switch { - MemberTypes.Method => GetMethodFromGenericMemberDefinition(member), - MemberTypes.Constructor => GetConstructorFromGenericMemberDefinition(member), - MemberTypes.Property => GetPropertyFromGenericMemberDefinition(member), - MemberTypes.Field => GetFieldFromGenericMemberDefinition(member), - MemberTypes.Event => GetEventFromGenericMemberDefinition(member), + MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(member), + MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(member), + MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(member), + MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(member), + MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(member), + MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(member), _ => null }; } - private MemberInfo? GetMethodFromGenericMemberDefinition(MemberInfo method) + private MemberInfo? GetMethodWithSameMetadataDefinitionAs(MemberInfo method) { RuntimeMethodInfo[] cache = Cache.GetMethodList(MemberListType.CaseSensitive, method.Name); @@ -3100,7 +3101,7 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return null; } - private MemberInfo? GetConstructorFromGenericMemberDefinition(MemberInfo constructor) + private MemberInfo? GetConstructorWithSameMetadataDefinitionAs(MemberInfo constructor) { RuntimeConstructorInfo[] cache = Cache.GetConstructorList(MemberListType.CaseSensitive, constructor.Name); @@ -3116,7 +3117,7 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return null; } - private MemberInfo? GetPropertyFromGenericMemberDefinition(MemberInfo property) + private MemberInfo? GetPropertyWithSameMetadataDefinitionAs(MemberInfo property) { RuntimePropertyInfo[] cache = Cache.GetPropertyList(MemberListType.CaseSensitive, property.Name); @@ -3132,7 +3133,7 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return null; } - private MemberInfo? GetFieldFromGenericMemberDefinition(MemberInfo field) + private MemberInfo? GetFieldWithSameMetadataDefinitionAs(MemberInfo field) { RuntimeFieldInfo[] cache = Cache.GetFieldList(MemberListType.CaseSensitive, field.Name); @@ -3148,7 +3149,7 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return null; } - private MemberInfo? GetEventFromGenericMemberDefinition(MemberInfo eventInfo) + private MemberInfo? GetEventWithSameMetadataDefinitionAs(MemberInfo eventInfo) { RuntimeEventInfo[] cache = Cache.GetEventList(MemberListType.CaseSensitive, eventInfo.Name); @@ -3163,6 +3164,22 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return null; } + + private MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(MemberInfo nestedType) + { + RuntimeType[] cache = Cache.GetNestedTypeList(MemberListType.CaseSensitive, nestedType.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeType candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(nestedType)) + { + return candidate; + } + } + + return null; + } #endregion #region Identity diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs index 9bcfdc0b03300..feedc533675db 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs @@ -15,6 +15,8 @@ namespace System.ComponentModel /// public class NullableConverter : TypeConverter { + private static readonly ConstructorInfo s_nullableConstructor = typeof(Nullable<>).GetConstructor(typeof(Nullable<>).GetGenericArguments())!; + /// /// Nullable converter is initialized with the underlying simple type. /// @@ -108,7 +110,7 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul } else if (destinationType == typeof(InstanceDescriptor)) { - ConstructorInfo ci = GetNullableConstructor(); + ConstructorInfo ci = (ConstructorInfo)NullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableConstructor)!; Debug.Assert(ci != null, "Couldn't find constructor"); return new InstanceDescriptor(ci, new object[] { value }, true); } @@ -128,14 +130,6 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul return base.ConvertTo(context, culture, value, destinationType); } - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", - Justification = "The Nullable ctor will be preserved by the DynamicDependency.")] - private ConstructorInfo GetNullableConstructor() - { - return NullableType.GetConstructor(new Type[] { UnderlyingType })!; - } - /// /// public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs index afa81a14932b8..bfdee83fa64f0 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs @@ -16,6 +16,8 @@ internal static class TypeUtils .Select(i => i.GetGenericTypeDefinition()) .ToArray(); + private static readonly ConstructorInfo s_nullableConstructor = typeof(Nullable<>).GetConstructor(typeof(Nullable<>).GetGenericArguments())!; + public static Type GetNonNullableType(this Type type) => IsNullableType(type) ? type.GetGenericArguments()[0] : type; public static Type GetNullableType(this Type type) @@ -29,15 +31,11 @@ public static Type GetNullableType(this Type type) return type; } - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The Nullable ctor will be preserved by the DynamicDependency.")] - public static ConstructorInfo GetNullableConstructor(Type nullableType, Type nonNullableType) + public static ConstructorInfo GetNullableConstructor(Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - Debug.Assert(!nonNullableType.IsNullableType() && nonNullableType.IsValueType); - return nullableType.GetConstructor(new Type[] { nonNullableType })!; + return (ConstructorInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableConstructor)!; } public static bool IsNullableType(this Type type) => type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs index 673e213432a72..53898899c94ef 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs @@ -12,6 +12,10 @@ namespace System.Linq.Expressions.Compiler { internal static class ILGen { + private static readonly MethodInfo s_nullableHasValueGetter = typeof(Nullable<>).GetMethod("get_HasValue", BindingFlags.Instance | BindingFlags.Public)!; + private static readonly MethodInfo s_nullableValueGetter = typeof(Nullable<>).GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public)!; + private static readonly MethodInfo s_nullableGetValueOrDefault = typeof(Nullable<>).GetMethod("GetValueOrDefault", Type.EmptyTypes)!; + internal static void Emit(this ILGenerator il, OpCode opcode, MethodBase methodBase) { Debug.Assert(methodBase is MethodInfo || methodBase is ConstructorInfo); @@ -485,7 +489,7 @@ private static bool TryEmitILConstant(this ILGenerator il, object value, Type ty if (TryEmitILConstant(il, value, nonNullType)) { - il.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type, nonNullType)); + il.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type)); return true; } @@ -826,7 +830,7 @@ private static void EmitNullableToNullableConversion(this ILGenerator il, Type t Type nnTypeTo = typeTo.GetNonNullableType(); il.EmitConvertToType(nnTypeFrom, nnTypeTo, isChecked, locals); // construct result type - ConstructorInfo ci = TypeUtils.GetNullableConstructor(typeTo, nnTypeTo); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(typeTo); il.Emit(OpCodes.Newobj, ci); labEnd = il.DefineLabel(); il.Emit(OpCodes.Br_S, labEnd); @@ -846,7 +850,7 @@ private static void EmitNonNullableToNullableConversion(this ILGenerator il, Typ Debug.Assert(typeTo.IsNullableType()); Type nnTypeTo = typeTo.GetNonNullableType(); il.EmitConvertToType(typeFrom, nnTypeTo, isChecked, locals); - ConstructorInfo ci = TypeUtils.GetNullableConstructor(typeTo, nnTypeTo); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(typeTo); il.Emit(OpCodes.Newobj, ci); } @@ -898,38 +902,29 @@ private static void EmitNullableConversion(this ILGenerator il, Type typeFrom, T il.EmitNonNullableToNullableConversion(typeFrom, typeTo, isChecked, locals); } - [DynamicDependency("get_HasValue", typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The Nullable method will be preserved by the DynamicDependency.")] internal static void EmitHasValue(this ILGenerator il, Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - MethodInfo mi = nullableType.GetMethod("get_HasValue", BindingFlags.Instance | BindingFlags.Public)!; + MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableHasValueGetter)!; Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); } - [DynamicDependency("get_Value", typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The Nullable method will be preserved by the DynamicDependency.")] internal static void EmitGetValue(this ILGenerator il, Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - MethodInfo mi = nullableType.GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public)!; + MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableValueGetter)!; Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); } - [DynamicDependency("GetValueOrDefault()", typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The Nullable method will be preserved by the DynamicDependency.")] internal static void EmitGetValueOrDefault(this ILGenerator il, Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - MethodInfo mi = nullableType.GetMethod("GetValueOrDefault", Type.EmptyTypes)!; + MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableGetValueOrDefault)!; Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs index a888be0831e21..c4e448a2dce29 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs @@ -480,7 +480,7 @@ private void EmitLiftedBinaryArithmetic(ExpressionType op, Type leftType, Type r EmitBinaryOperator(op, leftType.GetNonNullableType(), rightType.GetNonNullableType(), resultNonNullableType, liftedToNull: false); // construct result type - ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, resultNonNullableType); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType); _ilg.Emit(OpCodes.Newobj, ci); _ilg.Emit(OpCodes.Stloc, locResult); _ilg.Emit(OpCodes.Br_S, labEnd); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs index a3049f80d4927..55c300172537c 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Dynamic.Utils; using System.Reflection; using System.Reflection.Emit; @@ -14,6 +13,8 @@ namespace System.Linq.Expressions.Compiler { internal sealed partial class LambdaCompiler { + private static readonly FieldInfo s_callSiteTargetField = typeof(CallSite<>).GetField("Target")!; + [Flags] internal enum CompilationFlags { @@ -613,13 +614,10 @@ private void EmitDynamicExpression(Expression expr) EmitWriteBack(wb); } - [DynamicDependency("Target", typeof(CallSite<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The 'Target' field will be preserved by the DynamicDependency.")] private static FieldInfo GetCallSiteTargetField(Type siteType) { Debug.Assert(siteType.IsGenericType && siteType.GetGenericTypeDefinition() == typeof(CallSite<>)); - return siteType.GetField("Target")!; + return (FieldInfo)siteType.GetMemberWithSameMetadataDefinitionAs(s_callSiteTargetField)!; } private void EmitNewExpression(Expression expr) @@ -1171,7 +1169,7 @@ private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpres EmitMethodCallExpression(mc); if (resultType.IsNullableType() && !TypeUtils.AreEquivalent(resultType, mc.Type)) { - ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, mc.Type); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType); _ilg.Emit(OpCodes.Newobj, ci); } _ilg.Emit(OpCodes.Br_S, exit); @@ -1275,7 +1273,7 @@ private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpres EmitMethodCallExpression(mc); if (resultType.IsNullableType() && !TypeUtils.AreEquivalent(resultType, mc.Type)) { - ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, mc.Type); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType); _ilg.Emit(OpCodes.Newobj, ci); } _ilg.Emit(OpCodes.Br_S, exit); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs index f487d73d7c3f2..b17d414466441 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs @@ -94,7 +94,7 @@ private void EmitUnary(UnaryExpression node, CompilationFlags flags) EmitBinaryOperator(ExpressionType.SubtractChecked, nnType, nnType, nnType, liftedToNull: false); // construct result - _ilg.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type, nnType)); + _ilg.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type)); _ilg.Emit(OpCodes.Br_S, end); // if null then push back on stack @@ -164,7 +164,7 @@ private void EmitUnaryOperator(ExpressionType op, Type operandType, Type resultT EmitUnaryOperator(op, nnOperandType, nnOperandType); // construct result - ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, nnOperandType); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType); _ilg.Emit(OpCodes.Newobj, ci); _ilg.Emit(OpCodes.Br_S, labEnd); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs index fc45b9c5ff81f..aaba66b0952cd 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs @@ -21,6 +21,8 @@ namespace System.Linq.Expressions [DebuggerTypeProxy(typeof(LambdaExpressionProxy))] public abstract class LambdaExpression : Expression, IParameterProvider { + private static readonly MethodInfo s_expressionCompileMethodInfo = typeof(Expression<>).GetMethod("Compile", Type.EmptyTypes)!; + private readonly Expression _body; internal LambdaExpression(Expression body) @@ -119,20 +121,7 @@ internal static MethodInfo GetCompileMethod(Type lambdaExpressionType) return typeof(LambdaExpression).GetMethod("Compile", Type.EmptyTypes)!; } - return GetDerivedCompileMethod(lambdaExpressionType); - } - - [DynamicDependency("Compile()", typeof(Expression<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The 'Compile' method will be preserved by the DynamicDependency.")] - private static MethodInfo GetDerivedCompileMethod(Type lambdaExpressionType) - { - Debug.Assert(lambdaExpressionType.IsAssignableTo(typeof(LambdaExpression)) && lambdaExpressionType != typeof(LambdaExpression)); - - MethodInfo result = lambdaExpressionType.GetMethod("Compile", Type.EmptyTypes)!; - Debug.Assert(result.DeclaringType!.IsGenericType && result.DeclaringType.GetGenericTypeDefinition() == typeof(Expression<>)); - - return result; + return (MethodInfo)lambdaExpressionType.GetMemberWithSameMetadataDefinitionAs(s_expressionCompileMethodInfo)!; } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 6bc612bf5d414..4195ed517934b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -233,7 +233,7 @@ public ConstructorInfo? TypeInitializer /// The representing the generic definition of the member. /// /// An object representing the member on the current constructed generic type that matches the specified generic definition, if found; otherwise, null. - public virtual MemberInfo? GetMemberFromGenericMemberDefinition(MemberInfo member) => throw new NotSupportedException(SR.NotSupported_SubclassOverride); + public virtual MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member) => throw new NotSupportedException(SR.NotSupported_SubclassOverride); [DynamicallyAccessedMembers(GetAllMembers)] public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr); diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs index 09e30d4bb4622..71baa7066dd67 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs @@ -12,16 +12,15 @@ namespace System.Runtime.InteropServices.JavaScript { public static class Runtime { - private static readonly Dictionary> _boundObjects = new Dictionary>(); - private static readonly Dictionary _rawToJS = new Dictionary(); + private static readonly Dictionary> s_boundObjects = new Dictionary>(); + private static readonly Dictionary s_rawToJS = new Dictionary(); // _weakDelegateTable is a ConditionalWeakTable with the Delegate and associated JSObject: // Key Lifetime: // Once the key dies, the dictionary automatically removes the key/value entry. // No need to lock as it is thread safe. - private static readonly ConditionalWeakTable _weakDelegateTable = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable s_weakDelegateTable = new ConditionalWeakTable(); - private const string TaskGetResultName = "get_Result"; - private static readonly MethodInfo _taskGetResultMethodInfo = typeof(Task<>).GetMethod(TaskGetResultName)!; + private static readonly MethodInfo s_taskGetResultMethodInfo = typeof(Task<>).GetMethod("get_Result")!; // // Execute the provided string in the JavaScript context @@ -56,9 +55,9 @@ public static void FreeObject(object obj) } JSObject? jsobj; - lock (_rawToJS) + lock (s_rawToJS) { - if (!_rawToJS.Remove(obj, out jsobj)) + if (!s_rawToJS.Remove(obj, out jsobj)) { throw new JSException(SR.Format(SR.ErrorReleasingObject, obj)); } @@ -79,15 +78,15 @@ public static int BindJSObject(int jsId, bool ownsHandle, int mappedType) { JSObject? target = null; - lock (_boundObjects) + lock (s_boundObjects) { - if (!_boundObjects.TryGetValue(jsId, out WeakReference? reference) || + if (!s_boundObjects.TryGetValue(jsId, out WeakReference? reference) || !reference.TryGetTarget(out target) || target.IsDisposed) { IntPtr jsIntPtr = (IntPtr)jsId; target = mappedType > 0 ? BindJSType(jsIntPtr, ownsHandle, mappedType) : new JSObject(jsIntPtr, ownsHandle); - _boundObjects[jsId] = new WeakReference(target, trackResurrection: true); + s_boundObjects[jsId] = new WeakReference(target, trackResurrection: true); } } @@ -99,9 +98,9 @@ public static int BindCoreCLRObject(int jsId, int gcHandle) GCHandle h = (GCHandle)(IntPtr)gcHandle; JSObject? obj = null; - lock (_boundObjects) + lock (s_boundObjects) { - if (_boundObjects.TryGetValue(jsId, out WeakReference? wr)) + if (s_boundObjects.TryGetValue(jsId, out WeakReference? wr)) { if (!wr.TryGetTarget(out JSObject? instance) || (instance.Int32Handle != (int)(IntPtr)h && h.IsAllocated)) { @@ -112,7 +111,7 @@ public static int BindCoreCLRObject(int jsId, int gcHandle) } else if (h.Target is JSObject instance) { - _boundObjects.Add(jsId, new WeakReference(instance, trackResurrection: true)); + s_boundObjects.Add(jsId, new WeakReference(instance, trackResurrection: true)); obj = instance; } } @@ -147,9 +146,9 @@ internal static bool ReleaseJSObject(JSObject objToRelease) if (exception != 0) throw new JSException($"Error releasing handle on (js-obj js '{objToRelease.JSHandle}' mono '{objToRelease.Int32Handle} raw '{objToRelease.RawObject != null}' weak raw '{objToRelease.IsWeakWrapper}' )"); - lock (_boundObjects) + lock (s_boundObjects) { - _boundObjects.Remove(objToRelease.JSHandle); + s_boundObjects.Remove(objToRelease.JSHandle); } return true; } @@ -158,11 +157,11 @@ public static void UnBindRawJSObjectAndFree(int gcHandle) { GCHandle h = (GCHandle)(IntPtr)gcHandle; JSObject? obj = h.Target as JSObject; - lock (_rawToJS) + lock (s_rawToJS) { if (obj?.RawObject != null) { - _rawToJS.Remove(obj.RawObject); + s_rawToJS.Remove(obj.RawObject); obj.FreeHandle(); } } @@ -194,22 +193,22 @@ public static int BindExistingObject(object rawObj, int jsId) if (rawObj is Delegate dele) { jsObject = new JSObject(jsId, dele); - lock (_boundObjects) + lock (s_boundObjects) { - _boundObjects.Add(jsId, new WeakReference(jsObject)); + s_boundObjects.Add(jsId, new WeakReference(jsObject)); } - lock (_weakDelegateTable) + lock (s_weakDelegateTable) { - _weakDelegateTable.Add(dele, jsObject); + s_weakDelegateTable.Add(dele, jsObject); } } else { - lock (_rawToJS) + lock (s_rawToJS) { - if (!_rawToJS.TryGetValue(rawObj, out jsObject)) + if (!s_rawToJS.TryGetValue(rawObj, out jsObject)) { - _rawToJS.Add(rawObj, jsObject = new JSObject(jsId, rawObj)); + s_rawToJS.Add(rawObj, jsObject = new JSObject(jsId, rawObj)); } } } @@ -221,16 +220,16 @@ public static int GetJSObjectId(object rawObj) JSObject? jsObject; if (rawObj is Delegate dele) { - lock (_weakDelegateTable) + lock (s_weakDelegateTable) { - _weakDelegateTable.TryGetValue(dele, out jsObject); + s_weakDelegateTable.TryGetValue(dele, out jsObject); } } else { - lock (_rawToJS) + lock (s_rawToJS) { - _rawToJS.TryGetValue(rawObj, out jsObject); + s_rawToJS.TryGetValue(rawObj, out jsObject); } } return jsObject?.JSHandle ?? -1; @@ -389,17 +388,9 @@ void Complete() /// The reason for this restriction is to make this use of Reflection trim-compatible, /// ensuring that trimming doesn't change the application's behavior. /// - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Task.Result is preserved by the ILLinker because _taskGetResultMethodInfo was initialized with it.")] private static MethodInfo? GetTaskResultMethodInfo(Type taskType) { - MethodInfo? result = taskType.GetMethod(TaskGetResultName); - if (result != null && result.HasSameMetadataDefinitionAs(_taskGetResultMethodInfo)) - { - return result; - } - - return null; + return (MethodInfo?)taskType.GetMemberWithSameMetadataDefinitionAs(s_taskGetResultMethodInfo); } public static string ObjectToString(object o) @@ -481,9 +472,9 @@ public static void SafeHandleReleaseByHandle(int jsId) #if DEBUG_HANDLE Debug.WriteLine($"SafeHandleReleaseByHandle: {jsId}"); #endif - lock (_boundObjects) + lock (s_boundObjects) { - if (_boundObjects.TryGetValue(jsId, out WeakReference? reference)) + if (s_boundObjects.TryGetValue(jsId, out WeakReference? reference)) { reference.TryGetTarget(out JSObject? target); Debug.Assert(target != null, $"\tSafeHandleReleaseByHandle: did not find active target {jsId}"); diff --git a/src/libraries/System.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs index a86250d5c36eb..8fb387da81a97 100644 --- a/src/libraries/System.Reflection/tests/TypeInfoTests.cs +++ b/src/libraries/System.Reflection/tests/TypeInfoTests.cs @@ -1566,19 +1566,18 @@ public void IsSZArray(Type type, bool expected) } [Fact] - public void GetMemberFromGenericMemberDefinition() + public void GetMemberWithSameMetadataDefinitionAs() { - //System.Diagnostics.Debugger.Launch(); Type openGenericType = typeof(TI_GenericTypeWithAllMembers<>); Type closedGenericType = typeof(TI_GenericTypeWithAllMembers); BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; foreach (MemberInfo openGenericMember in openGenericType.GetMembers(all)) { - MemberInfo closedGenericMember = closedGenericType.GetMemberFromGenericMemberDefinition(openGenericMember); - Assert.True(closedGenericMember != null, openGenericMember.Name + " is null"); - Assert.NotNull(closedGenericMember); + MemberInfo closedGenericMember = closedGenericType.GetMemberWithSameMetadataDefinitionAs(openGenericMember); + Assert.True(closedGenericMember != null, $"'{openGenericMember.Name}' was not found"); Assert.True(closedGenericMember.HasSameMetadataDefinitionAs(openGenericMember)); + Assert.Equal(closedGenericMember.Name, openGenericMember.Name); } } @@ -1863,6 +1862,11 @@ private TI_GenericTypeWithAllMembers() { } private T PrivateInstanceProperty { get; set; } private T PrivateInstanceMethod(T t) => default; private T PrivateInstanceMethod(T t1, T t2) => default; + + public class Nested + { + public T NestedField; + } } #pragma warning restore 0067, 0169 diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs index d9eba9228f1fb..79b1d7977be60 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs @@ -16,6 +16,8 @@ public class ObjectManager private const string ObjectManagerUnreferencedCodeMessage = "ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered."; + private static readonly FieldInfo s_nullableValueField = typeof(Nullable<>).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance)!; + private DeserializationEventHandler? _onDeserializationHandler; private SerializationEventHandler? _onDeserializedHandler; @@ -383,14 +385,11 @@ private bool DoValueTypeFixup(FieldInfo? memberToFix, ObjectHolder holder, objec return true; } - [DynamicDependency("value", typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The Nullable.value field will be preserved by the DynamicDependency.")] private static FieldInfo? GetNullableValueField(Type type) { if (Nullable.GetUnderlyingType(type) != null) { - return type.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance)!; + return (FieldInfo)type.GetMemberWithSameMetadataDefinitionAs(s_nullableValueField)!; } return null; diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 651fe8a033983..bee68d1d65aa9 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4470,7 +4470,7 @@ protected Type() { } public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.BindingFlags bindingAttr) { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; } - public virtual System.Reflection.MemberInfo? GetMemberFromGenericMemberDefinition(System.Reflection.MemberInfo member) { throw null; } + public virtual System.Reflection.MemberInfo? GetMemberWithSameMetadataDefinitionAs(System.Reflection.MemberInfo member) { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] public System.Reflection.MemberInfo[] GetMembers() { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] From 7a15f9750f654d362b452e0ba5251e9756c16860 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 3 Jun 2021 18:43:31 -0500 Subject: [PATCH 03/10] Implement GetMemberWithSameMetadataDefinitionAs in mono --- .../System.Reflection/tests/TypeInfoTests.cs | 4 + .../src/System/Reflection/RuntimeEventInfo.cs | 8 -- .../src/System/Reflection/RuntimeFieldInfo.cs | 8 -- .../System/Reflection/RuntimeMethodInfo.cs | 16 --- .../System/Reflection/RuntimePropertyInfo.cs | 8 -- .../src/System/RuntimeType.Mono.cs | 125 ++++++++++++++++-- 6 files changed, 119 insertions(+), 50 deletions(-) diff --git a/src/libraries/System.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs index 8fb387da81a97..3d5940959ac11 100644 --- a/src/libraries/System.Reflection/tests/TypeInfoTests.cs +++ b/src/libraries/System.Reflection/tests/TypeInfoTests.cs @@ -1578,6 +1578,10 @@ public void GetMemberWithSameMetadataDefinitionAs() Assert.True(closedGenericMember != null, $"'{openGenericMember.Name}' was not found"); Assert.True(closedGenericMember.HasSameMetadataDefinitionAs(openGenericMember)); Assert.Equal(closedGenericMember.Name, openGenericMember.Name); + if (openGenericMember is not Type) + { + Assert.True(closedGenericMember.DeclaringType == closedGenericType, $"'{closedGenericMember.Name}' doesn't have the right DeclaringType"); + } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs index 2c7fbda9e8ddf..e92011c9d2f81 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs @@ -82,14 +82,6 @@ internal RuntimeType GetDeclaringTypeInternal() return (RuntimeType)DeclaringType; } - private RuntimeType ReflectedTypeInternal - { - get - { - return (RuntimeType)ReflectedType; - } - } - internal RuntimeModule GetRuntimeModule() { return GetDeclaringTypeInternal().GetRuntimeModule(); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs index b4a9c2f13a065..15649ac800aff 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs @@ -63,14 +63,6 @@ internal RuntimeType GetDeclaringTypeInternal() return (RuntimeType)DeclaringType!; } - private RuntimeType ReflectedTypeInternal - { - get - { - return (RuntimeType)ReflectedType; - } - } - internal RuntimeModule GetRuntimeModule() { return GetDeclaringTypeInternal().GetRuntimeModule(); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index aba9b94c8b83f..362b99998df2c 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -157,14 +157,6 @@ public override Module Module } } - private RuntimeType? ReflectedTypeInternal - { - get - { - return (RuntimeType?)ReflectedType; - } - } - private string FormatNameAndSig() { // Serialization uses ToString to resolve MethodInfo overloads. @@ -788,14 +780,6 @@ internal RuntimeModule GetRuntimeModule() return RuntimeTypeHandle.GetModule((RuntimeType)DeclaringType); } - private RuntimeType? ReflectedTypeInternal - { - get - { - return (RuntimeType?)ReflectedType; - } - } - public override MethodImplAttributes GetMethodImplementationFlags() { return MonoMethodInfo.GetMethodImplementationFlags(mhandle); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index 9e05a18daaf0f..20defaa52c48c 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -131,14 +131,6 @@ internal RuntimeType GetDeclaringTypeInternal() return (RuntimeType)DeclaringType; } - private RuntimeType ReflectedTypeInternal - { - get - { - return (RuntimeType)ReflectedType; - } - } - internal RuntimeModule GetRuntimeModule() { return GetDeclaringTypeInternal().GetRuntimeModule(); diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 7b9c50c6c25a9..3a166c22c5f9c 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Runtime.Serialization; using System.Runtime.CompilerServices; -using System.Diagnostics.Contracts; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Diagnostics; @@ -38,14 +37,6 @@ internal enum TypeNameFormatFlags FormatFullInst } - internal enum TypeNameKind - { - Name, - ToString, - SerializationName, - FullName, - } - internal partial class RuntimeType { #region Definitions @@ -1127,8 +1118,122 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return compressMembers; } - #endregion + public override MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member) + { + if (member is null) throw new ArgumentNullException(nameof(member)); + + return member.MemberType switch + { + MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(member), + MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(member), + MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(member), + MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(member), + MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(member), + MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(member), + _ => null + }; + } + + private const BindingFlags GetMemberWithSameMetadataDefinitionAsBindingFlags = + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + + private MemberInfo? GetMethodWithSameMetadataDefinitionAs(MemberInfo methodInfo) + { + ListBuilder methods = GetMethodCandidates(methodInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, CallingConventions.Any, null, -1, allowPrefixLookup: false); + + for (int i = 0; i < methods.Count; i++) + { + MethodInfo candidate = methods[i]; + if (candidate.HasSameMetadataDefinitionAs(methodInfo)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetConstructorWithSameMetadataDefinitionAs(MemberInfo constructorInfo) + { + ListBuilder ctors = GetConstructorCandidates(null, GetMemberWithSameMetadataDefinitionAsBindingFlags, CallingConventions.Any, null, allowPrefixLookup: false); + + for (int i = 0; i < ctors.Count; i++) + { + ConstructorInfo candidate = ctors[i]; + if (candidate.HasSameMetadataDefinitionAs(constructorInfo)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetPropertyWithSameMetadataDefinitionAs(MemberInfo propertyInfo) + { + ListBuilder properties = GetPropertyCandidates(propertyInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, null, allowPrefixLookup: false); + + for (int i = 0; i < properties.Count; i++) + { + PropertyInfo candidate = properties[i]; + if (candidate.HasSameMetadataDefinitionAs(propertyInfo)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetFieldWithSameMetadataDefinitionAs(MemberInfo fieldInfo) + { + ListBuilder fields = GetFieldCandidates(fieldInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); + + for (int i = 0; i < fields.Count; i++) + { + FieldInfo candidate = fields[i]; + if (candidate.HasSameMetadataDefinitionAs(fieldInfo)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetEventWithSameMetadataDefinitionAs(MemberInfo eventInfo) + { + ListBuilder events = GetEventCandidates(null, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); + + for (int i = 0; i < events.Count; i++) + { + EventInfo candidate = events[i]; + if (candidate.HasSameMetadataDefinitionAs(eventInfo)) + { + return candidate; + } + } + + return null; + } + + private MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(MemberInfo nestedType) + { + ListBuilder nestedTypes = GetNestedTypeCandidates(nestedType.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); + + for (int i = 0; i < nestedTypes.Count; i++) + { + Type candidate = nestedTypes[i]; + if (candidate.HasSameMetadataDefinitionAs(nestedType)) + { + return candidate; + } + } + + return null; + } + #endregion #region Hierarchy From 0936408818d3714d218bcdc072f9f61e95d14cca Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 4 Jun 2021 18:13:27 -0500 Subject: [PATCH 04/10] Respond to PR feedback --- .../src/System/RuntimeType.CoreCLR.cs | 6 +- .../ComponentModel/NullableConverter.cs | 2 +- .../src/System/Dynamic/Utils/TypeUtils.cs | 2 +- .../System/Linq/Expressions/Compiler/ILGen.cs | 6 +- .../Compiler/LambdaCompiler.Expressions.cs | 2 +- .../Linq/Expressions/LambdaExpression.cs | 2 +- .../src/Resources/Strings.resx | 57 ++++++++++--------- .../src/System/Reflection/TypeDelegator.cs | 2 + .../System.Private.CoreLib/src/System/Type.cs | 28 +++++++-- .../InteropServices/JavaScript/Runtime.cs | 7 ++- .../System.Reflection/tests/TypeInfoTests.cs | 46 +++++++++++++-- .../Runtime/Serialization/ObjectManager.cs | 2 +- .../System.Runtime/ref/System.Runtime.cs | 2 +- .../src/System/RuntimeType.Mono.cs | 6 +- 14 files changed, 120 insertions(+), 50 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index cb7672608c8d8..4fc1d20f396ab 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3069,11 +3069,11 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return compressMembers; } - public override MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member) + public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member) { if (member is null) throw new ArgumentNullException(nameof(member)); - return member.MemberType switch + MemberInfo? result = member.MemberType switch { MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(member), MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(member), @@ -3083,6 +3083,8 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(member), _ => null }; + + return result ?? throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); } private MemberInfo? GetMethodWithSameMetadataDefinitionAs(MemberInfo method) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs index feedc533675db..08a077b037d73 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs @@ -110,7 +110,7 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul } else if (destinationType == typeof(InstanceDescriptor)) { - ConstructorInfo ci = (ConstructorInfo)NullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableConstructor)!; + ConstructorInfo ci = (ConstructorInfo)NullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableConstructor); Debug.Assert(ci != null, "Couldn't find constructor"); return new InstanceDescriptor(ci, new object[] { value }, true); } diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs index bfdee83fa64f0..3a0fc56030a92 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs @@ -35,7 +35,7 @@ public static ConstructorInfo GetNullableConstructor(Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - return (ConstructorInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableConstructor)!; + return (ConstructorInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableConstructor); } public static bool IsNullableType(this Type type) => type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs index 53898899c94ef..5cd7fd59185d2 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs @@ -906,7 +906,7 @@ internal static void EmitHasValue(this ILGenerator il, Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableHasValueGetter)!; + MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableHasValueGetter); Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); } @@ -915,7 +915,7 @@ internal static void EmitGetValue(this ILGenerator il, Type nullableType) { Debug.Assert(nullableType.IsNullableType()); - MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableValueGetter)!; + MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableValueGetter); Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); } @@ -924,7 +924,7 @@ internal static void EmitGetValueOrDefault(this ILGenerator il, Type nullableTyp { Debug.Assert(nullableType.IsNullableType()); - MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableGetValueOrDefault)!; + MethodInfo mi = (MethodInfo)nullableType.GetMemberWithSameMetadataDefinitionAs(s_nullableGetValueOrDefault); Debug.Assert(nullableType.IsValueType); il.Emit(OpCodes.Call, mi); } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs index 55c300172537c..505b29844da4b 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs @@ -617,7 +617,7 @@ private void EmitDynamicExpression(Expression expr) private static FieldInfo GetCallSiteTargetField(Type siteType) { Debug.Assert(siteType.IsGenericType && siteType.GetGenericTypeDefinition() == typeof(CallSite<>)); - return (FieldInfo)siteType.GetMemberWithSameMetadataDefinitionAs(s_callSiteTargetField)!; + return (FieldInfo)siteType.GetMemberWithSameMetadataDefinitionAs(s_callSiteTargetField); } private void EmitNewExpression(Expression expr) diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs index aaba66b0952cd..a615e89056abd 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs @@ -121,7 +121,7 @@ internal static MethodInfo GetCompileMethod(Type lambdaExpressionType) return typeof(LambdaExpression).GetMethod("Compile", Type.EmptyTypes)!; } - return (MethodInfo)lambdaExpressionType.GetMemberWithSameMetadataDefinitionAs(s_expressionCompileMethodInfo)!; + return (MethodInfo)lambdaExpressionType.GetMemberWithSameMetadataDefinitionAs(s_expressionCompileMethodInfo); } /// diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index c64c59ae39136..1b84362baf98f 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -3781,4 +3781,7 @@ File encryption is not supported on this platform. + + A MemberInfo that matches '{0}' could not be found. + \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeDelegator.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeDelegator.cs index f09c20aa97b9e..d9de5027ce0a2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeDelegator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeDelegator.cs @@ -126,6 +126,8 @@ public TypeDelegator([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes. [DynamicallyAccessedMembers(GetAllMembers)] public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => typeImpl.GetMembers(bindingAttr); + public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member) => typeImpl.GetMemberWithSameMetadataDefinitionAs(member); + protected override TypeAttributes GetAttributeFlagsImpl() => typeImpl.Attributes; public override bool IsTypeDefinition => typeImpl.IsTypeDefinition; diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 4195ed517934b..28fc83e0986bb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -227,13 +227,33 @@ public ConstructorInfo? TypeInitializer public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup); /// - /// Searches for the constructed generic member that matches the specified generic member definition. + /// Searches for the on the current that matches the specified . /// /// - /// The representing the generic definition of the member. + /// The to find on the current . /// - /// An object representing the member on the current constructed generic type that matches the specified generic definition, if found; otherwise, null. - public virtual MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member) => throw new NotSupportedException(SR.NotSupported_SubclassOverride); + /// An object representing the member on the current that matches the specified member. + /// This method can be used to find a constructed generic member given a member from a generic type definition. + /// is . + /// does not match a member on the current . + public virtual MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member) + { + if (member is null) throw new ArgumentNullException(nameof(member)); + + const BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; + foreach (MemberInfo myMemberInfo in GetMembers(all)) + { + if (myMemberInfo.HasSameMetadataDefinitionAs(member)) + { + return myMemberInfo; + } + } + + throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); + } + + private protected static ArgumentException CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(MemberInfo member) => + new ArgumentException(SR.Format(SR.Arg_MemberInfoNotFound, member.Name), nameof(member)); [DynamicallyAccessedMembers(GetAllMembers)] public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr); diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs index 71baa7066dd67..749ec9b59b3b2 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs @@ -390,7 +390,12 @@ void Complete() /// private static MethodInfo? GetTaskResultMethodInfo(Type taskType) { - return (MethodInfo?)taskType.GetMemberWithSameMetadataDefinitionAs(s_taskGetResultMethodInfo); + if (taskType.IsConstructedGenericType && taskType.GetGenericTypeDefinition() == typeof(Task<>)) + { + return (MethodInfo)taskType.GetMemberWithSameMetadataDefinitionAs(s_taskGetResultMethodInfo); + } + + return null; } public static string ObjectToString(object o) diff --git a/src/libraries/System.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs index 3d5940959ac11..433a70776e13d 100644 --- a/src/libraries/System.Reflection/tests/TypeInfoTests.cs +++ b/src/libraries/System.Reflection/tests/TypeInfoTests.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Xunit; @@ -1565,12 +1567,43 @@ public void IsSZArray(Type type, bool expected) Assert.Equal(expected, type.GetTypeInfo().IsSZArray); } - [Fact] - public void GetMemberWithSameMetadataDefinitionAs() + public static IEnumerable GetMemberWithSameMetadataDefinitionAsData() + { + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers) }; + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers) }; + + static TypeInfo GetTypeDelegator(Type t) => new TypeDelegator(t); + yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), typeof(TI_GenericTypeWithAllMembers) }; + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers)) }; + yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers)) }; + + if (RuntimeFeature.IsDynamicCodeSupported) + { + (Type generatedType1, Type generatedType2) = CreateGeneratedTypes(); + + yield return new object[] { generatedType1, generatedType2 }; + yield return new object[] { generatedType2, generatedType1 }; + } + } + + private static (Type, Type) CreateGeneratedTypes() { - Type openGenericType = typeof(TI_GenericTypeWithAllMembers<>); - Type closedGenericType = typeof(TI_GenericTypeWithAllMembers); + AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("GetMemberWithSameMetadataDefinitionAsGeneratedAssembly"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assembly.DefineDynamicModule("GetMemberWithSameMetadataDefinitionAsGeneratedModule"); + TypeBuilder genericType = module.DefineType("GenericGeneratedType"); + genericType.DefineGenericParameters("T0"); + genericType.DefineField("_int", typeof(int), FieldAttributes.Private); + genericType.DefineProperty("Prop", PropertyAttributes.None, typeof(string), null); + Type builtGenericType = genericType.CreateType(); + Type closedType = builtGenericType.MakeGenericType(typeof(int)); + + return (genericType, closedType); + } + + [Theory, MemberData(nameof(GetMemberWithSameMetadataDefinitionAsData))] + public void GetMemberWithSameMetadataDefinitionAs(Type openGenericType, Type closedGenericType) + { BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; foreach (MemberInfo openGenericMember in openGenericType.GetMembers(all)) { @@ -1580,9 +1613,12 @@ public void GetMemberWithSameMetadataDefinitionAs() Assert.Equal(closedGenericMember.Name, openGenericMember.Name); if (openGenericMember is not Type) { - Assert.True(closedGenericMember.DeclaringType == closedGenericType, $"'{closedGenericMember.Name}' doesn't have the right DeclaringType"); + Assert.True(closedGenericMember.DeclaringType.Equals(closedGenericType), $"'{closedGenericMember.Name}' doesn't have the right DeclaringType"); } } + + Assert.Throws(() => openGenericType.GetMemberWithSameMetadataDefinitionAs(null)); + Assert.Throws(() => openGenericType.GetMemberWithSameMetadataDefinitionAs(typeof(string).GetMethod("get_Length"))); } #pragma warning disable 0067, 0169 diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs index 79b1d7977be60..9398d93fb1f42 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs @@ -389,7 +389,7 @@ private bool DoValueTypeFixup(FieldInfo? memberToFix, ObjectHolder holder, objec { if (Nullable.GetUnderlyingType(type) != null) { - return (FieldInfo)type.GetMemberWithSameMetadataDefinitionAs(s_nullableValueField)!; + return (FieldInfo)type.GetMemberWithSameMetadataDefinitionAs(s_nullableValueField); } return null; diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index bee68d1d65aa9..2758e114fa8b2 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4470,7 +4470,7 @@ protected Type() { } public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.BindingFlags bindingAttr) { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; } - public virtual System.Reflection.MemberInfo? GetMemberWithSameMetadataDefinitionAs(System.Reflection.MemberInfo member) { throw null; } + public virtual System.Reflection.MemberInfo GetMemberWithSameMetadataDefinitionAs(System.Reflection.MemberInfo member) { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] public System.Reflection.MemberInfo[] GetMembers() { throw null; } [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicProperties | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicEvents | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicNestedTypes | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 3a166c22c5f9c..8fe9071ff1e25 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1119,11 +1119,11 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla return compressMembers; } - public override MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member) + public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member) { if (member is null) throw new ArgumentNullException(nameof(member)); - return member.MemberType switch + MemberInfo? result = member.MemberType switch { MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(member), MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(member), @@ -1133,6 +1133,8 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(member), _ => null }; + + return result ?? throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); } private const BindingFlags GetMemberWithSameMetadataDefinitionAsBindingFlags = From f80df3e62a985cf0d3f96e75f002415481b16ef1 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Sat, 5 Jun 2021 07:41:14 -0500 Subject: [PATCH 05/10] Fix trimming warning --- src/libraries/System.Private.CoreLib/src/System/Type.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 28fc83e0986bb..4cb76612b1d93 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -236,6 +236,9 @@ public ConstructorInfo? TypeInitializer /// This method can be used to find a constructed generic member given a member from a generic type definition. /// is . /// does not match a member on the current . + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2085:UnrecognizedReflectionPattern", + Justification = "This is finding the MemberInfo with the same MetadataToken as specified MemberInfo. If the specified MemberInfo " + + "exists and wasn't trimmed, then the current Type's MemberInfo couldn't have been trimmed.")] public virtual MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member) { if (member is null) throw new ArgumentNullException(nameof(member)); From 9f09790fa61f8f519796c2907e4dad4e2a80e03d Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 9 Jun 2021 18:29:43 -0500 Subject: [PATCH 06/10] Fix wasm tests --- .../Runtime/InteropServices/JavaScript/Runtime.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs index 749ec9b59b3b2..d2140346387cc 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs @@ -390,12 +390,16 @@ void Complete() /// private static MethodInfo? GetTaskResultMethodInfo(Type taskType) { - if (taskType.IsConstructedGenericType && taskType.GetGenericTypeDefinition() == typeof(Task<>)) + try { return (MethodInfo)taskType.GetMemberWithSameMetadataDefinitionAs(s_taskGetResultMethodInfo); } - - return null; + catch (ArgumentException) + { + // If the taskType wasn't assignable to Task, the get_Result method won't be found. + // Return null in that case. + return null; + } } public static string ObjectToString(object o) From f7754582fbe404afb4f60f76fca3947a3f6a7877 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 9 Jun 2021 22:04:23 -0500 Subject: [PATCH 07/10] Revert JavaScript Runtime changes. --- .../InteropServices/JavaScript/Runtime.cs | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs index d2140346387cc..09e30d4bb4622 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs @@ -12,15 +12,16 @@ namespace System.Runtime.InteropServices.JavaScript { public static class Runtime { - private static readonly Dictionary> s_boundObjects = new Dictionary>(); - private static readonly Dictionary s_rawToJS = new Dictionary(); + private static readonly Dictionary> _boundObjects = new Dictionary>(); + private static readonly Dictionary _rawToJS = new Dictionary(); // _weakDelegateTable is a ConditionalWeakTable with the Delegate and associated JSObject: // Key Lifetime: // Once the key dies, the dictionary automatically removes the key/value entry. // No need to lock as it is thread safe. - private static readonly ConditionalWeakTable s_weakDelegateTable = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable _weakDelegateTable = new ConditionalWeakTable(); - private static readonly MethodInfo s_taskGetResultMethodInfo = typeof(Task<>).GetMethod("get_Result")!; + private const string TaskGetResultName = "get_Result"; + private static readonly MethodInfo _taskGetResultMethodInfo = typeof(Task<>).GetMethod(TaskGetResultName)!; // // Execute the provided string in the JavaScript context @@ -55,9 +56,9 @@ public static void FreeObject(object obj) } JSObject? jsobj; - lock (s_rawToJS) + lock (_rawToJS) { - if (!s_rawToJS.Remove(obj, out jsobj)) + if (!_rawToJS.Remove(obj, out jsobj)) { throw new JSException(SR.Format(SR.ErrorReleasingObject, obj)); } @@ -78,15 +79,15 @@ public static int BindJSObject(int jsId, bool ownsHandle, int mappedType) { JSObject? target = null; - lock (s_boundObjects) + lock (_boundObjects) { - if (!s_boundObjects.TryGetValue(jsId, out WeakReference? reference) || + if (!_boundObjects.TryGetValue(jsId, out WeakReference? reference) || !reference.TryGetTarget(out target) || target.IsDisposed) { IntPtr jsIntPtr = (IntPtr)jsId; target = mappedType > 0 ? BindJSType(jsIntPtr, ownsHandle, mappedType) : new JSObject(jsIntPtr, ownsHandle); - s_boundObjects[jsId] = new WeakReference(target, trackResurrection: true); + _boundObjects[jsId] = new WeakReference(target, trackResurrection: true); } } @@ -98,9 +99,9 @@ public static int BindCoreCLRObject(int jsId, int gcHandle) GCHandle h = (GCHandle)(IntPtr)gcHandle; JSObject? obj = null; - lock (s_boundObjects) + lock (_boundObjects) { - if (s_boundObjects.TryGetValue(jsId, out WeakReference? wr)) + if (_boundObjects.TryGetValue(jsId, out WeakReference? wr)) { if (!wr.TryGetTarget(out JSObject? instance) || (instance.Int32Handle != (int)(IntPtr)h && h.IsAllocated)) { @@ -111,7 +112,7 @@ public static int BindCoreCLRObject(int jsId, int gcHandle) } else if (h.Target is JSObject instance) { - s_boundObjects.Add(jsId, new WeakReference(instance, trackResurrection: true)); + _boundObjects.Add(jsId, new WeakReference(instance, trackResurrection: true)); obj = instance; } } @@ -146,9 +147,9 @@ internal static bool ReleaseJSObject(JSObject objToRelease) if (exception != 0) throw new JSException($"Error releasing handle on (js-obj js '{objToRelease.JSHandle}' mono '{objToRelease.Int32Handle} raw '{objToRelease.RawObject != null}' weak raw '{objToRelease.IsWeakWrapper}' )"); - lock (s_boundObjects) + lock (_boundObjects) { - s_boundObjects.Remove(objToRelease.JSHandle); + _boundObjects.Remove(objToRelease.JSHandle); } return true; } @@ -157,11 +158,11 @@ public static void UnBindRawJSObjectAndFree(int gcHandle) { GCHandle h = (GCHandle)(IntPtr)gcHandle; JSObject? obj = h.Target as JSObject; - lock (s_rawToJS) + lock (_rawToJS) { if (obj?.RawObject != null) { - s_rawToJS.Remove(obj.RawObject); + _rawToJS.Remove(obj.RawObject); obj.FreeHandle(); } } @@ -193,22 +194,22 @@ public static int BindExistingObject(object rawObj, int jsId) if (rawObj is Delegate dele) { jsObject = new JSObject(jsId, dele); - lock (s_boundObjects) + lock (_boundObjects) { - s_boundObjects.Add(jsId, new WeakReference(jsObject)); + _boundObjects.Add(jsId, new WeakReference(jsObject)); } - lock (s_weakDelegateTable) + lock (_weakDelegateTable) { - s_weakDelegateTable.Add(dele, jsObject); + _weakDelegateTable.Add(dele, jsObject); } } else { - lock (s_rawToJS) + lock (_rawToJS) { - if (!s_rawToJS.TryGetValue(rawObj, out jsObject)) + if (!_rawToJS.TryGetValue(rawObj, out jsObject)) { - s_rawToJS.Add(rawObj, jsObject = new JSObject(jsId, rawObj)); + _rawToJS.Add(rawObj, jsObject = new JSObject(jsId, rawObj)); } } } @@ -220,16 +221,16 @@ public static int GetJSObjectId(object rawObj) JSObject? jsObject; if (rawObj is Delegate dele) { - lock (s_weakDelegateTable) + lock (_weakDelegateTable) { - s_weakDelegateTable.TryGetValue(dele, out jsObject); + _weakDelegateTable.TryGetValue(dele, out jsObject); } } else { - lock (s_rawToJS) + lock (_rawToJS) { - s_rawToJS.TryGetValue(rawObj, out jsObject); + _rawToJS.TryGetValue(rawObj, out jsObject); } } return jsObject?.JSHandle ?? -1; @@ -388,18 +389,17 @@ void Complete() /// The reason for this restriction is to make this use of Reflection trim-compatible, /// ensuring that trimming doesn't change the application's behavior. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "Task.Result is preserved by the ILLinker because _taskGetResultMethodInfo was initialized with it.")] private static MethodInfo? GetTaskResultMethodInfo(Type taskType) { - try - { - return (MethodInfo)taskType.GetMemberWithSameMetadataDefinitionAs(s_taskGetResultMethodInfo); - } - catch (ArgumentException) + MethodInfo? result = taskType.GetMethod(TaskGetResultName); + if (result != null && result.HasSameMetadataDefinitionAs(_taskGetResultMethodInfo)) { - // If the taskType wasn't assignable to Task, the get_Result method won't be found. - // Return null in that case. - return null; + return result; } + + return null; } public static string ObjectToString(object o) @@ -481,9 +481,9 @@ public static void SafeHandleReleaseByHandle(int jsId) #if DEBUG_HANDLE Debug.WriteLine($"SafeHandleReleaseByHandle: {jsId}"); #endif - lock (s_boundObjects) + lock (_boundObjects) { - if (s_boundObjects.TryGetValue(jsId, out WeakReference? reference)) + if (_boundObjects.TryGetValue(jsId, out WeakReference? reference)) { reference.TryGetTarget(out JSObject? target); Debug.Assert(target != null, $"\tSafeHandleReleaseByHandle: did not find active target {jsId}"); From a38c6608ff6beca0e229db28a99d48e7cc8b093b Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 9 Jun 2021 22:09:07 -0500 Subject: [PATCH 08/10] Revert whitespace changes caused by VS --- .../src/Resources/Strings.resx | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 1b84362baf98f..99b032174387f 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -1,17 +1,17 @@  - From 5fe95b02593fab17b250725c9cf36e7ef567ea6c Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Thu, 10 Jun 2021 18:39:18 -0500 Subject: [PATCH 09/10] Support inheritance in GetMemberWithSameMetadataDefinitionAs. --- .../src/System/RuntimeType.CoreCLR.cs | 126 +++++++++++------- .../System.Private.CoreLib/src/System/Type.cs | 2 +- .../System.Reflection/tests/TypeInfoTests.cs | 38 ++++-- .../src/System/RuntimeType.Mono.cs | 2 +- 4 files changed, 109 insertions(+), 59 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 4fc1d20f396ab..5f1ae54982007 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3075,109 +3075,139 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb MemberInfo? result = member.MemberType switch { - MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(member), - MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(member), - MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(member), - MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(member), - MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(member), - MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(member), + MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(this, member), + MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(this, member), + MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(this, member), + MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(this, member), + MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(this, member), + MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(this, member), _ => null }; return result ?? throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); } - private MemberInfo? GetMethodWithSameMetadataDefinitionAs(MemberInfo method) + private static MemberInfo? GetMethodWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo method) { - RuntimeMethodInfo[] cache = Cache.GetMethodList(MemberListType.CaseSensitive, method.Name); - - for (int i = 0; i < cache.Length; i++) + while (runtimeType != null) { - RuntimeMethodInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(method)) + RuntimeMethodInfo[] cache = runtimeType.Cache.GetMethodList(MemberListType.CaseSensitive, method.Name); + + for (int i = 0; i < cache.Length; i++) { - return candidate; + RuntimeMethodInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(method)) + { + return candidate; + } } + + runtimeType = runtimeType.GetBaseType(); } return null; } - private MemberInfo? GetConstructorWithSameMetadataDefinitionAs(MemberInfo constructor) + private static MemberInfo? GetConstructorWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo constructor) { - RuntimeConstructorInfo[] cache = Cache.GetConstructorList(MemberListType.CaseSensitive, constructor.Name); - - for (int i = 0; i < cache.Length; i++) + while (runtimeType != null) { - RuntimeConstructorInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(constructor)) + RuntimeConstructorInfo[] cache = runtimeType.Cache.GetConstructorList(MemberListType.CaseSensitive, constructor.Name); + + for (int i = 0; i < cache.Length; i++) { - return candidate; + RuntimeConstructorInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(constructor)) + { + return candidate; + } } + + runtimeType = runtimeType.GetBaseType(); } return null; } - private MemberInfo? GetPropertyWithSameMetadataDefinitionAs(MemberInfo property) + private static MemberInfo? GetPropertyWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo property) { - RuntimePropertyInfo[] cache = Cache.GetPropertyList(MemberListType.CaseSensitive, property.Name); - - for (int i = 0; i < cache.Length; i++) + while (runtimeType != null) { - RuntimePropertyInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(property)) + RuntimePropertyInfo[] cache = runtimeType.Cache.GetPropertyList(MemberListType.CaseSensitive, property.Name); + + for (int i = 0; i < cache.Length; i++) { - return candidate; + RuntimePropertyInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(property)) + { + return candidate; + } } + + runtimeType = runtimeType.GetBaseType(); } return null; } - private MemberInfo? GetFieldWithSameMetadataDefinitionAs(MemberInfo field) + private static MemberInfo? GetFieldWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo field) { - RuntimeFieldInfo[] cache = Cache.GetFieldList(MemberListType.CaseSensitive, field.Name); - - for (int i = 0; i < cache.Length; i++) + while (runtimeType != null) { - RuntimeFieldInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(field)) + RuntimeFieldInfo[] cache = runtimeType.Cache.GetFieldList(MemberListType.CaseSensitive, field.Name); + + for (int i = 0; i < cache.Length; i++) { - return candidate; + RuntimeFieldInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(field)) + { + return candidate; + } } + + runtimeType = runtimeType.GetBaseType(); } return null; } - private MemberInfo? GetEventWithSameMetadataDefinitionAs(MemberInfo eventInfo) + private static MemberInfo? GetEventWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo eventInfo) { - RuntimeEventInfo[] cache = Cache.GetEventList(MemberListType.CaseSensitive, eventInfo.Name); - - for (int i = 0; i < cache.Length; i++) + while (runtimeType != null) { - RuntimeEventInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(eventInfo)) + RuntimeEventInfo[] cache = runtimeType.Cache.GetEventList(MemberListType.CaseSensitive, eventInfo.Name); + + for (int i = 0; i < cache.Length; i++) { - return candidate; + RuntimeEventInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(eventInfo)) + { + return candidate; + } } + + runtimeType = runtimeType.GetBaseType(); } return null; } - private MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(MemberInfo nestedType) + private static MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo nestedType) { - RuntimeType[] cache = Cache.GetNestedTypeList(MemberListType.CaseSensitive, nestedType.Name); - - for (int i = 0; i < cache.Length; i++) + while (runtimeType != null) { - RuntimeType candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(nestedType)) + RuntimeType[] cache = runtimeType.Cache.GetNestedTypeList(MemberListType.CaseSensitive, nestedType.Name); + + for (int i = 0; i < cache.Length; i++) { - return candidate; + RuntimeType candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(nestedType)) + { + return candidate; + } } + + runtimeType = runtimeType.GetBaseType(); } return null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 4cb76612b1d93..3c1a1783a6e76 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -243,7 +243,7 @@ public virtual MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo membe { if (member is null) throw new ArgumentNullException(nameof(member)); - const BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; + const BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; foreach (MemberInfo myMemberInfo in GetMembers(all)) { if (myMemberInfo.HasSameMetadataDefinitionAs(member)) diff --git a/src/libraries/System.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs index 433a70776e13d..f3b9240505c69 100644 --- a/src/libraries/System.Reflection/tests/TypeInfoTests.cs +++ b/src/libraries/System.Reflection/tests/TypeInfoTests.cs @@ -1569,20 +1569,25 @@ public void IsSZArray(Type type, bool expected) public static IEnumerable GetMemberWithSameMetadataDefinitionAsData() { - yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers) }; - yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers) }; + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers), true }; + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers), true}; + + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_TypeDerivedFromGenericTypeWithAllMembers), false }; + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_TypeDerivedFromGenericTypeWithAllMembers), false }; + + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_TypeDerivedFromGenericTypeWithAllMembersClosed), false }; static TypeInfo GetTypeDelegator(Type t) => new TypeDelegator(t); - yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), typeof(TI_GenericTypeWithAllMembers) }; - yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers)) }; - yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers)) }; + yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), typeof(TI_GenericTypeWithAllMembers), true }; + yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers)), true }; + yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers)), true }; if (RuntimeFeature.IsDynamicCodeSupported) { (Type generatedType1, Type generatedType2) = CreateGeneratedTypes(); - yield return new object[] { generatedType1, generatedType2 }; - yield return new object[] { generatedType2, generatedType1 }; + yield return new object[] { generatedType1, generatedType2, true }; + yield return new object[] { generatedType2, generatedType1, true }; } } @@ -1602,7 +1607,7 @@ private static (Type, Type) CreateGeneratedTypes() } [Theory, MemberData(nameof(GetMemberWithSameMetadataDefinitionAsData))] - public void GetMemberWithSameMetadataDefinitionAs(Type openGenericType, Type closedGenericType) + public void GetMemberWithSameMetadataDefinitionAs(Type openGenericType, Type closedGenericType, bool checkDeclaringType) { BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; foreach (MemberInfo openGenericMember in openGenericType.GetMembers(all)) @@ -1611,12 +1616,17 @@ public void GetMemberWithSameMetadataDefinitionAs(Type openGenericType, Type clo Assert.True(closedGenericMember != null, $"'{openGenericMember.Name}' was not found"); Assert.True(closedGenericMember.HasSameMetadataDefinitionAs(openGenericMember)); Assert.Equal(closedGenericMember.Name, openGenericMember.Name); - if (openGenericMember is not Type) + if (checkDeclaringType && openGenericMember is not Type) { Assert.True(closedGenericMember.DeclaringType.Equals(closedGenericType), $"'{closedGenericMember.Name}' doesn't have the right DeclaringType"); } } + MemberInfo toString = closedGenericType.GetMemberWithSameMetadataDefinitionAs(typeof(object).GetMethod("ToString")); + Assert.NotNull(toString); + Assert.IsAssignableFrom(toString); + Assert.Equal("ToString", toString.Name); + Assert.Throws(() => openGenericType.GetMemberWithSameMetadataDefinitionAs(null)); Assert.Throws(() => openGenericType.GetMemberWithSameMetadataDefinitionAs(typeof(string).GetMethod("get_Length"))); } @@ -1909,6 +1919,16 @@ public class Nested } } + public class TI_TypeDerivedFromGenericTypeWithAllMembers : TI_GenericTypeWithAllMembers + { + public TI_TypeDerivedFromGenericTypeWithAllMembers(T t) : base(t) { } + } + + public class TI_TypeDerivedFromGenericTypeWithAllMembersClosed : TI_TypeDerivedFromGenericTypeWithAllMembers + { + public TI_TypeDerivedFromGenericTypeWithAllMembersClosed(int t) : base(t) { } + } + #pragma warning restore 0067, 0169 public class OutsideTypeInfoTests diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 8fe9071ff1e25..78fcbc66a1067 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1138,7 +1138,7 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb } private const BindingFlags GetMemberWithSameMetadataDefinitionAsBindingFlags = - BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private MemberInfo? GetMethodWithSameMetadataDefinitionAs(MemberInfo methodInfo) { From 4a0e0f85d42ffa29549a1b500bc3eb70f2a78634 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 15 Jun 2021 13:25:46 -0500 Subject: [PATCH 10/10] Respond to PR feedback --- .../src/System/RuntimeType.CoreCLR.cs | 149 ++++++++---------- .../src/System/RuntimeType.Mono.cs | 57 ++++--- 2 files changed, 99 insertions(+), 107 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 5f1ae54982007..b07971e0f5600 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3073,141 +3073,122 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb { if (member is null) throw new ArgumentNullException(nameof(member)); - MemberInfo? result = member.MemberType switch - { - MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(this, member), - MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(this, member), - MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(this, member), - MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(this, member), - MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(this, member), - MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(this, member), - _ => null - }; - - return result ?? throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); - } - - private static MemberInfo? GetMethodWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo method) - { + RuntimeType? runtimeType = this; while (runtimeType != null) { - RuntimeMethodInfo[] cache = runtimeType.Cache.GetMethodList(MemberListType.CaseSensitive, method.Name); - - for (int i = 0; i < cache.Length; i++) + MemberInfo? result = member.MemberType switch { - RuntimeMethodInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(method)) - { - return candidate; - } + MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(runtimeType, member), + _ => null + }; + + if (result != null) + { + return result; } runtimeType = runtimeType.GetBaseType(); } - return null; + throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); } - private static MemberInfo? GetConstructorWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo constructor) + private static MemberInfo? GetMethodWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo method) { - while (runtimeType != null) - { - RuntimeConstructorInfo[] cache = runtimeType.Cache.GetConstructorList(MemberListType.CaseSensitive, constructor.Name); + RuntimeMethodInfo[] cache = runtimeType.Cache.GetMethodList(MemberListType.CaseSensitive, method.Name); - for (int i = 0; i < cache.Length; i++) + for (int i = 0; i < cache.Length; i++) + { + RuntimeMethodInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(method)) { - RuntimeConstructorInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(constructor)) - { - return candidate; - } + return candidate; } - - runtimeType = runtimeType.GetBaseType(); } return null; } - private static MemberInfo? GetPropertyWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo property) + private static MemberInfo? GetConstructorWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo constructor) { - while (runtimeType != null) - { - RuntimePropertyInfo[] cache = runtimeType.Cache.GetPropertyList(MemberListType.CaseSensitive, property.Name); + RuntimeConstructorInfo[] cache = runtimeType.Cache.GetConstructorList(MemberListType.CaseSensitive, constructor.Name); - for (int i = 0; i < cache.Length; i++) + for (int i = 0; i < cache.Length; i++) + { + RuntimeConstructorInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(constructor)) { - RuntimePropertyInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(property)) - { - return candidate; - } + return candidate; } - - runtimeType = runtimeType.GetBaseType(); } return null; } - private static MemberInfo? GetFieldWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo field) + private static MemberInfo? GetPropertyWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo property) { - while (runtimeType != null) - { - RuntimeFieldInfo[] cache = runtimeType.Cache.GetFieldList(MemberListType.CaseSensitive, field.Name); + RuntimePropertyInfo[] cache = runtimeType.Cache.GetPropertyList(MemberListType.CaseSensitive, property.Name); - for (int i = 0; i < cache.Length; i++) + for (int i = 0; i < cache.Length; i++) + { + RuntimePropertyInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(property)) { - RuntimeFieldInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(field)) - { - return candidate; - } + return candidate; } - - runtimeType = runtimeType.GetBaseType(); } return null; } - private static MemberInfo? GetEventWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo eventInfo) + private static MemberInfo? GetFieldWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo field) { - while (runtimeType != null) - { - RuntimeEventInfo[] cache = runtimeType.Cache.GetEventList(MemberListType.CaseSensitive, eventInfo.Name); + RuntimeFieldInfo[] cache = runtimeType.Cache.GetFieldList(MemberListType.CaseSensitive, field.Name); - for (int i = 0; i < cache.Length; i++) + for (int i = 0; i < cache.Length; i++) + { + RuntimeFieldInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(field)) { - RuntimeEventInfo candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(eventInfo)) - { - return candidate; - } + return candidate; } - - runtimeType = runtimeType.GetBaseType(); } return null; } - private static MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(RuntimeType? runtimeType, MemberInfo nestedType) + private static MemberInfo? GetEventWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo eventInfo) { - while (runtimeType != null) - { - RuntimeType[] cache = runtimeType.Cache.GetNestedTypeList(MemberListType.CaseSensitive, nestedType.Name); + RuntimeEventInfo[] cache = runtimeType.Cache.GetEventList(MemberListType.CaseSensitive, eventInfo.Name); - for (int i = 0; i < cache.Length; i++) + for (int i = 0; i < cache.Length; i++) + { + RuntimeEventInfo candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(eventInfo)) { - RuntimeType candidate = cache[i]; - if (candidate.HasSameMetadataDefinitionAs(nestedType)) - { - return candidate; - } + return candidate; } + } - runtimeType = runtimeType.GetBaseType(); + return null; + } + + private static MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo nestedType) + { + RuntimeType[] cache = runtimeType.Cache.GetNestedTypeList(MemberListType.CaseSensitive, nestedType.Name); + + for (int i = 0; i < cache.Length; i++) + { + RuntimeType candidate = cache[i]; + if (candidate.HasSameMetadataDefinitionAs(nestedType)) + { + return candidate; + } } return null; diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 78fcbc66a1067..241fee87a4c43 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1123,26 +1123,37 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb { if (member is null) throw new ArgumentNullException(nameof(member)); - MemberInfo? result = member.MemberType switch + RuntimeType? runtimeType = this; + while (runtimeType != null) { - MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(member), - MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(member), - MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(member), - MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(member), - MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(member), - MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(member), - _ => null - }; + MemberInfo? result = member.MemberType switch + { + MemberTypes.Method => GetMethodWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Constructor => GetConstructorWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Property => GetPropertyWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Field => GetFieldWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.Event => GetEventWithSameMetadataDefinitionAs(runtimeType, member), + MemberTypes.NestedType => GetNestedTypeWithSameMetadataDefinitionAs(runtimeType, member), + _ => null + }; + + if (result != null) + { + return result; + } + + runtimeType = runtimeType.GetBaseType(); + } - return result ?? throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); + throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member); } private const BindingFlags GetMemberWithSameMetadataDefinitionAsBindingFlags = - BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; - private MemberInfo? GetMethodWithSameMetadataDefinitionAs(MemberInfo methodInfo) + private static MemberInfo? GetMethodWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo methodInfo) { - ListBuilder methods = GetMethodCandidates(methodInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, CallingConventions.Any, null, -1, allowPrefixLookup: false); + ListBuilder methods = runtimeType.GetMethodCandidates(methodInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, CallingConventions.Any, null, -1, allowPrefixLookup: false); for (int i = 0; i < methods.Count; i++) { @@ -1156,9 +1167,9 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb return null; } - private MemberInfo? GetConstructorWithSameMetadataDefinitionAs(MemberInfo constructorInfo) + private static MemberInfo? GetConstructorWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo constructorInfo) { - ListBuilder ctors = GetConstructorCandidates(null, GetMemberWithSameMetadataDefinitionAsBindingFlags, CallingConventions.Any, null, allowPrefixLookup: false); + ListBuilder ctors = runtimeType.GetConstructorCandidates(null, GetMemberWithSameMetadataDefinitionAsBindingFlags, CallingConventions.Any, null, allowPrefixLookup: false); for (int i = 0; i < ctors.Count; i++) { @@ -1172,9 +1183,9 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb return null; } - private MemberInfo? GetPropertyWithSameMetadataDefinitionAs(MemberInfo propertyInfo) + private static MemberInfo? GetPropertyWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo propertyInfo) { - ListBuilder properties = GetPropertyCandidates(propertyInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, null, allowPrefixLookup: false); + ListBuilder properties = runtimeType.GetPropertyCandidates(propertyInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, null, allowPrefixLookup: false); for (int i = 0; i < properties.Count; i++) { @@ -1188,9 +1199,9 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb return null; } - private MemberInfo? GetFieldWithSameMetadataDefinitionAs(MemberInfo fieldInfo) + private static MemberInfo? GetFieldWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo fieldInfo) { - ListBuilder fields = GetFieldCandidates(fieldInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); + ListBuilder fields = runtimeType.GetFieldCandidates(fieldInfo.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); for (int i = 0; i < fields.Count; i++) { @@ -1204,9 +1215,9 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb return null; } - private MemberInfo? GetEventWithSameMetadataDefinitionAs(MemberInfo eventInfo) + private static MemberInfo? GetEventWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo eventInfo) { - ListBuilder events = GetEventCandidates(null, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); + ListBuilder events = runtimeType.GetEventCandidates(null, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); for (int i = 0; i < events.Count; i++) { @@ -1220,9 +1231,9 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb return null; } - private MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(MemberInfo nestedType) + private static MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo nestedType) { - ListBuilder nestedTypes = GetNestedTypeCandidates(nestedType.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); + ListBuilder nestedTypes = runtimeType.GetNestedTypeCandidates(nestedType.Name, GetMemberWithSameMetadataDefinitionAsBindingFlags, allowPrefixLookup: false); for (int i = 0; i < nestedTypes.Count; i++) {