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..b07971e0f5600 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,131 @@ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFla
return compressMembers;
}
+
+ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo member)
+ {
+ if (member is null) throw new ArgumentNullException(nameof(member));
+
+ RuntimeType? runtimeType = this;
+ while (runtimeType != 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();
+ }
+
+ throw CreateGetMemberWithSameMetadataDefinitionAsNotFoundException(member);
+ }
+
+ private static MemberInfo? GetMethodWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo method)
+ {
+ RuntimeMethodInfo[] cache = runtimeType.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 static MemberInfo? GetConstructorWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo constructor)
+ {
+ RuntimeConstructorInfo[] cache = runtimeType.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 static MemberInfo? GetPropertyWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo property)
+ {
+ RuntimePropertyInfo[] cache = runtimeType.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 static MemberInfo? GetFieldWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo field)
+ {
+ RuntimeFieldInfo[] cache = runtimeType.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 static MemberInfo? GetEventWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo eventInfo)
+ {
+ RuntimeEventInfo[] cache = runtimeType.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;
+ }
+
+ 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;
+ }
#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..08a077b037d73 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..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
@@ -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..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
@@ -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..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
@@ -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..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
@@ -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/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
index c64c59ae39136..99b032174387f 100644
--- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
+++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
@@ -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 ca57ed53988aa..3c1a1783a6e76 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Type.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs
@@ -226,6 +226,38 @@ public ConstructorInfo? TypeInitializer
DynamicallyAccessedMemberTypes.PublicNestedTypes)]
public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup);
+ ///
+ /// Searches for the on the current that matches the specified .
+ ///
+ ///
+ /// The to find on the current .
+ ///
+ /// 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 .
+ [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));
+
+ const BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
+ 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.Reflection/tests/TypeInfoTests.cs b/src/libraries/System.Reflection/tests/TypeInfoTests.cs
index 4e3603c2f3aa9..f3b9240505c69 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,6 +1567,70 @@ public void IsSZArray(Type type, bool expected)
Assert.Equal(expected, type.GetTypeInfo().IsSZArray);
}
+ public static IEnumerable