* Add API to find MethodInfo on instantiated generic type from generic type definition
Fix #45771
* Rename to GetMemberWithSameMetadataDefinitionAs
* Fix a bug for NestedType
* Use new method libraries that were working around not having it
* Implement GetMemberWithSameMetadataDefinitionAs in mono
* Revert JavaScript Runtime changes.
* Support inheritance in GetMemberWithSameMetadataDefinitionAs.
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
/// </summary>
public class NullableConverter : TypeConverter
{
+ private static readonly ConstructorInfo s_nullableConstructor = typeof(Nullable<>).GetConstructor(typeof(Nullable<>).GetGenericArguments())!;
+
/// <summary>
/// Nullable converter is initialized with the underlying simple type.
/// </summary>
}
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);
}
return base.ConvertTo(context, culture, value, destinationType);
}
- [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Nullable<>))]
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
- Justification = "The Nullable<T> ctor will be preserved by the DynamicDependency.")]
- private ConstructorInfo GetNullableConstructor()
- {
- return NullableType.GetConstructor(new Type[] { UnderlyingType })!;
- }
-
/// <summary>
/// </summary>
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
.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)
return type;
}
- [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Nullable<>))]
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
- Justification = "The Nullable<T> 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<>);
{
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);
if (TryEmitILConstant(il, value, nonNullType))
{
- il.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type, nonNullType));
+ il.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type));
return true;
}
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);
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);
}
il.EmitNonNullableToNullableConversion(typeFrom, typeTo, isChecked, locals);
}
- [DynamicDependency("get_HasValue", typeof(Nullable<>))]
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
- Justification = "The Nullable<T> 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<T> 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<T> 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);
}
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);
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;
{
internal sealed partial class LambdaCompiler
{
+ private static readonly FieldInfo s_callSiteTargetField = typeof(CallSite<>).GetField("Target")!;
+
[Flags]
internal enum CompilationFlags
{
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)
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);
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);
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
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);
[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)
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);
}
/// <summary>
<data name="PlatformNotSupported_FileEncryption" xml:space="preserve">
<value>File encryption is not supported on this platform.</value>
</data>
+ <data name="Arg_MemberInfoNotFound" xml:space="preserve">
+ <value>A MemberInfo that matches '{0}' could not be found.</value>
+ </data>
</root>
\ No newline at end of file
[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;
DynamicallyAccessedMemberTypes.PublicNestedTypes)]
public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup);
+ /// <summary>
+ /// Searches for the <see cref="MemberInfo"/> on the current <see cref="Type"/> that matches the specified <see cref="MemberInfo"/>.
+ /// </summary>
+ /// <param name="member">
+ /// The <see cref="MemberInfo"/> to find on the current <see cref="Type"/>.
+ /// </param>
+ /// <returns>An object representing the member on the current <see cref="Type"/> that matches the specified member.</returns>
+ /// <remarks>This method can be used to find a constructed generic member given a member from a generic type definition.</remarks>
+ /// <exception cref="ArgumentNullException"><paramref name="member"/> is <see langword="null"/>.</exception>
+ /// <exception cref="ArgumentException"><paramref name="member"/> does not match a member on the current <see cref="Type"/>.</exception>
+ [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);
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Xunit;
Assert.Equal(expected, type.GetTypeInfo().IsSZArray);
}
+ public static IEnumerable<object[]> GetMemberWithSameMetadataDefinitionAsData()
+ {
+ yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers<int>), true };
+ yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_GenericTypeWithAllMembers<ClassWithMultipleConstructors>), true};
+
+ yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_TypeDerivedFromGenericTypeWithAllMembers<int>), false };
+ yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), typeof(TI_TypeDerivedFromGenericTypeWithAllMembers<ClassWithMultipleConstructors>), 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<ClassWithMultipleConstructors>), true };
+ yield return new object[] { typeof(TI_GenericTypeWithAllMembers<>), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<ClassWithMultipleConstructors>)), true };
+ yield return new object[] { GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<>)), GetTypeDelegator(typeof(TI_GenericTypeWithAllMembers<ClassWithMultipleConstructors>)), true };
+
+ if (RuntimeFeature.IsDynamicCodeSupported)
+ {
+ (Type generatedType1, Type generatedType2) = CreateGeneratedTypes();
+
+ yield return new object[] { generatedType1, generatedType2, true };
+ yield return new object[] { generatedType2, generatedType1, true };
+ }
+ }
+
+ private static (Type, Type) CreateGeneratedTypes()
+ {
+ 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, bool checkDeclaringType)
+ {
+ BindingFlags all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
+ foreach (MemberInfo openGenericMember in openGenericType.GetMembers(all))
+ {
+ 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);
+ 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<MethodInfo>(toString);
+ Assert.Equal("ToString", toString.Name);
+
+ Assert.Throws<ArgumentNullException>(() => openGenericType.GetMemberWithSameMetadataDefinitionAs(null));
+ Assert.Throws<ArgumentException>(() => openGenericType.GetMemberWithSameMetadataDefinitionAs(typeof(string).GetMethod("get_Length")));
+ }
+
#pragma warning disable 0067, 0169
public static class ClassWithStaticConstructor
{
public abstract class AbstractSubClass : AbstractBaseClass { }
public class AbstractSubSubClass : AbstractSubClass { }
}
+
+ public class TI_GenericTypeWithAllMembers<T>
+ {
+ private static event EventHandler<T> 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<T> 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<T> 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<T> PrivateInstanceEvent;
+ private T PrivateInstanceField;
+ 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;
+ }
+ }
+
+ public class TI_TypeDerivedFromGenericTypeWithAllMembers<T> : TI_GenericTypeWithAllMembers<T>
+ {
+ public TI_TypeDerivedFromGenericTypeWithAllMembers(T t) : base(t) { }
+ }
+
+ public class TI_TypeDerivedFromGenericTypeWithAllMembersClosed : TI_TypeDerivedFromGenericTypeWithAllMembers<int>
+ {
+ public TI_TypeDerivedFromGenericTypeWithAllMembersClosed(int t) : base(t) { }
+ }
+
#pragma warning restore 0067, 0169
public class OutsideTypeInfoTests
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;
return true;
}
- [DynamicDependency("value", typeof(Nullable<>))]
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
- Justification = "The Nullable<T>.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;
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; }
[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)]
return (RuntimeType)DeclaringType;
}
- private RuntimeType ReflectedTypeInternal
- {
- get
- {
- return (RuntimeType)ReflectedType;
- }
- }
-
internal RuntimeModule GetRuntimeModule()
{
return GetDeclaringTypeInternal().GetRuntimeModule();
return (RuntimeType)DeclaringType!;
}
- private RuntimeType ReflectedTypeInternal
- {
- get
- {
- return (RuntimeType)ReflectedType;
- }
- }
-
internal RuntimeModule GetRuntimeModule()
{
return GetDeclaringTypeInternal().GetRuntimeModule();
}
}
- private RuntimeType? ReflectedTypeInternal
- {
- get
- {
- return (RuntimeType?)ReflectedType;
- }
- }
-
private string FormatNameAndSig()
{
// Serialization uses ToString to resolve MethodInfo overloads.
return RuntimeTypeHandle.GetModule((RuntimeType)DeclaringType);
}
- private RuntimeType? ReflectedTypeInternal
- {
- get
- {
- return (RuntimeType?)ReflectedType;
- }
- }
-
public override MethodImplAttributes GetMethodImplementationFlags()
{
return MonoMethodInfo.GetMethodImplementationFlags(mhandle);
return (RuntimeType)DeclaringType;
}
- private RuntimeType ReflectedTypeInternal
- {
- get
- {
- return (RuntimeType)ReflectedType;
- }
- }
-
internal RuntimeModule GetRuntimeModule()
{
return GetDeclaringTypeInternal().GetRuntimeModule();
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;
FormatFullInst
}
- internal enum TypeNameKind
- {
- Name,
- ToString,
- SerializationName,
- FullName,
- }
-
internal partial class RuntimeType
{
#region Definitions
return compressMembers;
}
- #endregion
+ 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 const BindingFlags GetMemberWithSameMetadataDefinitionAsBindingFlags =
+ BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+
+ private static MemberInfo? GetMethodWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo methodInfo)
+ {
+ ListBuilder<MethodInfo> methods = runtimeType.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 static MemberInfo? GetConstructorWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo constructorInfo)
+ {
+ ListBuilder<ConstructorInfo> ctors = runtimeType.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 static MemberInfo? GetPropertyWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo propertyInfo)
+ {
+ ListBuilder<PropertyInfo> properties = runtimeType.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 static MemberInfo? GetFieldWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo fieldInfo)
+ {
+ ListBuilder<FieldInfo> fields = runtimeType.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 static MemberInfo? GetEventWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo eventInfo)
+ {
+ ListBuilder<EventInfo> events = runtimeType.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 static MemberInfo? GetNestedTypeWithSameMetadataDefinitionAs(RuntimeType runtimeType, MemberInfo nestedType)
+ {
+ ListBuilder<Type> nestedTypes = runtimeType.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