diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml
index b1a9381f3fd415..0abedd830a6b14 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml
@@ -653,14 +653,6 @@
CP0001
T:Internal.Metadata.NativeFormat.UInt64Collection
-
- CP0001
- T:Internal.Reflection.Augments.ReflectionAugments
-
-
- CP0001
- T:Internal.Reflection.Augments.ReflectionCoreCallbacks
-
CP0001
T:Internal.Reflection.Core.AssemblyBinder
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs
index 5ed208a4d59815..86fbbcba782fe5 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs
@@ -17,30 +17,31 @@
// Reflection.Core.dll
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
-using System.Numerics;
using System.Reflection;
-
+using System.Reflection.Runtime.Assemblies;
+using System.Reflection.Runtime.BindingFlagSupport;
+using System.Reflection.Runtime.FieldInfos;
+using System.Reflection.Runtime.FieldInfos.NativeFormat;
+using System.Reflection.Runtime.General;
+using System.Reflection.Runtime.MethodInfos;
+using System.Reflection.Runtime.TypeInfos;
+using System.Reflection.Runtime.TypeInfos.NativeFormat;
+
+using Internal.Metadata.NativeFormat;
+using Internal.Reflection.Core.Execution;
using Internal.Runtime;
+using Internal.Runtime.Augments;
using EETypeElementType = Internal.Runtime.EETypeElementType;
namespace Internal.Reflection.Augments
{
- public static class ReflectionAugments
+ internal static class ReflectionAugments
{
- //
- // One time start up initialization - called by Reflection.Core.dll to provide System.Reflection with a way to call back
- // into Reflection.Core.dll.
- //
- public static void Initialize(ReflectionCoreCallbacks reflectionCoreCallbacks)
- {
- Debug.Assert(s_reflectionCoreCallbacks == null);
- s_reflectionCoreCallbacks = reflectionCoreCallbacks;
- }
-
internal static unsafe TypeCode GetRuntimeTypeCode(RuntimeType type)
{
Debug.Assert(type != null);
@@ -97,82 +98,436 @@ public static TypeLoadException CreateTypeLoadException(string message, string t
return new TypeLoadException(message, typeName);
}
- internal static ReflectionCoreCallbacks ReflectionCoreCallbacks
+ public static Assembly Load(AssemblyName assemblyRef, bool throwOnFileNotFound)
+ {
+ ArgumentNullException.ThrowIfNull(assemblyRef);
+
+ if (throwOnFileNotFound)
+ return RuntimeAssemblyInfo.GetRuntimeAssembly(assemblyRef.ToRuntimeAssemblyName());
+ else
+ return RuntimeAssemblyInfo.GetRuntimeAssemblyIfExists(assemblyRef.ToRuntimeAssemblyName());
+ }
+
+ public static Assembly Load(ReadOnlySpan rawAssembly, ReadOnlySpan pdbSymbolStore)
+ {
+ if (rawAssembly.IsEmpty)
+ throw new ArgumentNullException(nameof(rawAssembly));
+
+ return RuntimeAssemblyInfo.GetRuntimeAssemblyFromByteArray(rawAssembly, pdbSymbolStore);
+ }
+
+ public static Assembly Load(string assemblyPath)
{
- get
+ ArgumentNullException.ThrowIfNull(assemblyPath);
+
+ return RuntimeAssemblyInfo.GetRuntimeAssemblyFromPath(assemblyPath);
+ }
+
+ //
+ // This overload of GetMethodForHandle only accepts handles for methods declared on non-generic types (the method, however,
+ // can be an instance of a generic method.) To resolve handles for methods declared on generic types, you must pass
+ // the declaring type explicitly using the two-argument overload of GetMethodFromHandle.
+ //
+ // This is a vestige from desktop generic sharing that got itself enshrined in the code generated by the C# compiler for Linq Expressions.
+ //
+ public static MethodBase GetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle)
+ {
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ QMethodDefinition methodHandle;
+ RuntimeTypeHandle declaringTypeHandle;
+ RuntimeTypeHandle[] genericMethodTypeArgumentHandles;
+ if (!executionEnvironment.TryGetMethodFromHandle(runtimeMethodHandle, out declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ throw new ArgumentException(SR.Argument_InvalidHandle);
+
+ MethodBase methodBase = ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles);
+ if (methodBase.DeclaringType.IsConstructedGenericType) // For compat with desktop, insist that the caller pass us the declaring type to resolve members of generic types.
+ throw new ArgumentException(SR.Format(SR.Argument_MethodDeclaringTypeGeneric, methodBase));
+ return methodBase;
+ }
+
+ //
+ // This overload of GetMethodHandle can handle all method handles.
+ //
+ public static MethodBase GetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle)
+ {
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ QMethodDefinition methodHandle;
+ RuntimeTypeHandle[] genericMethodTypeArgumentHandles;
+ if (!executionEnvironment.TryGetMethodFromHandleAndType(runtimeMethodHandle, declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
{
- ReflectionCoreCallbacks callbacks = s_reflectionCoreCallbacks;
- Debug.Assert(callbacks != null);
- return callbacks;
+ // This may be a method declared on a non-generic type: this api accepts that too so try the other table.
+ RuntimeTypeHandle actualDeclaringTypeHandle;
+ if (!executionEnvironment.TryGetMethodFromHandle(runtimeMethodHandle, out actualDeclaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ throw new ArgumentException(SR.Argument_InvalidHandle);
+ if (!actualDeclaringTypeHandle.Equals(declaringTypeHandle))
+ throw new ArgumentException(SR.Format(SR.Argument_ResolveMethodHandle,
+ declaringTypeHandle.GetRuntimeTypeInfoForRuntimeTypeHandle(),
+ actualDeclaringTypeHandle.GetRuntimeTypeInfoForRuntimeTypeHandle()));
}
+
+ MethodBase methodBase = ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles);
+ return methodBase;
}
- internal static bool IsInitialized
+ //
+ // This overload of GetFieldForHandle only accepts handles for fields declared on non-generic types. To resolve handles for fields
+ // declared on generic types, you must pass the declaring type explicitly using the two-argument overload of GetFieldFromHandle.
+ //
+ // This is a vestige from desktop generic sharing that got itself enshrined in the code generated by the C# compiler for Linq Expressions.
+ //
+ public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle)
+ {
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ FieldHandle fieldHandle;
+ RuntimeTypeHandle declaringTypeHandle;
+ if (!executionEnvironment.TryGetFieldFromHandle(runtimeFieldHandle, out declaringTypeHandle, out fieldHandle))
+ throw new ArgumentException(SR.Argument_InvalidHandle);
+
+ FieldInfo fieldInfo = GetFieldInfo(declaringTypeHandle, fieldHandle);
+ if (fieldInfo.DeclaringType.IsConstructedGenericType) // For compat with desktop, insist that the caller pass us the declaring type to resolve members of generic types.
+ throw new ArgumentException(SR.Format(SR.Argument_FieldDeclaringTypeGeneric, fieldInfo));
+ return fieldInfo;
+ }
+
+ //
+ // This overload of GetFieldHandle can handle all field handles.
+ //
+ public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, RuntimeTypeHandle declaringTypeHandle)
{
- get
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ FieldHandle fieldHandle;
+ if (!executionEnvironment.TryGetFieldFromHandleAndType(runtimeFieldHandle, declaringTypeHandle, out fieldHandle))
{
- return s_reflectionCoreCallbacks != null;
+ // This may be a field declared on a non-generic type: this api accepts that too so try the other table.
+ RuntimeTypeHandle actualDeclaringTypeHandle;
+ if (!executionEnvironment.TryGetFieldFromHandle(runtimeFieldHandle, out actualDeclaringTypeHandle, out fieldHandle))
+ throw new ArgumentException(SR.Argument_InvalidHandle);
+ if (!actualDeclaringTypeHandle.Equals(declaringTypeHandle))
+ throw new ArgumentException(SR.Format(SR.Argument_ResolveFieldHandle,
+ declaringTypeHandle.GetRuntimeTypeInfoForRuntimeTypeHandle(),
+ actualDeclaringTypeHandle.GetRuntimeTypeInfoForRuntimeTypeHandle()));
}
+
+ FieldInfo fieldInfo = GetFieldInfo(declaringTypeHandle, fieldHandle);
+ return fieldInfo;
}
- private static ReflectionCoreCallbacks s_reflectionCoreCallbacks;
- }
+ public static EventInfo GetImplicitlyOverriddenBaseClassEvent(EventInfo e)
+ {
+ return e.GetImplicitlyOverriddenBaseClassMember(EventPolicies.Instance);
+ }
- //
- // This class is implemented by Internal.Reflection.Core.dll and provides the actual implementation
- // of Type.GetTypeInfo() and Assembly.Load().
- //
- public abstract class ReflectionCoreCallbacks
- {
- public abstract Assembly Load(AssemblyName refName, bool throwOnFileNotFound);
- public abstract Assembly Load(ReadOnlySpan rawAssembly, ReadOnlySpan pdbSymbolStore);
- public abstract Assembly Load(string assemblyPath);
+ public static MethodInfo GetImplicitlyOverriddenBaseClassMethod(MethodInfo m)
+ {
+ return m.GetImplicitlyOverriddenBaseClassMember(MethodPolicies.Instance);
+ }
+
+ public static PropertyInfo GetImplicitlyOverriddenBaseClassProperty(PropertyInfo p)
+ {
+ return p.GetImplicitlyOverriddenBaseClassMember(PropertyPolicies.Instance);
+ }
- public abstract MethodBase GetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle);
- public abstract MethodBase GetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle);
- public abstract FieldInfo GetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle);
- public abstract FieldInfo GetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, RuntimeTypeHandle declaringTypeHandle);
+ private static RuntimeFieldInfo GetFieldInfo(RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle)
+ {
+ RuntimeTypeInfo contextTypeInfo = declaringTypeHandle.GetRuntimeTypeInfoForRuntimeTypeHandle();
+ NativeFormatRuntimeNamedTypeInfo definingTypeInfo = contextTypeInfo.AnchoringTypeDefinitionForDeclaredMembers.CastToNativeFormatRuntimeNamedTypeInfo();
- public abstract EventInfo GetImplicitlyOverriddenBaseClassEvent(EventInfo e);
- public abstract MethodInfo GetImplicitlyOverriddenBaseClassMethod(MethodInfo m);
- public abstract PropertyInfo GetImplicitlyOverriddenBaseClassProperty(PropertyInfo p);
+ // RuntimeFieldHandles always yield FieldInfo's whose ReflectedType equals the DeclaringType.
+ RuntimeTypeInfo reflectedType = contextTypeInfo;
+ return NativeFormatRuntimeFieldInfo.GetRuntimeFieldInfo(fieldHandle, definingTypeInfo, contextTypeInfo, reflectedType);
+ }
- public abstract object ActivatorCreateInstance(
+ [DebuggerHidden]
+ [DebuggerStepThrough]
+ public static object ActivatorCreateInstance(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
- Type type, bool nonPublic);
- public abstract object ActivatorCreateInstance(
+ Type type, bool nonPublic)
+ {
+ return ActivatorImplementation.CreateInstance(type, nonPublic);
+ }
+
+ [DebuggerHidden]
+ [DebuggerStepThrough]
+ public static object ActivatorCreateInstance(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
- Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes);
+ Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes)
+ {
+ return ActivatorImplementation.CreateInstance(type, bindingAttr, binder, args, culture, activationAttributes);
+ }
// V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed.
- public abstract Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method, bool throwOnBindFailure);
+ public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
+ {
+ return CreateDelegateWorker(type, firstArgument, method, throwOnBindFailure, allowClosed: true);
+ }
// V1 api: Creates open delegates to static or instance methods - relaxed signature checking allowed.
- public abstract Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure);
+ public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure)
+ {
+ // This API existed in v1/v1.1 and only expected to create open
+ // instance delegates, so we forbid closed delegates for backward compatibility.
+ // But we'll allow relaxed signature checking and open static delegates because
+ // there's no ambiguity there (the caller would have to explicitly
+ // pass us a static method or a method with a non-exact signature
+ // and the only change in behavior from v1.1 there is that we won't
+ // fail the call).
+ return CreateDelegateWorker(type, null, method, throwOnBindFailure, allowClosed: false);
+ }
+
+ private static Delegate CreateDelegateWorker(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure, bool allowClosed)
+ {
+ ArgumentNullException.ThrowIfNull(type);
+ ArgumentNullException.ThrowIfNull(method);
+
+ if (!(type is RuntimeType runtimeDelegateType))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
+
+ if (!(method is RuntimeMethodInfo runtimeMethodInfo))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, nameof(method));
+
+ RuntimeTypeInfo runtimeDelegateTypeInfo = runtimeDelegateType.GetRuntimeTypeInfo();
+
+ if (!runtimeDelegateTypeInfo.IsDelegate)
+ throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(type));
+
+ Delegate result = runtimeMethodInfo.CreateDelegateNoThrowOnBindFailure(runtimeDelegateTypeInfo, firstArgument, allowClosed);
+ if (result == null)
+ {
+ if (throwOnBindFailure)
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ return null;
+ }
+ return result;
+ }
// V1 api: Creates closed delegates to instance methods only, relaxed signature checking disallowed.
[RequiresUnreferencedCode("The target method might be removed")]
- public abstract Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure);
+ public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
+ {
+ ArgumentNullException.ThrowIfNull(type);
+ ArgumentNullException.ThrowIfNull(target);
+ ArgumentNullException.ThrowIfNull(method);
+
+ if (!(type is RuntimeType runtimeDelegateType))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
+
+ RuntimeTypeInfo runtimeDelegateTypeInfo = runtimeDelegateType.GetRuntimeTypeInfo();
+ if (!runtimeDelegateTypeInfo.IsDelegate)
+ throw new ArgumentException(SR.Arg_MustBeDelegate);
+
+ RuntimeTypeInfo runtimeContainingType = target.GetType().ToRuntimeTypeInfo();
+ RuntimeMethodInfo runtimeMethodInfo = LookupMethodForCreateDelegate(runtimeDelegateTypeInfo, runtimeContainingType, method, isStatic: false, ignoreCase: ignoreCase);
+ if (runtimeMethodInfo == null)
+ {
+ if (throwOnBindFailure)
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ return null;
+ }
+ return runtimeMethodInfo.CreateDelegateWithoutSignatureValidation(type, target, isStatic: false, isOpen: false);
+ }
// V1 api: Creates open delegates to static methods only, relaxed signature checking disallowed.
- public abstract Delegate CreateDelegate(Type type, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.AllMethods)] Type target, string method, bool ignoreCase, bool throwOnBindFailure);
+ public static Delegate CreateDelegate(Type type, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.AllMethods)] Type target, string method, bool ignoreCase, bool throwOnBindFailure)
+ {
+ ArgumentNullException.ThrowIfNull(type);
+ ArgumentNullException.ThrowIfNull(target);
+ if (target.ContainsGenericParameters)
+ throw new ArgumentException(SR.Arg_UnboundGenParam, nameof(target));
+ ArgumentNullException.ThrowIfNull(method);
+
+ if (!(type is RuntimeType runtimeDelegateType))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(type));
+
+ if (!(target is RuntimeType runtimeContainingType))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(target));
+
+ RuntimeTypeInfo runtimeDelegateTypeInfo = runtimeDelegateType.GetRuntimeTypeInfo();
+
+ if (!runtimeDelegateTypeInfo.IsDelegate)
+ throw new ArgumentException(SR.Arg_MustBeDelegate);
+
+ RuntimeMethodInfo runtimeMethodInfo = LookupMethodForCreateDelegate(runtimeDelegateTypeInfo, runtimeContainingType.GetRuntimeTypeInfo(), method, isStatic: true, ignoreCase: ignoreCase);
+ if (runtimeMethodInfo == null)
+ {
+ if (throwOnBindFailure)
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ return null;
+ }
+ return runtimeMethodInfo.CreateDelegateWithoutSignatureValidation(type, target: null, isStatic: true, isOpen: true);
+ }
+
+ //
+ // Helper for the V1/V1.1 Delegate.CreateDelegate() api. These apis take method names rather than MethodInfo and only expect to create open static delegates
+ // or closed instance delegates. For backward compatibility, they don't allow relaxed signature matching (which could make the choice of target method ambiguous.)
+ //
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
+ Justification = "Analysis does not track annotations for RuntimeTypeInfo")]
+ private static RuntimeMethodInfo LookupMethodForCreateDelegate(RuntimeTypeInfo runtimeDelegateType, RuntimeTypeInfo containingType, string method, bool isStatic, bool ignoreCase)
+ {
+ Debug.Assert(runtimeDelegateType.IsDelegate);
+
+ BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.ExactBinding;
+ if (isStatic)
+ {
+ bindingFlags |= BindingFlags.Static;
+ }
+ else
+ {
+ bindingFlags |= BindingFlags.Instance | BindingFlags.DeclaredOnly;
+ }
+ if (ignoreCase)
+ {
+ bindingFlags |= BindingFlags.IgnoreCase;
+ }
+ RuntimeMethodInfo invokeMethod = runtimeDelegateType.GetInvokeMethod();
+ ReadOnlySpan parameters = invokeMethod.GetParametersAsSpan();
+ int numParameters = parameters.Length;
+ Type[] parameterTypes = new Type[numParameters];
+ for (int i = 0; i < numParameters; i++)
+ {
+ parameterTypes[i] = parameters[i].ParameterType;
+ }
+
+ Type? type = containingType.ToType();
+ while (type != null)
+ {
+ MethodInfo? methodInfo = type.GetMethod(method, 0, bindingFlags, parameterTypes);
+ if (methodInfo != null && methodInfo.ReturnType.Equals(invokeMethod.ReturnType))
+ return (RuntimeMethodInfo)methodInfo; // This cast is safe since we already verified that containingType is runtime implemented.
+
+ type = type.BaseType;
+ }
+ return null;
+ }
+
+ public static IntPtr GetFunctionPointer(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle)
+ {
+ MethodBase method = GetMethodFromHandle(runtimeMethodHandle, declaringTypeHandle);
+
+ switch (method)
+ {
+ case RuntimeMethodInfo methodInfo:
+ return methodInfo.LdFtnResult;
+ case RuntimeConstructorInfo constructorInfo:
+ return constructorInfo.LdFtnResult;
+ default:
+ Debug.Fail("RuntimeMethodHandle should only return a methodbase implemented by the runtime.");
+ throw new NotSupportedException();
+ }
+ }
+
+ public static void MakeTypedReference(object target, FieldInfo[] flds, out Type type, out int offset)
+ {
+ ArgumentNullException.ThrowIfNull(target);
+ ArgumentNullException.ThrowIfNull(flds);
+ if (flds.Length == 0)
+ throw new ArgumentException(SR.Arg_ArrayZeroError, nameof(flds));
+
+ offset = 0;
+ Type targetType = target.GetType();
+ for (int i = 0; i < flds.Length; i++)
+ {
+ if (!(flds[i] is RuntimeFieldInfo field))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeFieldInfo);
+ if (field.IsStatic)
+ throw new ArgumentException(SR.Argument_TypedReferenceInvalidField);
+
+ // For proper handling of Nullable don't change to something like 'IsAssignableFrom'
+ // Currently we can't make a TypedReference to fields of Nullable, which is fine.
+ Type declaringType = field.DeclaringType;
+ if (targetType != declaringType && !targetType.IsSubclassOf(declaringType))
+ throw new MissingMemberException(SR.MissingMemberTypeRef); // MissingMemberException is a strange exception to throw, but it is the compatible exception.
+
+ Type fieldType = field.FieldType;
+ if (i < (flds.Length - 1) && !fieldType.IsValueType)
+ throw new MissingMemberException(SR.MissingMemberNestErr); // MissingMemberException is a strange exception to throw, but it is the compatible exception.
+
+ targetType = fieldType;
+ offset = checked(offset + field.Offset);
+ }
+
+ type = targetType;
+ }
+
+ public static Assembly[] GetLoadedAssemblies() => RuntimeAssemblyInfo.GetLoadedAssemblies();
- public abstract IntPtr GetFunctionPointer(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle);
+ public static EnumInfo GetEnumInfo(Type type, Func create)
+ {
+ RuntimeTypeInfo runtimeType = type.ToRuntimeTypeInfo();
- public abstract void MakeTypedReference(object target, FieldInfo[] flds, out Type type, out int offset);
+ var info = runtimeType.GenericCache as EnumInfo;
+ if (info != null)
+ return info;
- public abstract Assembly[] GetLoadedAssemblies();
+ ReflectionCoreExecution.ExecutionEnvironment.GetEnumInfo(runtimeType.TypeHandle, out string[] unsortedNames, out object[] unsortedValues, out bool isFlags);
- public abstract EnumInfo GetEnumInfo(Type type, Func create);
+ // Call into IntrospectiveSort directly to avoid the Comparer.Default codepath.
+ // That codepath would bring functionality to compare everything that was ever allocated in the program.
+ ArraySortHelper