Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Ghiondea <ghiondea.alexandru@microsoft.com>2015-12-23 23:17:35 +0300
committerAlex Ghiondea <ghiondea.alexandru@microsoft.com>2015-12-23 23:17:35 +0300
commit54a7e4b76dd58797a26fcdc727f0ba296f6c367d (patch)
treee386d328900e2fecd62d5562cb2546f35db927a2 /src/System.Private.Reflection.Core
parenta4e8d45a352f5952912add6ee0391a4d8f201741 (diff)
While porting the library I ended up updating quite a few projects to make sure they continue to work.
There were a couple of changes to the build system that are included in this change: - The location of the tool to restore the packages is set to use dnu for now. - When restoring packages for the internal build we need to actually pass the right parameters to the build of the depproj There were a couple of places where we had some issues that I fixed while I was doing the port: - The compiler gave error messages about some method out parameters not being assigned. - There was one missing 'unsafe' modifier on an interop file - I had to pull in a 'debug' method temporarily in the ret build. This was needed because the debug build of CoreLib currently does not build with the 'DEBUG' define. [tfs-changeset: 1559864]
Diffstat (limited to 'src/System.Private.Reflection.Core')
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/AssemblyBinder.cs30
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs166
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs145
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/FieldAccessor.cs21
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs16
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs22
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ReflectionCoreExecution.cs93
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/FoundationTypes.cs34
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomain.cs114
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomainSetup.cs42
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ITraceableTypeMember.cs18
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Internal.cs256
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.Events.cs673
-rw-r--r--src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.cs32
-rw-r--r--src/System.Private.Reflection.Core/src/Resources/Resources.resx210
-rw-r--r--src/System.Private.Reflection.Core/src/Resources/Strings.resx210
-rw-r--r--src/System.Private.Reflection.Core/src/Resources/System.Private.Reflection.Core.rd.xml11
-rw-r--r--src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj143
-rw-r--r--src/System.Private.Reflection.Core/src/System/DBNull.cs33
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.StrongName.cs134
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.cs179
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameLexer.cs140
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameParser.cs230
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssembly.cs243
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyName.cs173
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs148
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeNormalCustomAttributeData.cs250
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs68
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs70
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/Dispenser.cs20
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs32
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs64
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs18
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs45
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs30
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs45
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatLatchesTypeInfosInsideTypes.cs30
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs36
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs3
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs47
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs260
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/LiteralFieldAccessor.cs43
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs256
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs405
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs614
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs548
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs80
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QHandles.cs193
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs161
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeNamespaceInfo.cs3
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeExtensions.cs36
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeUnifierEx.cs115
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs104
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeContext.cs43
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeExtensions.cs21
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs212
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs30
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs168
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs151
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodCommon.cs308
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs402
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs245
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs166
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs152
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs185
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs33
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs88
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs114
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs55
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs94
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs88
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs88
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs72
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs380
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Tracing/ReflectionEventSource.cs376
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs317
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs187
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs172
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs193
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs88
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs364
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs182
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs1003
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/TypeInfoCachedData.cs121
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs242
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs535
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs210
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterType.cs152
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForMethods.cs156
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForTypes.cs123
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeInspectionOnlyNamedType.cs197
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/ShadowRuntimeInspectionOnlyNamedType.cs43
92 files changed, 14848 insertions, 0 deletions
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/AssemblyBinder.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/AssemblyBinder.cs
new file mode 100644
index 000000000..d4601dbd5
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/AssemblyBinder.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Collections.Generic;
+using global::System.Reflection;
+using global::Internal.Metadata.NativeFormat;
+using global::System.Reflection.Runtime.General;
+
+namespace Internal.Reflection.Core
+{
+ //
+ // Implements the custom assembly binding policy for a Reflection domain. This gets called any time the domain needs
+ // to resolve an assembly name.
+ //
+ // If the binder cannot locate an assembly, it must return null and set "exception" to an exception object.
+ //
+ public abstract class AssemblyBinder
+ {
+ public abstract bool Bind(AssemblyName refName, out MetadataReader reader, out ScopeDefinitionHandle scopeDefinitionHandle, out IEnumerable<QScopeDefinition> overflowScopes, out Exception exception);
+
+ // This helper is a concession to the fact that third-party binders running on top of the Win8P surface area have no sensible way
+ // to perform this task due to the lack of a SetCulture() api on the AssemblyName class. Reflection.Core *is* able to do this
+ // thanks to the Internal.Reflection.Augment contract so we will expose this helper for the convenience of binders.
+ protected AssemblyName CreateAssemblyNameFromMetadata(MetadataReader reader, ScopeDefinitionHandle scopeDefinitionHandle)
+ {
+ return scopeDefinitionHandle.ToRuntimeAssemblyName(reader).ToAssemblyName();
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs
new file mode 100644
index 000000000..69e169449
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs
@@ -0,0 +1,166 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.TypeParsing;
+using global::System.Reflection.Runtime.CustomAttributes;
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace Internal.Reflection.Core.Execution
+{
+ //
+ // This singleton class implements the domain used for "execution" reflection objects, e.g. Types obtained from RuntimeTypeHandles.
+ // This class is only instantiated on Project N, as the desktop uses IRC only for LMR.
+ //
+ public sealed class ExecutionDomain : ReflectionDomain
+ {
+ internal ExecutionDomain(ReflectionDomainSetup executionDomainSetup, ExecutionEnvironment executionEnvironment)
+ : base(executionDomainSetup, 0)
+ {
+ this.ExecutionEnvironment = executionEnvironment;
+ }
+
+ //
+ // Retrieves a type by name. Helper to implement Type.GetType();
+ //
+ public Type GetType(String typeName, bool throwOnError, bool ignoreCase, IEnumerable<String> defaultAssemblyNames)
+ {
+ if (typeName == null)
+ throw new ArgumentNullException();
+
+ if (typeName.Length == 0)
+ {
+ if (throwOnError)
+ throw new TypeLoadException(SR.Arg_TypeLoadNullStr);
+ else
+ return null;
+ }
+
+ AssemblyQualifiedTypeName assemblyQualifiedTypeName;
+ try
+ {
+ assemblyQualifiedTypeName = TypeParser.ParseAssemblyQualifiedTypeName(typeName);
+ }
+ catch (ArgumentException)
+ {
+ // Input string was a syntactically invalid type name.
+ if (throwOnError)
+ throw;
+ return null;
+ }
+
+ if (assemblyQualifiedTypeName.AssemblyName != null)
+ {
+ defaultAssemblyNames = new String[] { null };
+ }
+
+ Exception lastTypeLoadException = null;
+ foreach (String assemblyName in defaultAssemblyNames)
+ {
+ RuntimeAssembly defaultAssembly;
+ if (assemblyName == null)
+ {
+ defaultAssembly = null;
+ }
+ else
+ {
+ RuntimeAssemblyName runtimeAssemblyName = AssemblyNameParser.Parse(assemblyName);
+ Exception e = RuntimeAssembly.TryGetRuntimeAssembly(this, runtimeAssemblyName, out defaultAssembly);
+ if (e != null)
+ continue; // A default assembly such as "System.Runtime" might not "exist" in an app that opts heavily out of pay-for-play metadata. Just go on to the next one.
+ }
+
+ RuntimeType result;
+ Exception typeLoadException = assemblyQualifiedTypeName.TryResolve(this, defaultAssembly, ignoreCase, out result);
+ if (typeLoadException == null)
+ return result;
+ lastTypeLoadException = typeLoadException;
+ }
+
+ if (throwOnError)
+ {
+ if (lastTypeLoadException == null)
+ throw new TypeLoadException(SR.Format(SR.TypeLoad_TypeNotFoundByGetType, typeName));
+ else
+ throw lastTypeLoadException;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ //
+ // Retrieves the MethodBase for a given method handle. Helper to implement Delegate.GetMethodInfo()
+ //
+ public MethodBase GetMethod(RuntimeTypeHandle declaringTypeHandle, MethodHandle methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
+ {
+ RuntimeType declaringType = ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(declaringTypeHandle);
+ RuntimeTypeInfo contextTypeInfo = declaringType.GetRuntimeTypeInfo();
+ RuntimeNamedTypeInfo definingTypeInfo = contextTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
+ MetadataReader reader = definingTypeInfo.Reader;
+ if (methodHandle.IsConstructor(reader))
+ {
+ return RuntimePlainConstructorInfo.GetRuntimePlainConstructorInfo(methodHandle, definingTypeInfo, contextTypeInfo);
+ }
+ else
+ {
+ RuntimeNamedMethodInfo runtimeNamedMethodInfo = RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(methodHandle, definingTypeInfo, contextTypeInfo);
+ if (!runtimeNamedMethodInfo.IsGenericMethod)
+ {
+ return runtimeNamedMethodInfo;
+ }
+ else
+ {
+ RuntimeType[] genericTypeArguments = new RuntimeType[genericMethodTypeArgumentHandles.Length];
+ for (int i = 0; i < genericMethodTypeArgumentHandles.Length; i++)
+ {
+ genericTypeArguments[i] = ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(genericMethodTypeArgumentHandles[i]);
+ }
+ return RuntimeConstructedGenericMethodInfo.GetRuntimeConstructedGenericMethodInfo(runtimeNamedMethodInfo, genericTypeArguments);
+ }
+ }
+ }
+
+ //
+ // Get or create a CustomAttributeData object for a specific type and arguments.
+ //
+ public CustomAttributeData GetCustomAttributeData(Type attributeType, IList<CustomAttributeTypedArgument> constructorArguments, IList<CustomAttributeNamedArgument> namedArguments)
+ {
+ RuntimeType runtimeAttributeType = attributeType as RuntimeType;
+ if (runtimeAttributeType == null)
+ throw new InvalidOperationException();
+ return new RuntimePseudoCustomAttributeData(runtimeAttributeType, constructorArguments, namedArguments);
+ }
+
+ //=======================================================================================
+ // Flotsam and jetsam.
+ //=======================================================================================
+ //
+ // ShadowTypes are a trick to make Types based on RuntimeTypeHandles "light up" on Project N when metadata and reflection are present.
+ // This is exposed on the execution domain only as it makes no sense for LMR types.
+ //
+ public Type CreateShadowRuntimeInspectionOnlyNamedTypeIfAvailable(RuntimeTypeHandle runtimeTypeHandle)
+ {
+ MetadataReader metadataReader;
+ TypeDefinitionHandle typeDefinitionHandle;
+
+ if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetMetadataForNamedType(runtimeTypeHandle, out metadataReader, out typeDefinitionHandle))
+ return null;
+ return new ShadowRuntimeInspectionOnlyNamedType(metadataReader, typeDefinitionHandle);
+ }
+
+ internal ExecutionEnvironment ExecutionEnvironment { get; private set; }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs
new file mode 100644
index 000000000..1b83aa1b7
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs
@@ -0,0 +1,145 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.IO;
+using global::System.Reflection;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using OpenMethodInvoker = global::System.Reflection.Runtime.MethodInfos.OpenMethodInvoker;
+
+namespace Internal.Reflection.Core.Execution
+{
+ //
+ // This class abstracts the underlying Redhawk (or whatever execution engine) runtime and exposes the services
+ // that I.R.Core.Execution needs.
+ //
+ public abstract class ExecutionEnvironment
+ {
+ //==============================================================================================
+ // Access to the underlying execution engine's object allocation routines.
+ //==============================================================================================
+ public abstract Object NewObject(RuntimeTypeHandle typeHandle);
+ public abstract Array NewArray(RuntimeTypeHandle typeHandleForArrayType, int count);
+ public abstract Array NewMultiDimArray(RuntimeTypeHandle typeHandleForArrayType, int[] lengths, int[] lowerBounds);
+
+ //==============================================================================================
+ // Execution engine policies.
+ //==============================================================================================
+
+ //
+ // This returns a generic type with one generic parameter (representing the array element type)
+ // whose base type and interface list determines what TypeInfo.BaseType and TypeInfo.ImplementedInterfaces
+ // return for types that return true for IsArray.
+ //
+ public abstract RuntimeTypeHandle ProjectionTypeForArrays { get; }
+ public abstract bool IsAssignableFrom(RuntimeTypeHandle dstType, RuntimeTypeHandle srcType);
+ public abstract bool TryGetBaseType(RuntimeTypeHandle typeHandle, out RuntimeTypeHandle baseTypeHandle);
+ public abstract IEnumerable<RuntimeTypeHandle> TryGetImplementedInterfaces(RuntimeTypeHandle typeHandle);
+ public abstract bool IsReflectionBlocked(RuntimeTypeHandle typeHandle);
+
+ //==============================================================================================
+ // Default Value support.
+ //==============================================================================================
+ public abstract bool GetDefaultValueIfAny(MetadataReader reader, ParameterHandle parameterHandle, Type declaredType, IEnumerable<CustomAttributeData> customAttributes, out Object defaultValue);
+ public abstract bool GetDefaultValueIfAny(MetadataReader reader, FieldHandle fieldHandle, Type declaredType, IEnumerable<CustomAttributeData> customAttributes, out Object defaultValue);
+ public abstract bool GetDefaultValueIfAny(MetadataReader reader, PropertyHandle propertyHandle, Type declaredType, IEnumerable<CustomAttributeData> customAttributes, out Object defaultValue);
+
+ //==============================================================================================
+ // Reflection Mapping Tables
+ //==============================================================================================
+ public abstract bool TryGetMetadataForNamedType(RuntimeTypeHandle runtimeTypeHandle, out MetadataReader metadataReader, out TypeDefinitionHandle typeDefHandle);
+ public abstract bool TryGetNamedTypeForMetadata(MetadataReader metadataReader, TypeDefinitionHandle typeDefHandle, out RuntimeTypeHandle runtimeTypeHandle);
+
+ public abstract bool TryGetTypeReferenceForNamedType(RuntimeTypeHandle runtimeTypeHandle, out MetadataReader metadataReader, out TypeReferenceHandle typeRefHandle);
+ public abstract bool TryGetNamedTypeForTypeReference(MetadataReader metadataReader, TypeReferenceHandle typeRefHandle, out RuntimeTypeHandle runtimeTypeHandle);
+
+ public abstract bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, out RuntimeTypeHandle arrayTypeHandle);
+ public abstract bool TryGetArrayTypeElementType(RuntimeTypeHandle arrayTypeHandle, out RuntimeTypeHandle elementTypeHandle);
+
+ public abstract bool TryGetMultiDimArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, int rank, out RuntimeTypeHandle arrayTypeHandle);
+ public abstract bool TryGetMultiDimArrayTypeElementType(RuntimeTypeHandle arrayTypeHandle, int rank, out RuntimeTypeHandle elementTypeHandle);
+
+ public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle pointerTypeHandle);
+ public abstract bool TryGetPointerTypeTargetType(RuntimeTypeHandle pointerTypeHandle, out RuntimeTypeHandle targetTypeHandle);
+
+ public abstract bool TryGetConstructedGenericTypeComponents(RuntimeTypeHandle runtimeTypeHandle, out RuntimeTypeHandle genericTypeDefinitionHandle, out RuntimeTypeHandle[] genericTypeArgumentHandles);
+ public abstract bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle);
+
+ public abstract bool TryGetMetadataNameForRuntimeTypeHandle(RuntimeTypeHandle rtth, out string name);
+
+ //==============================================================================================
+ // Invoke and field access support.
+ //==============================================================================================
+ public abstract MethodInvoker TryGetMethodInvoker(MetadataReader reader, RuntimeTypeHandle declaringTypeHandle, MethodHandle methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles);
+ public abstract FieldAccessor TryGetFieldAccessor(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle, FieldHandle fieldHandle);
+
+ //==============================================================================================
+ // Pseudo Custom Attributes
+ //==============================================================================================
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, ScopeDefinitionHandle scopeDefinitionHandle);
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle);
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, MethodHandle methodHandle, TypeDefinitionHandle declaringTypeHandle);
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, ParameterHandle parameterHandle, MethodHandle declaringMethodHandle);
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, FieldHandle fieldHandle, TypeDefinitionHandle declaringTypeHandle);
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, PropertyHandle propertyHandle, TypeDefinitionHandle declaringTypeHandle);
+ public abstract IEnumerable<CustomAttributeData> GetPsuedoCustomAttributes(MetadataReader reader, EventHandle eventHandle, TypeDefinitionHandle declaringTypeHandle);
+
+ //==============================================================================================
+ // RuntimeMethodHandle and RuntimeFieldHandle support.
+ //==============================================================================================
+ public abstract bool TryGetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles);
+ public abstract bool TryGetMethodFromHandleAndType(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle, out MethodHandle methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles);
+ public abstract bool TryGetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle);
+ public abstract bool TryGetFieldFromHandleAndType(RuntimeFieldHandle runtimeFieldHandle, RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle);
+
+
+ //==============================================================================================
+ // Manifest resource stream support.
+ //==============================================================================================
+ public abstract ManifestResourceInfo GetManifestResourceInfo(Assembly assembly, String resourceName);
+ public abstract String[] GetManifestResourceNames(Assembly assembly);
+ public abstract Stream GetManifestResourceStream(Assembly assembly, String name);
+
+ //==============================================================================================
+ // Other
+ //==============================================================================================
+ public abstract MethodInvoker GetSyntheticMethodInvoker(RuntimeTypeHandle thisType, RuntimeTypeHandle[] parameterTypes, InvokerOptions options, Func<Object, Object[], Object> invoker);
+ public abstract bool IsCOMObject(Type type);
+
+ //==============================================================================================
+ // Generic Virtual Method Support
+ //==============================================================================================
+ public abstract bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, ref RuntimeTypeHandle[] genericArguments, ref string methodName, ref IntPtr methodSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated);
+
+ //==============================================================================================
+ // Non-public methods
+ //==============================================================================================
+ internal MethodInvoker GetMethodInvoker(MetadataReader reader, RuntimeType declaringType, MethodHandle methodHandle, RuntimeType[] genericMethodTypeArguments, MemberInfo exceptionPertainant)
+ {
+ if (declaringType.InternalIsOpen)
+ return new OpenMethodInvoker();
+ for (int i = 0; i < genericMethodTypeArguments.Length; i++)
+ {
+ if (genericMethodTypeArguments[i].InternalIsOpen)
+ return new OpenMethodInvoker();
+ }
+
+ RuntimeTypeHandle typeDefinitionHandle = declaringType.TypeHandle;
+ RuntimeTypeHandle[] genericMethodTypeArgumentHandles = new RuntimeTypeHandle[genericMethodTypeArguments.Length];
+
+ for (int i = 0; i < genericMethodTypeArguments.Length; i++)
+ {
+ genericMethodTypeArgumentHandles[i] = genericMethodTypeArguments[i].TypeHandle;
+ }
+ MethodInvoker methodInvoker = TryGetMethodInvoker(reader, typeDefinitionHandle, methodHandle, genericMethodTypeArgumentHandles);
+ if (methodInvoker == null)
+ throw declaringType.GetReflectionDomain().CreateNonInvokabilityException(exceptionPertainant);
+ return methodInvoker;
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/FieldAccessor.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/FieldAccessor.cs
new file mode 100644
index 000000000..6faba1d4f
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/FieldAccessor.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace Internal.Reflection.Core.Execution
+{
+ //
+ // This class abstracts the underlying Redhawk (or whatever execution engine) runtime that sets and gets fields.
+ //
+ public abstract class FieldAccessor
+ {
+ protected FieldAccessor() { }
+ public abstract Object GetField(Object obj);
+ public abstract void SetField(Object obj, Object value);
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs
new file mode 100644
index 000000000..d011b22fe
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/InvokerOptions.cs
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+
+namespace Internal.Reflection.Core.Execution
+{
+ [Flags]
+ public enum InvokerOptions
+ {
+ None = 0x00000000,
+ AllowNullThis = 0x00000001, // Don't raise an exception if the "thisObject" parameter to Invoker is null.
+ DontWrapException = 0x00000002, // Don't wrap target exceptions in TargetInvocationException.
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs
new file mode 100644
index 000000000..67a3c6021
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/MethodInvoker.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+
+namespace Internal.Reflection.Core.Execution
+{
+ //
+ // This class polymorphically implements the MethodBase.Invoke() api and its close cousins. MethodInvokers are designed to be built once and cached
+ // for maximum Invoke() throughput.
+ //
+ public abstract class MethodInvoker
+ {
+ protected MethodInvoker() { }
+
+ public abstract Object Invoke(Object thisObject, Object[] arguments);
+ public abstract Delegate CreateDelegate(RuntimeTypeHandle delegateType, Object target, bool isStatic, bool isVirtual, bool isOpen);
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ReflectionCoreExecution.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ReflectionCoreExecution.cs
new file mode 100644
index 000000000..4552d30bc
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ReflectionCoreExecution.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+// Internal.Reflection.Core.Execution
+// -------------------------------------------------
+// Why does this exist?:
+// This contract augments Internal.Reflection.Core and adds the ability
+// to create a single "execution domain" which allows creation of
+// a Win8P-style "invokable" Reflection object tree. Reflection objects
+// in this domain unify with the underlying execution engine's
+// native type artifacts (i.e. typeof() and Object.GetType() returns
+// types in this domain.)
+//
+// Implemented by:
+// Reflection.Core.dll on RH and desktop.
+//
+// Consumed by:
+// RH for "classic reflection".
+// Not used on desktop.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+
+using global::Internal.Metadata.NativeFormat;
+using global::Internal.Reflection.Augments;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace Internal.Reflection.Core.Execution
+{
+ public static class ReflectionCoreExecution
+ {
+ //
+ // One time initialization to supply the information needed to initialize the default domain and the
+ // the execution environment.
+ //
+ // Remarks:
+ // This design intentionally restricts you to one ExecutionEnvironment per side-by-side runtime in a process.
+ // Aside from the dubious value of allowing multiple executionEnvironments, there is no good way to
+ // for this scenario:
+ //
+ // typeof(Foo).GetTypeInfo()
+ //
+ // to "lookup" a domain in order to map the RuntimeTypeHandle to a specific ExecutionEnvironment.
+ //
+ public static void InitializeExecutionDomain(ReflectionDomainSetup executionDomainSetup, ExecutionEnvironment executionEnvironment)
+ {
+ ExecutionDomain executionDomain = new ExecutionDomain(executionDomainSetup, executionEnvironment);
+ //@todo: This check has a race window but since this is a private api targeted by the toolchain, perhaps this is not so critical.
+ if (_executionDomain != null)
+ throw new InvalidOperationException(); // Multiple Initializes not allowed.
+ _executionDomain = executionDomain;
+
+ ReflectionCoreCallbacks reflectionCallbacks = new ReflectionCoreCallbacksImplementation();
+ ReflectionAugments.Initialize(reflectionCallbacks);
+ return;
+ }
+
+ //
+ // The ExecutionDomain is the domain that hosts reflection entities created by these constructs:
+ //
+ // Type.GetTypeFromHandle() ( i.e. typeof() )
+ // Object.GetType()
+ // Type.GetType(String name, [bool throwOnError])
+ // Assembly.Load(AssemblyName)
+ //
+ // There is only one ExecutionDomain and it is initialized by the Initialize() method. It is the only domain capable
+ // of supporting invocation.
+ //
+ public static ExecutionDomain ExecutionDomain
+ {
+ get
+ {
+ return _executionDomain;
+ }
+ }
+
+ internal static ExecutionEnvironment ExecutionEnvironment
+ {
+ get
+ {
+ return ExecutionDomain.ExecutionEnvironment;
+ }
+ }
+
+ private volatile static ExecutionDomain _executionDomain;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/FoundationTypes.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/FoundationTypes.cs
new file mode 100644
index 000000000..fe87cf128
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/FoundationTypes.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+
+namespace Internal.Reflection.Core
+{
+ // This class serves up a small set of foundation types that have special meaning to Reflection.
+ public abstract class FoundationTypes
+ {
+ public abstract Type SystemObject { get; }
+ public abstract Type SystemValueType { get; }
+ public abstract Type SystemEnum { get; }
+ public abstract Type SystemVoid { get; }
+ public abstract Type SystemArray { get; }
+ public abstract Type SystemString { get; }
+ public abstract Type SystemType { get; }
+ public abstract Type SystemBoolean { get; }
+ public abstract Type SystemChar { get; }
+ public abstract Type SystemSByte { get; }
+ public abstract Type SystemByte { get; }
+ public abstract Type SystemInt16 { get; }
+ public abstract Type SystemUInt16 { get; }
+ public abstract Type SystemInt32 { get; }
+ public abstract Type SystemUInt32 { get; }
+ public abstract Type SystemInt64 { get; }
+ public abstract Type SystemUInt64 { get; }
+ public abstract Type SystemIntPtr { get; }
+ public abstract Type SystemUIntPtr { get; }
+ public abstract Type SystemSingle { get; }
+ public abstract Type SystemDouble { get; }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomain.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomain.cs
new file mode 100644
index 000000000..045c4fd77
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomain.cs
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//Internal.Reflection.Core
+//-------------------------------------------------
+// Why does this exist?:
+// This contract exposes the service
+// of consuming metadata (through the S.R.M api) and creating
+// an Win8P-style "browse-only" Reflection object tree on top of it.
+//
+// The contract allows the creation of multiple "reflection domains" with
+// custom assembly binding policies.
+//
+//
+// Implemented by:
+// Reflection.Core.dll on RH and desktop.
+//
+// Consumed by:
+// LMR on RH and desktop.
+// "Classic reflection" on RH.
+//
+//
+
+using global::System;
+using global::System.Reflection;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+
+namespace Internal.Reflection.Core
+{
+ //=====================================================================================================================================
+ // A Reflection domain is an independent "universe" of loaded reflection types. Reflection entities cannot exist in multiple domains,
+ // nor at they allowed to intermix.
+ //
+ // Reflection domains are "browse-only" - attempts to invoke, instantiate or set or get fields and properties all fail.
+ //
+ // Each reflection domain determines its own rules for resolving assemblies and the identity of the "core" assembly (typically
+ // mscorlib.dll.)
+ //=====================================================================================================================================
+ public class ReflectionDomain
+ {
+ public ReflectionDomain(ReflectionDomainSetup setup)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public Assembly LoadAssembly(AssemblyName refName)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public Exception CreateMissingMetadataException(Type pertainant)
+ {
+ return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant);
+ }
+
+ public Exception CreateMissingMetadataException(TypeInfo pertainant)
+ {
+ return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant);
+ }
+
+ public Exception CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName)
+ {
+ return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant, nestedTypeName);
+ }
+
+ public Exception CreateNonInvokabilityException(MemberInfo pertainant)
+ {
+ return this.ReflectionDomainSetup.CreateNonInvokabilityException(pertainant);
+ }
+
+
+ // This private constructor exists as a temporary measure so that we can create Execution domains without enabling the
+ // general ReflectionDomain case.
+ internal ReflectionDomain(ReflectionDomainSetup setup, int meaningless)
+ {
+ this.ReflectionDomainSetup = setup;
+ }
+
+ internal ReflectionDomainSetup ReflectionDomainSetup { get; private set; }
+
+ internal FoundationTypes FoundationTypes
+ {
+ get
+ {
+ return this.ReflectionDomainSetup.FoundationTypes;
+ }
+ }
+
+ internal IEnumerable<Type> PrimitiveTypes
+ {
+ get
+ {
+ FoundationTypes foundationTypes = this.FoundationTypes;
+ return new Type[]
+ {
+ foundationTypes.SystemBoolean,
+ foundationTypes.SystemChar,
+ foundationTypes.SystemSByte,
+ foundationTypes.SystemByte,
+ foundationTypes.SystemInt16,
+ foundationTypes.SystemUInt16,
+ foundationTypes.SystemInt32,
+ foundationTypes.SystemUInt32,
+ foundationTypes.SystemInt64,
+ foundationTypes.SystemUInt64,
+ foundationTypes.SystemSingle,
+ foundationTypes.SystemDouble,
+ foundationTypes.SystemIntPtr,
+ foundationTypes.SystemUIntPtr,
+ };
+ }
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomainSetup.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomainSetup.cs
new file mode 100644
index 000000000..d9b88686f
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Core/ReflectionDomainSetup.cs
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//Internal.Reflection.Core
+//-------------------------------------------------
+// Why does this exist?:
+// This contract exposes the service
+// of consuming metadata (through the S.R.M api) and creating
+// an Win8P-style "browse-only" Reflection object tree on top of it.
+//
+// The contract allows the creation of multiple "reflection domains" with
+// custom assembly binding policies.
+//
+//
+// Implemented by:
+// Reflection.Core.dll on RH and desktop.
+//
+// Consumed by:
+// LMR on RH and desktop.
+// "Classic reflection" on RH.
+//
+//
+
+using global::System;
+using global::System.Reflection;
+using global::System.Reflection.Runtime.General;
+
+namespace Internal.Reflection.Core
+{
+ //=====================================================================================================================================
+ // This object encapsulates the customization parameters for Reflection domains.
+ //=====================================================================================================================================
+ public abstract class ReflectionDomainSetup
+ {
+ protected ReflectionDomainSetup() { }
+ public abstract AssemblyBinder AssemblyBinder { get; }
+ public abstract FoundationTypes FoundationTypes { get; }
+ public abstract Exception CreateMissingMetadataException(TypeInfo pertainant);
+ public abstract Exception CreateMissingMetadataException(Type pertainant);
+ public abstract Exception CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName);
+ public abstract Exception CreateNonInvokabilityException(MemberInfo pertainant);
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ITraceableTypeMember.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ITraceableTypeMember.cs
new file mode 100644
index 000000000..082ec20ca
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ITraceableTypeMember.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+
+namespace Internal.Reflection.Tracing
+{
+ internal interface ITraceableTypeMember
+ {
+ // Returns the Name value *without recursing into the public Name implementation.*
+ String MemberName { get; }
+
+ // Returns the DeclaringType value *without recursing into the public DeclaringType implementation.*
+ Type ContainingType { get; }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Internal.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Internal.cs
new file mode 100644
index 000000000..fca49f7c7
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Internal.cs
@@ -0,0 +1,256 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Text;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace Internal.Reflection.Tracing
+{
+ public static partial class ReflectionTrace
+ {
+ //==============================================================================
+ // Returns the type name to emit into the ETW record.
+ //
+ // - If it returns null, skip writing the ETW record. Null returns can happen
+ // for the following reasons:
+ // - Missing metadata
+ // - Open type (no need to trace these - open type creations always succeed)
+ // - Third-party-implemented Types.
+ //
+ // The implementation does a reasonable-effort to avoid MME's to avoid an annoying
+ // debugger experience. However, some MME's will still get caught by the try/catch.
+ //
+ // - The format happens to match what the AssemblyQualifiedName property returns
+ // but we cannot invoke that here due to the risk of infinite recursion.
+ // The implementation must be very careful what it calls.
+ //==============================================================================
+ private static String NameString(this Type type)
+ {
+ try
+ {
+ return type.AssemblyQualifiedTypeName();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ //==============================================================================
+ // Returns the assembly name to emit into the ETW record.
+ //==============================================================================
+ private static String NameString(this Assembly assembly)
+ {
+ try
+ {
+ RuntimeAssembly runtimeAssembly = assembly as RuntimeAssembly;
+ if (runtimeAssembly == null)
+ return null;
+ return runtimeAssembly.Scope.Handle.ToRuntimeAssemblyName(runtimeAssembly.Scope.Reader).FullName;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ //==============================================================================
+ // Returns the custom attribute type name to emit into the ETW record.
+ //==============================================================================
+ private static String AttributeTypeNameString(this CustomAttributeData customAttributeData)
+ {
+ try
+ {
+ RuntimeCustomAttributeData runtimeCustomAttributeData = customAttributeData as RuntimeCustomAttributeData;
+ if (runtimeCustomAttributeData == null)
+ return null;
+ return runtimeCustomAttributeData.AttributeType.NameString();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ //==============================================================================
+ // Returns the declaring type name (without calling MemberInfo.DeclaringType) to emit into the ETW record.
+ //==============================================================================
+ private static String DeclaringTypeNameString(this MemberInfo memberInfo)
+ {
+ try
+ {
+ ITraceableTypeMember traceableTypeMember = memberInfo as ITraceableTypeMember;
+ if (traceableTypeMember == null)
+ return null;
+ return traceableTypeMember.ContainingType.NameString();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ //==============================================================================
+ // Returns the MemberInfo.Name value (without calling MemberInfo.Name) to emit into the ETW record.
+ //==============================================================================
+ private static String NameString(this MemberInfo memberInfo)
+ {
+ try
+ {
+ TypeInfo typeInfo = memberInfo as TypeInfo;
+ if (typeInfo != null)
+ return typeInfo.AsType().NameString();
+
+ ITraceableTypeMember traceableTypeMember = memberInfo as ITraceableTypeMember;
+ if (traceableTypeMember == null)
+ return null;
+ return traceableTypeMember.MemberName;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ //==============================================================================
+ // Append type argument strings.
+ //==============================================================================
+ private static String GenericTypeArgumentStrings(this Type[] typeArguments)
+ {
+ if (typeArguments == null)
+ return null;
+ String s = "";
+ foreach (Type typeArgument in typeArguments)
+ {
+ String typeArgumentString = typeArgument.NameString();
+ if (typeArgumentString == null)
+ return null;
+ s += "@" + typeArgumentString;
+ }
+ return s;
+ }
+
+ private static String NonQualifiedTypeName(this Type type)
+ {
+ RuntimeType runtimeType = type as RuntimeType;
+ if (runtimeType == null)
+ return null;
+
+ if (runtimeType.HasElementType)
+ {
+ String elementTypeName = runtimeType.InternalRuntimeElementType.NonQualifiedTypeName();
+ if (elementTypeName == null)
+ return null;
+ String suffix;
+ if (runtimeType.IsArray)
+ {
+ int rank = runtimeType.GetArrayRank();
+ if (rank == 1)
+ suffix = "[" + (runtimeType.InternalIsMultiDimArray ? "*" : "") + "]";
+ else
+ suffix = "[" + new String(',', rank - 1) + "]";
+ }
+ else if (runtimeType.IsByRef)
+ suffix = "&";
+ else if (runtimeType.IsPointer)
+ suffix = "*";
+ else
+ return null;
+
+ return elementTypeName + suffix;
+ }
+ else if (runtimeType.IsGenericParameter)
+ {
+ return null;
+ }
+ else if (runtimeType.IsConstructedGenericType)
+ {
+ StringBuilder sb = new StringBuilder();
+ String genericTypeDefinitionTypeName = runtimeType.GetGenericTypeDefinition().NonQualifiedTypeName();
+ if (genericTypeDefinitionTypeName == null)
+ return null;
+ sb.Append(genericTypeDefinitionTypeName);
+ sb.Append("[");
+ String sep = "";
+ foreach (RuntimeType ga in runtimeType.InternalRuntimeGenericTypeArguments)
+ {
+ String gaTypeName = ga.AssemblyQualifiedTypeName();
+ if (gaTypeName == null)
+ return null;
+ sb.Append(sep + "[" + gaTypeName + "]");
+ sep = ",";
+ }
+ sb.Append("]");
+
+ return sb.ToString();
+ }
+ else
+ {
+ RuntimeNamedTypeInfo runtimeNamedTypeInfo = type.GetTypeInfo() as RuntimeNamedTypeInfo;
+ if (runtimeNamedTypeInfo == null)
+ return null;
+ MetadataReader reader = runtimeNamedTypeInfo.Reader;
+
+ String s = "";
+ TypeDefinitionHandle typeDefinitionHandle = runtimeNamedTypeInfo.TypeDefinitionHandle;
+ NamespaceDefinitionHandle namespaceDefinitionHandle;
+ do
+ {
+ TypeDefinition typeDefinition = typeDefinitionHandle.GetTypeDefinition(reader);
+ String name = typeDefinition.Name.GetString(reader);
+ if (s == "")
+ s = name;
+ else
+ s = name + "+" + s;
+ namespaceDefinitionHandle = typeDefinition.NamespaceDefinition;
+ typeDefinitionHandle = typeDefinition.EnclosingType;
+ }
+ while (!typeDefinitionHandle.IsNull(reader));
+
+ NamespaceChain namespaceChain = new NamespaceChain(reader, namespaceDefinitionHandle);
+ String ns = namespaceChain.NameSpace;
+ if (ns != null)
+ s = ns + "." + s;
+ return s;
+ }
+ }
+
+ private static String AssemblyQualifiedTypeName(this Type type)
+ {
+ RuntimeType runtimeType = type as RuntimeType;
+ if (runtimeType == null)
+ return null;
+ String nonqualifiedTypeName = runtimeType.NonQualifiedTypeName();
+ if (nonqualifiedTypeName == null)
+ return null;
+ String assemblyName = runtimeType.ContainingAssemblyName();
+ if (assemblyName == null)
+ return assemblyName;
+ return nonqualifiedTypeName + ", " + assemblyName;
+ }
+
+ private static String ContainingAssemblyName(this Type type)
+ {
+ RuntimeType runtimeType = type as RuntimeType;
+ if (runtimeType == null)
+ return null;
+ RuntimeTypeInfo runtimeTypeInfo = runtimeType.GetRuntimeTypeInfo<RuntimeTypeInfo>();
+ if (runtimeTypeInfo is RuntimeNoMetadataNamedTypeInfo)
+ return null;
+ return runtimeTypeInfo.Assembly.NameString();
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.Events.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.Events.cs
new file mode 100644
index 000000000..3ba3b1a2c
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.Events.cs
@@ -0,0 +1,673 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using ReflectionEventSource = global::System.Reflection.Runtime.Tracing.ReflectionEventSource;
+
+namespace Internal.Reflection.Tracing
+{
+ //
+ // The individual event methods. These are in a separate file to allow them to be tool-generated.
+ //
+ public static partial class ReflectionTrace
+ {
+ public static void Type_MakeGenericType(Type type, Type[] typeArguments)
+ {
+ String typeName = type.NameString();
+ if (typeName == null)
+ return;
+ String typeArgumentStrings = typeArguments.GenericTypeArgumentStrings();
+ if (typeArgumentStrings == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakeGenericType(typeName, typeArgumentStrings);
+ }
+
+ public static void Type_MakeArrayType(Type type)
+ {
+ String typeName = type.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakeArrayType(typeName);
+ }
+
+ public static void Type_FullName(Type type)
+ {
+ String typeName = type.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_FullName(typeName);
+ }
+
+ public static void Type_Namespace(Type type)
+ {
+ String typeName = type.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_Namespace(typeName);
+ }
+
+ public static void Type_AssemblyQualifiedName(Type type)
+ {
+ String typeName = type.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_AssemblyQualifiedName(typeName);
+ }
+
+ public static void Type_Name(Type type)
+ {
+ String typeName = type.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_Name(typeName);
+ }
+
+ public static void TypeInfo_CustomAttributes(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_CustomAttributes(typeName);
+ }
+
+ public static void TypeInfo_Name(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_Name(typeName);
+ }
+
+ public static void TypeInfo_BaseType(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_BaseType(typeName);
+ }
+
+ public static void TypeInfo_DeclaredConstructors(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredConstructors(typeName);
+ }
+
+ public static void TypeInfo_DeclaredEvents(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredEvents(typeName);
+ }
+
+ public static void TypeInfo_DeclaredFields(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredFields(typeName);
+ }
+
+ public static void TypeInfo_DeclaredMembers(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredMembers(typeName);
+ }
+
+ public static void TypeInfo_DeclaredMethods(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredMethods(typeName);
+ }
+
+ public static void TypeInfo_DeclaredNestedTypes(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredNestedTypes(typeName);
+ }
+
+ public static void TypeInfo_DeclaredProperties(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaredProperties(typeName);
+ }
+
+ public static void TypeInfo_DeclaringMethod(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_DeclaringMethod(typeName);
+ }
+
+ public static void TypeInfo_FullName(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_FullName(typeName);
+ }
+
+ public static void TypeInfo_AssemblyQualifiedName(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_AssemblyQualifiedName(typeName);
+ }
+
+ public static void TypeInfo_Namespace(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_Namespace(typeName);
+ }
+
+ public static void TypeInfo_GetDeclaredEvent(TypeInfo typeInfo, String eventName)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_GetDeclaredEvent(typeName, eventName);
+ }
+
+ public static void TypeInfo_GetDeclaredField(TypeInfo typeInfo, String fieldName)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ if (fieldName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_GetDeclaredField(typeName, fieldName);
+ }
+
+ public static void TypeInfo_GetDeclaredMethod(TypeInfo typeInfo, String methodName)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_GetDeclaredMethod(typeName, methodName);
+ }
+
+ public static void TypeInfo_GetDeclaredProperty(TypeInfo typeInfo, String propertyName)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_GetDeclaredProperty(typeName, propertyName);
+ }
+
+ public static void TypeInfo_MakeArrayType(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakeArrayType(typeName);
+ }
+
+ public static void TypeInfo_MakeArrayType(TypeInfo typeInfo, int rank)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakeArrayType(typeName);
+ }
+
+ public static void TypeInfo_MakeByRefType(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakeByRefType(typeName);
+ }
+
+ public static void TypeInfo_MakeGenericType(TypeInfo typeInfo, Type[] typeArguments)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ String typeArgumentStrings = typeArguments.GenericTypeArgumentStrings();
+ if (typeArgumentStrings == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakeGenericType(typeName, typeArgumentStrings);
+ }
+
+ public static void TypeInfo_MakePointerType(TypeInfo typeInfo)
+ {
+ String typeName = typeInfo.NameString();
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.TypeInfo_MakePointerType(typeName);
+ }
+
+ public static void Assembly_DefinedTypes(Assembly assembly)
+ {
+ String assemblyName = assembly.NameString();
+ if (assemblyName == null)
+ return;
+ ReflectionEventSource.Log.Assembly_DefinedTypes(assemblyName);
+ }
+
+ public static void Assembly_GetType(Assembly assembly, String typeName)
+ {
+ String assemblyName = assembly.NameString();
+ if (assemblyName == null)
+ return;
+ if (typeName == null)
+ return;
+ ReflectionEventSource.Log.Assembly_GetType(assemblyName, typeName);
+ }
+
+ public static void Assembly_CustomAttributes(Assembly assembly)
+ {
+ String assemblyName = assembly.NameString();
+ if (assemblyName == null)
+ return;
+ ReflectionEventSource.Log.Assembly_CustomAttributes(assemblyName);
+ }
+
+ public static void Assembly_FullName(Assembly assembly)
+ {
+ String assemblyName = assembly.NameString();
+ if (assemblyName == null)
+ return;
+ ReflectionEventSource.Log.Assembly_FullName(assemblyName);
+ }
+
+ public static void Assembly_GetName(Assembly assembly)
+ {
+ String assemblyName = assembly.NameString();
+ if (assemblyName == null)
+ return;
+ ReflectionEventSource.Log.Assembly_GetName(assemblyName);
+ }
+
+ public static void CustomAttributeData_ConstructorArguments(CustomAttributeData customAttributeData)
+ {
+ String attributeTypeName = customAttributeData.AttributeTypeNameString();
+ if (attributeTypeName == null)
+ return;
+ ReflectionEventSource.Log.CustomAttributeData_ConstructorArguments(attributeTypeName);
+ }
+
+ public static void CustomAttributeData_NamedArguments(CustomAttributeData customAttributeData)
+ {
+ String attributeTypeName = customAttributeData.AttributeTypeNameString();
+ if (attributeTypeName == null)
+ return;
+ ReflectionEventSource.Log.CustomAttributeData_NamedArguments(attributeTypeName);
+ }
+
+ public static void EventInfo_AddMethod(EventInfo eventInfo)
+ {
+ String declaringTypeName = eventInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String eventName = eventInfo.NameString();
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.EventInfo_AddMethod(declaringTypeName, eventName);
+ }
+
+ public static void EventInfo_RaiseMethod(EventInfo eventInfo)
+ {
+ String declaringTypeName = eventInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String eventName = eventInfo.NameString();
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.EventInfo_RaiseMethod(declaringTypeName, eventName);
+ }
+
+ public static void EventInfo_RemoveMethod(EventInfo eventInfo)
+ {
+ String declaringTypeName = eventInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String eventName = eventInfo.NameString();
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.EventInfo_RemoveMethod(declaringTypeName, eventName);
+ }
+
+ public static void EventInfo_CustomAttributes(EventInfo eventInfo)
+ {
+ String declaringTypeName = eventInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String eventName = eventInfo.NameString();
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.EventInfo_CustomAttributes(declaringTypeName, eventName);
+ }
+
+ public static void EventInfo_Name(EventInfo eventInfo)
+ {
+ String declaringTypeName = eventInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String eventName = eventInfo.NameString();
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.EventInfo_Name(declaringTypeName, eventName);
+ }
+
+ public static void EventInfo_DeclaringType(EventInfo eventInfo)
+ {
+ String declaringTypeName = eventInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String eventName = eventInfo.NameString();
+ if (eventName == null)
+ return;
+ ReflectionEventSource.Log.EventInfo_DeclaringType(declaringTypeName, eventName);
+ }
+
+ public static void FieldInfo_SetValue(FieldInfo fieldInfo, Object obj, Object value)
+ {
+ String declaringTypeName = fieldInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String fieldName = fieldInfo.NameString();
+ if (fieldName == null)
+ return;
+ ReflectionEventSource.Log.FieldInfo_SetValue(declaringTypeName, fieldName);
+ }
+
+ public static void FieldInfo_GetValue(FieldInfo fieldInfo, Object obj)
+ {
+ String declaringTypeName = fieldInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String fieldName = fieldInfo.NameString();
+ if (fieldName == null)
+ return;
+ ReflectionEventSource.Log.FieldInfo_GetValue(declaringTypeName, fieldName);
+ }
+
+ public static void FieldInfo_CustomAttributes(FieldInfo fieldInfo)
+ {
+ String declaringTypeName = fieldInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String fieldName = fieldInfo.NameString();
+ if (fieldName == null)
+ return;
+ ReflectionEventSource.Log.FieldInfo_CustomAttributes(declaringTypeName, fieldName);
+ }
+
+ public static void FieldInfo_Name(FieldInfo fieldInfo)
+ {
+ String declaringTypeName = fieldInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String fieldName = fieldInfo.NameString();
+ if (fieldName == null)
+ return;
+ ReflectionEventSource.Log.FieldInfo_Name(declaringTypeName, fieldName);
+ }
+
+ public static void FieldInfo_DeclaringType(FieldInfo fieldInfo)
+ {
+ String declaringTypeName = fieldInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String fieldName = fieldInfo.NameString();
+ if (fieldName == null)
+ return;
+ ReflectionEventSource.Log.FieldInfo_DeclaringType(declaringTypeName, fieldName);
+ }
+
+ public static void MethodBase_CustomAttributes(MethodBase methodBase)
+ {
+ String declaringTypeName = methodBase.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodBase.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodBase_CustomAttributes(declaringTypeName, methodName);
+ }
+
+ public static void MethodBase_Name(MethodBase methodBase)
+ {
+ String declaringTypeName = methodBase.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodBase.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodBase_Name(declaringTypeName, methodName);
+ }
+
+ public static void MethodBase_DeclaringType(MethodBase methodBase)
+ {
+ String declaringTypeName = methodBase.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodBase.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodBase_DeclaringType(declaringTypeName, methodName);
+ }
+
+ public static void MethodBase_GetParameters(MethodBase methodBase)
+ {
+ String declaringTypeName = methodBase.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodBase.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodBase_GetParameters(declaringTypeName, methodName);
+ }
+
+ public static void ConstructorInfo_Invoke(ConstructorInfo constructor, Object[] parameters)
+ {
+ String declaringTypeName = constructor.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = constructor.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodBase_Invoke(declaringTypeName, methodName);
+ }
+
+ public static void MethodBase_Invoke(MethodBase methodBase, Object obj, Object[] parameters)
+ {
+ String declaringTypeName = methodBase.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodBase.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodBase_Invoke(declaringTypeName, methodName);
+ }
+
+ public static void MethodInfo_ReturnParameter(MethodInfo methodInfo)
+ {
+ String declaringTypeName = methodInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodInfo.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodInfo_ReturnParameter(declaringTypeName, methodName);
+ }
+
+ public static void MethodInfo_ReturnType(MethodInfo methodInfo)
+ {
+ String declaringTypeName = methodInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodInfo.NameString();
+ if (methodName == null)
+ return;
+ ReflectionEventSource.Log.MethodInfo_ReturnType(declaringTypeName, methodName);
+ }
+
+ public static void MethodInfo_MakeGenericMethod(MethodInfo methodInfo, Type[] typeArguments)
+ {
+ String declaringTypeName = methodInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodInfo.NameString();
+ if (methodName == null)
+ return;
+ String typeArgumentStrings = typeArguments.GenericTypeArgumentStrings();
+ if (typeArgumentStrings == null)
+ return;
+ ReflectionEventSource.Log.MethodInfo_MakeGenericMethod(declaringTypeName, methodName, typeArgumentStrings);
+ }
+
+ public static void MethodInfo_CreateDelegate(MethodInfo methodInfo, Type delegateType)
+ {
+ String declaringTypeName = methodInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodInfo.NameString();
+ if (methodName == null)
+ return;
+ String delegateTypeName = delegateType.NameString();
+ if (delegateType == null)
+ return;
+ ReflectionEventSource.Log.MethodInfo_CreateDelegate(declaringTypeName, methodName, delegateTypeName);
+ }
+
+ public static void MethodInfo_CreateDelegate(MethodInfo methodInfo, Type delegateType, Object target)
+ {
+ String declaringTypeName = methodInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String methodName = methodInfo.NameString();
+ if (methodName == null)
+ return;
+ String delegateTypeName = delegateType.NameString();
+ if (delegateType == null)
+ return;
+ ReflectionEventSource.Log.MethodInfo_CreateDelegate(declaringTypeName, methodName, delegateTypeName);
+ }
+
+ public static void PropertyInfo_GetValue(PropertyInfo propertyInfo, Object obj, Object[] index)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_GetValue(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_SetValue(PropertyInfo propertyInfo, Object obj, Object value, Object[] index)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_SetValue(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_GetMethod(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_GetMethod(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_SetMethod(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_SetMethod(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_GetConstantValue(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_GetConstantValue(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_PropertyType(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_PropertyType(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_CustomAttributes(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_CustomAttributes(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_Name(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_Name(declaringTypeName, propertyName);
+ }
+
+ public static void PropertyInfo_DeclaringType(PropertyInfo propertyInfo)
+ {
+ String declaringTypeName = propertyInfo.DeclaringTypeNameString();
+ if (declaringTypeName == null)
+ return;
+ String propertyName = propertyInfo.NameString();
+ if (propertyName == null)
+ return;
+ ReflectionEventSource.Log.PropertyInfo_DeclaringType(declaringTypeName, propertyName);
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.cs b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.cs
new file mode 100644
index 000000000..be029fe19
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Internal/Reflection/Tracing/ReflectionTrace.Public.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Runtime.CompilerServices;
+
+using ReflectionEventSource = global::System.Reflection.Runtime.Tracing.ReflectionEventSource;
+
+namespace Internal.Reflection.Tracing
+{
+ [DeveloperExperienceModeOnly]
+ public static partial class ReflectionTrace
+ {
+ public static bool Enabled
+ {
+ get
+ {
+ return ReflectionEventSource.IsInitialized && ReflectionEventSource.Log.IsEnabled();
+ }
+ }
+
+ public static String GetTraceString(this TypeInfo typeInfo)
+ {
+ return typeInfo.NameString();
+ }
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/Resources/Resources.resx b/src/System.Private.Reflection.Core/src/Resources/Resources.resx
new file mode 100644
index 000000000..f2bea8235
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Resources/Resources.resx
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Bif_InvalidMetadata" xml:space="preserve">
+ <value>A problem was found in this image's metadata.</value>
+ </data>
+ <data name="Acc_CreateAbstEx" xml:space="preserve">
+ <value>Cannot create an instance of {0} because it is an abstract class.</value>
+ </data>
+ <data name="Acc_NotClassInit" xml:space="preserve">
+ <value>Type initializer was not callable.</value>
+ </data>
+ <data name="Acc_ReadOnly" xml:space="preserve">
+ <value>Cannot set a constant field.</value>
+ </data>
+ <data name="Arg_NotGenericMethodDefinition" xml:space="preserve">
+ <value>{0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.</value>
+ </data>
+ <data name="Arg_NotGenericParameter" xml:space="preserve">
+ <value>Method may only be called on a Type for which Type.IsGenericParameter is true.</value>
+ </data>
+ <data name="Arg_TypeLoadNullStr" xml:space="preserve">
+ <value>A null or zero length string does not represent a valid Type.</value>
+ </data>
+ <data name="Argument_NotEnoughGenArguments" xml:space="preserve">
+ <value>The type or method has {1} generic parameter(s), but {0} generic argument(s) were provided. A generic argument must be provided for each generic parameter.</value>
+ </data>
+ <data name="Reflection_CustomReflectionObjectsNotSupported" xml:space="preserve">
+ <value>The object '{0}' was created by a custom ReflectionContext and cannot be used here.</value>
+ </data>
+ <data name="TypeLoad_TypeNotFoundByGetType" xml:space="preserve">
+ <value>The type '{0}' cannot be found.</value>
+ </data>
+ <data name="TypeLoad_TypeNotFound" xml:space="preserve">
+ <value>The type '{0}' cannot be found in the metadata for '{1}'.</value>
+ </data>
+ <data name="TypeLoad_BadEscape" xml:space="preserve">
+ <value>An invalid escape sequence was found inside a type name.</value>
+ </data>
+ <data name="FileNotFound_AssemblyNotFound" xml:space="preserve">
+ <value>Cannot load assembly '{0}'. No metadata found for this assembly.</value>
+ </data>
+ <data name="Format_StringZeroLength" xml:space="preserve">
+ <value>String cannot have zero length.</value>
+ </data>
+ <data name="Arg_HTCapacityOverflow" xml:space="preserve">
+ <value>Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.</value>
+ </data>
+ <data name="NotSupported_ByRefReturn" xml:space="preserve">
+ <value>ByRef return value not supported in reflection invocation.</value>
+ </data>
+ <data name="Security_InvalidAssemblyPublicKey" xml:space="preserve">
+ <value>Invalid assembly public key.</value>
+ </data>
+ <data name="Arg_DlgtTargMeth" xml:space="preserve">
+ <value>Cannot bind to the target method because its signature is not compatible with that of the delegate type.</value>
+ </data>
+ <data name="Arg_MustBeDelegate" xml:space="preserve">
+ <value>Type must derive from Delegate.</value>
+ </data>
+ <data name="Arg_InvokeMethodMissingMetadata" xml:space="preserve">
+ <value>Cannot create a delegate on type '{0}' as it is missing metadata for the Invoke method. For more information, please visit http://go.microsoft.com/fwlink/?LinkID=616867</value>
+ </data>
+ <data name="Argument_AddingDuplicate" xml:space="preserve">
+ <value>An item with the same key has already been added.</value>
+ </data>
+ <data name="Argument_InvalidHandle" xml:space="preserve">
+ <value>The handle is invalid.</value>
+ </data>
+ <data name="Argument_ResolveMethodHandle" xml:space="preserve">
+ <value>Type handle '{0}' and method handle with declaring type '{1}' are incompatible. Get RuntimeMethodHandle and declaring RuntimeTypeHandle off the same MethodBase.</value>
+ </data>
+ <data name="Argument_ResolveFieldHandle" xml:space="preserve">
+ <value>Type handle '{0}' and field handle with declaring type '{1}' are incompatible. Get RuntimeFieldHandle and declaring RuntimeTypeHandle off the same FieldInfo.</value>
+ </data>
+ <data name="Argument_MethodDeclaringTypeGeneric" xml:space="preserve">
+ <value>Cannot resolve method {0} because the declaring type of the method handle is generic. Explicitly provide the declaring type to GetMethodFromHandle.</value>
+ </data>
+ <data name="Argument_FieldDeclaringTypeGeneric" xml:space="preserve">
+ <value>Cannot resolve field {0} because the declaring type of the field handle is generic. Explicitly provide the declaring type to GetFieldFromHandle.</value>
+ </data>
+ <data name="Arg_UnboundGenParam" xml:space="preserve">
+ <value>Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.</value>
+ </data>
+ <data name="Argument_AssemblyGetTypeCannotSpecifyAssembly" xml:space="preserve">
+ <value>Type names passed to Assembly.GetType() must not specify an assembly.</value>
+ </data>
+ <data name="InvalidOperation_NoPublicAddMethod" xml:space="preserve">
+ <value>Cannot add the event handler since no public add method exists for the event.</value>
+ </data>
+ <data name="InvalidOperation_NoPublicRemoveMethod" xml:space="preserve">
+ <value>Cannot remove the event handler since no public remove method exists for the event.</value>
+ </data>
+</root>
diff --git a/src/System.Private.Reflection.Core/src/Resources/Strings.resx b/src/System.Private.Reflection.Core/src/Resources/Strings.resx
new file mode 100644
index 000000000..f2bea8235
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Resources/Strings.resx
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Bif_InvalidMetadata" xml:space="preserve">
+ <value>A problem was found in this image's metadata.</value>
+ </data>
+ <data name="Acc_CreateAbstEx" xml:space="preserve">
+ <value>Cannot create an instance of {0} because it is an abstract class.</value>
+ </data>
+ <data name="Acc_NotClassInit" xml:space="preserve">
+ <value>Type initializer was not callable.</value>
+ </data>
+ <data name="Acc_ReadOnly" xml:space="preserve">
+ <value>Cannot set a constant field.</value>
+ </data>
+ <data name="Arg_NotGenericMethodDefinition" xml:space="preserve">
+ <value>{0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.</value>
+ </data>
+ <data name="Arg_NotGenericParameter" xml:space="preserve">
+ <value>Method may only be called on a Type for which Type.IsGenericParameter is true.</value>
+ </data>
+ <data name="Arg_TypeLoadNullStr" xml:space="preserve">
+ <value>A null or zero length string does not represent a valid Type.</value>
+ </data>
+ <data name="Argument_NotEnoughGenArguments" xml:space="preserve">
+ <value>The type or method has {1} generic parameter(s), but {0} generic argument(s) were provided. A generic argument must be provided for each generic parameter.</value>
+ </data>
+ <data name="Reflection_CustomReflectionObjectsNotSupported" xml:space="preserve">
+ <value>The object '{0}' was created by a custom ReflectionContext and cannot be used here.</value>
+ </data>
+ <data name="TypeLoad_TypeNotFoundByGetType" xml:space="preserve">
+ <value>The type '{0}' cannot be found.</value>
+ </data>
+ <data name="TypeLoad_TypeNotFound" xml:space="preserve">
+ <value>The type '{0}' cannot be found in the metadata for '{1}'.</value>
+ </data>
+ <data name="TypeLoad_BadEscape" xml:space="preserve">
+ <value>An invalid escape sequence was found inside a type name.</value>
+ </data>
+ <data name="FileNotFound_AssemblyNotFound" xml:space="preserve">
+ <value>Cannot load assembly '{0}'. No metadata found for this assembly.</value>
+ </data>
+ <data name="Format_StringZeroLength" xml:space="preserve">
+ <value>String cannot have zero length.</value>
+ </data>
+ <data name="Arg_HTCapacityOverflow" xml:space="preserve">
+ <value>Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.</value>
+ </data>
+ <data name="NotSupported_ByRefReturn" xml:space="preserve">
+ <value>ByRef return value not supported in reflection invocation.</value>
+ </data>
+ <data name="Security_InvalidAssemblyPublicKey" xml:space="preserve">
+ <value>Invalid assembly public key.</value>
+ </data>
+ <data name="Arg_DlgtTargMeth" xml:space="preserve">
+ <value>Cannot bind to the target method because its signature is not compatible with that of the delegate type.</value>
+ </data>
+ <data name="Arg_MustBeDelegate" xml:space="preserve">
+ <value>Type must derive from Delegate.</value>
+ </data>
+ <data name="Arg_InvokeMethodMissingMetadata" xml:space="preserve">
+ <value>Cannot create a delegate on type '{0}' as it is missing metadata for the Invoke method. For more information, please visit http://go.microsoft.com/fwlink/?LinkID=616867</value>
+ </data>
+ <data name="Argument_AddingDuplicate" xml:space="preserve">
+ <value>An item with the same key has already been added.</value>
+ </data>
+ <data name="Argument_InvalidHandle" xml:space="preserve">
+ <value>The handle is invalid.</value>
+ </data>
+ <data name="Argument_ResolveMethodHandle" xml:space="preserve">
+ <value>Type handle '{0}' and method handle with declaring type '{1}' are incompatible. Get RuntimeMethodHandle and declaring RuntimeTypeHandle off the same MethodBase.</value>
+ </data>
+ <data name="Argument_ResolveFieldHandle" xml:space="preserve">
+ <value>Type handle '{0}' and field handle with declaring type '{1}' are incompatible. Get RuntimeFieldHandle and declaring RuntimeTypeHandle off the same FieldInfo.</value>
+ </data>
+ <data name="Argument_MethodDeclaringTypeGeneric" xml:space="preserve">
+ <value>Cannot resolve method {0} because the declaring type of the method handle is generic. Explicitly provide the declaring type to GetMethodFromHandle.</value>
+ </data>
+ <data name="Argument_FieldDeclaringTypeGeneric" xml:space="preserve">
+ <value>Cannot resolve field {0} because the declaring type of the field handle is generic. Explicitly provide the declaring type to GetFieldFromHandle.</value>
+ </data>
+ <data name="Arg_UnboundGenParam" xml:space="preserve">
+ <value>Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.</value>
+ </data>
+ <data name="Argument_AssemblyGetTypeCannotSpecifyAssembly" xml:space="preserve">
+ <value>Type names passed to Assembly.GetType() must not specify an assembly.</value>
+ </data>
+ <data name="InvalidOperation_NoPublicAddMethod" xml:space="preserve">
+ <value>Cannot add the event handler since no public add method exists for the event.</value>
+ </data>
+ <data name="InvalidOperation_NoPublicRemoveMethod" xml:space="preserve">
+ <value>Cannot remove the event handler since no public remove method exists for the event.</value>
+ </data>
+</root>
diff --git a/src/System.Private.Reflection.Core/src/Resources/System.Private.Reflection.Core.rd.xml b/src/System.Private.Reflection.Core/src/Resources/System.Private.Reflection.Core.rd.xml
new file mode 100644
index 000000000..3498c6f52
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/Resources/System.Private.Reflection.Core.rd.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
+ <Library Name="*System.Private.Reflection.Core*">
+ <Assembly Name="System.Private.Reflection.Core">
+ <Namespace Name="System">
+ <Type Name="DBNull" Browse="All">
+ </Type>
+ </Namespace>
+ </Assembly>
+ </Library>
+</Directives>
diff --git a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
new file mode 100644
index 000000000..cbd265fb9
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>System.Private.Reflection.Core</AssemblyName>
+ <OutputType>Library</OutputType>
+ <ProjectGuid>{999BB20D-A032-4836-A587-627D243C1668}</ProjectGuid>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <EnableWinRT>true</EnableWinRT>
+ <CLSCompliant>false</CLSCompliant>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\AotPackageReference\AotPackageReference.depproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+
+ <ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
+ <ProjectReference Include="..\..\System.Private.Reflection\src\System.Private.Reflection.csproj" />
+ <ProjectReference Include="..\..\System.Private.Reflection.Metadata\src\System.Private.Reflection.Metadata.csproj" />
+
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Runtime.dll" />
+ <ReferencePath Include="$(AotPackageReferencePath)\System.IO.dll" />
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Diagnostics.Tracing.dll" />
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Resources.ResourceManager.dll" />
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Reflection.Primitives.dll" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="System\DBNull.cs" />
+ <Compile Include="System\Reflection\Runtime\Assemblies\AssemblyNameHelpers.StrongName.cs" />
+ <Compile Include="System\Reflection\Runtime\Assemblies\AssemblyNameHelpers.cs" />
+ <Compile Include="System\Reflection\Runtime\Assemblies\AssemblyNameLexer.cs" />
+ <Compile Include="System\Reflection\Runtime\Assemblies\AssemblyNameParser.cs" />
+ <Compile Include="System\Reflection\Runtime\Assemblies\RuntimeAssembly.cs" />
+ <Compile Include="System\Reflection\Runtime\Assemblies\RuntimeAssemblyName.cs" />
+ <Compile Include="System\Reflection\Runtime\CustomAttributes\RuntimeCustomAttributeData.cs" />
+ <Compile Include="System\Reflection\Runtime\CustomAttributes\RuntimeNormalCustomAttributeData.cs" />
+ <Compile Include="System\Reflection\Runtime\CustomAttributes\RuntimePseudoCustomAttributeData.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DefaultDispenserPolicy.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\Dispenser.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserAlgorithm.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserFactory.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserPolicy.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserScenario.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserThatAlwaysCreates.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserThatAlwaysReuses.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserThatReusesAsLongAsKeyIsAlive.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserThatReusesAsLongAsValueIsAlive.cs" />
+ <Compile Include="System\Reflection\Runtime\Dispensers\DispenserThatLatchesTypeInfosInsideTypes.cs" />
+ <Compile Include="System\Reflection\Runtime\EventInfos\RuntimeEventInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\FieldInfos\RuntimeFieldInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\FieldInfos\LiteralFieldAccessor.cs" />
+ <Compile Include="System\Reflection\Runtime\General\Assignability.cs" />
+ <Compile Include="System\Reflection\Runtime\General\ReflectionCoreCallbacksImplementation.cs" />
+ <Compile Include="System\Reflection\Runtime\General\Dispensers.cs" />
+ <Compile Include="System\Reflection\Runtime\General\MetadataReaderExtensions.cs" />
+ <Compile Include="System\Reflection\Runtime\General\NamespaceChain.cs" />
+ <Compile Include="System\Reflection\Runtime\General\QHandles.cs" />
+ <Compile Include="System\Reflection\Runtime\General\RuntimeNamespaceInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\General\RuntimeTypeExtensions.cs" />
+ <Compile Include="System\Reflection\Runtime\General\RuntimeTypeUnifierEx.cs" />
+ <Compile Include="System\Reflection\Runtime\General\ToStringUtils.cs" />
+ <Compile Include="System\Reflection\Runtime\General\TypeContext.cs" />
+ <Compile Include="System\Reflection\Runtime\General\TypeResolver.cs" />
+ <Compile Include="System\Reflection\Runtime\General\TypeExtensions.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\OpenMethodInvoker.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeConstructedGenericMethodInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeConstructorInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimePlainConstructorInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeSyntheticConstructorInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeMethodCommon.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeMethodInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeNamedMethodInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\RuntimeSyntheticMethodInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\MethodInfos\SyntheticMethodId.cs" />
+ <Compile Include="System\Reflection\Runtime\Modules\RuntimeModule.cs" />
+ <Compile Include="System\Reflection\Runtime\ParameterInfos\RuntimeFatMethodParameterInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\ParameterInfos\RuntimeMethodParameterInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\ParameterInfos\RuntimeParameterInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\ParameterInfos\RuntimePropertyIndexParameterInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\ParameterInfos\RuntimeThinMethodParameterInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\ParameterInfos\RuntimeSyntheticParameterInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\PropertyInfos\RuntimePropertyInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\Tracing\ReflectionEventSource.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeArrayTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeConstructedGenericTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeGenericParameterTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeHasElementTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeNamedTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeNoMetadataNamedTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeBlockedTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\RuntimeTypeInfo.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeInfos\TypeInfoCachedData.cs" />
+ <Compile Include="System\Reflection\Runtime\Types\RuntimeGenericParameterType.cs" />
+ <Compile Include="System\Reflection\Runtime\Types\RuntimeGenericParameterTypeForTypes.cs" />
+ <Compile Include="System\Reflection\Runtime\Types\RuntimeGenericParameterTypeForMethods.cs" />
+ <Compile Include="System\Reflection\Runtime\Types\RuntimeInspectionOnlyNamedType.cs" />
+ <Compile Include="System\Reflection\Runtime\Types\ShadowRuntimeInspectionOnlyNamedType.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeParsing\TypeName.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeParsing\TypeLexer.cs" />
+ <Compile Include="System\Reflection\Runtime\TypeParsing\TypeParser.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Internal\Reflection\Core\AssemblyBinder.cs" />
+ <Compile Include="Internal\Reflection\Core\FoundationTypes.cs" />
+ <Compile Include="Internal\Reflection\Core\ReflectionDomain.cs" />
+ <Compile Include="Internal\Reflection\Core\ReflectionDomainSetup.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Internal\Reflection\Core\Execution\ExecutionDomain.cs" />
+ <Compile Include="Internal\Reflection\Core\Execution\ExecutionEnvironment.cs" />
+ <Compile Include="Internal\Reflection\Core\Execution\FieldAccessor.cs" />
+ <Compile Include="Internal\Reflection\Core\Execution\MethodInvoker.cs" />
+ <Compile Include="Internal\Reflection\Core\Execution\ReflectionCoreExecution.cs" />
+ <Compile Include="Internal\Reflection\Core\Execution\InvokerOptions.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Internal\Reflection\Tracing\ReflectionTrace.Public.cs" />
+ <Compile Include="Internal\Reflection\Tracing\ReflectionTrace.Public.Events.cs" />
+ <Compile Include="Internal\Reflection\Tracing\ReflectionTrace.Internal.cs" />
+ <Compile Include="Internal\Reflection\Tracing\ITraceableTypeMember.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="...\..\common\src\System\CommonRuntimeTypes.cs" />
+ <Compile Include="...\..\common\src\System\NotImplemented.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Generic\LowLevelList.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Generic\LowLevelDictionary.cs" />
+ <Compile Include="...\..\common\src\System\Linq\LowLevelEnumerable.cs" />
+ <Compile Include="...\..\common\src\System\Collections\HashHelpers.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Generic\EnumerableExtensions.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Generic\Empty.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Concurrent\ConcurrentUnifier.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Concurrent\ConcurrentUnifierW.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Concurrent\ConcurrentUnifierWKeyed.cs" />
+ <Compile Include="...\..\common\src\System\Collections\Concurrent\IKeyedItem.cs" />
+ <Compile Include="...\..\common\src\System\Runtime\CompilerServices\DeveloperExperienceModeOnlyAttribute.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\$(AssemblyName).rd.xml" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/System.Private.Reflection.Core/src/System/DBNull.cs b/src/System.Private.Reflection.Core/src/System/DBNull.cs
new file mode 100644
index 000000000..df48d9933
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/DBNull.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System.Diagnostics;
+
+namespace System
+{
+ //
+ // This is not actually an instance of the System.DBNull type exposed out of System.Data.Common.
+ // But this is also true on CoreCLR, so it's still compatible!
+ //
+ // This will of course, confound anyone who actually tries to compare the real System.DBNull to what we return.
+ // This is, however, the least worst of many bad options. Current apps out in the wild do not have access to a
+ // contract exposing System.DBNull so this hack of checking the type name via reflection is what they actually do.
+ //
+ // Official guidance is: Call ParameterInfo.HasDefaultValue.
+ //
+
+ //
+ // @todo: B#1190393 - this type should be "internal" but has to be made "public" in order for it to be reflectable under
+ // our reflection-block mechanism. The ReflectionBlock mechanism is on the block itself, so once that's done, we can make this type
+ // "internal" too.
+ //
+ public sealed class DBNull
+ {
+ private DBNull()
+ {
+ }
+
+ internal static readonly Object Value = new DBNull();
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.StrongName.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.StrongName.cs
new file mode 100644
index 000000000..d1b6f3b53
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.StrongName.cs
@@ -0,0 +1,134 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+
+
+/*============================================================
+**
+ Type: AssemblyNameHelpers
+**
+==============================================================*/
+
+using global::System;
+using global::System.IO;
+using global::System.Text;
+using global::System.Collections.Generic;
+using global::Internal.Runtime.Augments;
+using Buffer = System.Buffer;
+
+using SecurityException = global::System.Security.SecurityException;
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ internal static partial class AssemblyNameHelpers
+ {
+ internal static byte[] ComputePublicKeyToken(byte[] publicKey)
+ {
+ if (publicKey == null)
+ return null;
+
+ if (publicKey.Length == 0)
+ return Array.Empty<byte>();
+
+ if (!IsValidPublicKey(publicKey))
+ throw new SecurityException(SR.Security_InvalidAssemblyPublicKey);
+
+ byte[] hash = WinRTInterop.Callbacks.ComputeSHA1(publicKey);
+ byte[] pkt = new byte[PUBLIC_KEY_TOKEN_LEN];
+ for (int i = 0; i < PUBLIC_KEY_TOKEN_LEN; i++)
+ {
+ pkt[i] = hash[hash.Length - i - 1];
+ }
+ return pkt;
+ }
+
+ //
+ // This validation logic is a manual port of StrongNameIsValidPublicKey() in the desktop CLR (see clr\src\StrongName\api\StrongNameInternal.cpp)
+ //
+ private static bool IsValidPublicKey(byte[] publicKey)
+ {
+ uint publicKeyLength = (uint)(publicKey.Length);
+
+ // The buffer must be at least as large as the public key structure (for compat with desktop, we actually compare with the size of the header + 4).
+ if (publicKeyLength < SizeOfPublicKeyBlob + 4)
+ return false;
+
+
+ // Poor man's reinterpret_cast into the PublicKeyBlob structure.
+ uint[] publicKeyBlob = new uint[3];
+ Buffer.BlockCopy(publicKey, 0, publicKeyBlob, 0, (int)SizeOfPublicKeyBlob);
+ uint sigAlgID = publicKeyBlob[0];
+ uint hashAlgID = publicKeyBlob[1];
+ uint cbPublicKey = publicKeyBlob[2];
+
+ // The buffer must be the same size as the structure header plus the trailing key data
+ if (cbPublicKey != publicKeyLength - SizeOfPublicKeyBlob)
+ return false;
+
+ // The buffer itself looks reasonable, but the public key structure needs to be validated as well
+
+ // The ECMA key doesn't look like a valid key so it will fail the below checks. If we were passed that
+ // key, then we can skip them.
+ if (ByteArrayEquals(publicKey, EcmaKey))
+ return true;
+
+ // If a hash algorithm is specified, it must be a sensible value
+ bool fHashAlgorithmValid = GetAlgClass(hashAlgID) == ALG_CLASS_HASH && GetAlgSid(hashAlgID) == ALG_SID_SHA1;
+ if (hashAlgID != 0 && !fHashAlgorithmValid)
+ return false;
+
+ // If a signature algorithm is specified, it must be a sensible value
+ bool fSignatureAlgorithmValid = GetAlgClass(sigAlgID) == ALG_CLASS_SIGNATURE;
+ if (sigAlgID != 0 && !fSignatureAlgorithmValid)
+ return false;
+
+ // The key blob must indicate that it is a PUBLICKEYBLOB
+ if (publicKey[SizeOfPublicKeyBlob] != PUBLICKEYBLOB)
+ return false;
+
+ //@todo: Desktop also tries to import the public key blob using the Crypto api as further validation - not clear if there's any non-banned API to do this.
+
+ return true;
+ }
+
+ private static bool ByteArrayEquals(byte[] b1, byte[] b2)
+ {
+ if (b1.Length != b2.Length)
+ return false;
+ for (int i = 0; i < b1.Length; i++)
+ {
+ if (b1[i] != b2[i])
+ return false;
+ }
+ return true;
+ }
+
+ // Constants and macros copied from WinCrypt.h:
+
+ private static uint GetAlgClass(uint x)
+ {
+ return (x & (7 << 13));
+ }
+
+ private static uint GetAlgSid(uint x)
+ {
+ return (x & (511));
+ }
+
+ private const uint ALG_CLASS_HASH = (4 << 13);
+ private const uint ALG_SID_SHA1 = 4;
+ private const uint ALG_CLASS_SIGNATURE = (1 << 13);
+ private const uint PUBLICKEYBLOB = 0x6;
+
+ private const uint SizeOfPublicKeyBlob = 12;
+
+ private const int PUBLIC_KEY_TOKEN_LEN = 8;
+
+ private static byte[] EcmaKey =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.cs
new file mode 100644
index 000000000..51778e061
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameHelpers.cs
@@ -0,0 +1,179 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+
+/*============================================================
+**
+ Type: AssemblyNameHelpers
+**
+==============================================================*/
+
+using global::System;
+using global::System.Globalization;
+using global::System.IO;
+using global::System.Text;
+using global::System.Collections.Generic;
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ internal static partial class AssemblyNameHelpers
+ {
+ internal static String ComputeDisplayName(RuntimeAssemblyName a)
+ {
+ if (a.Name == String.Empty)
+ throw new FileLoadException();
+
+ StringBuilder sb = new StringBuilder();
+ if (a.Name != null)
+ {
+ sb.AppendQuoted(a.Name);
+ }
+
+ if (a.Version != null)
+ {
+ sb.Append(", Version=");
+ sb.Append(a.Version.ToString());
+ }
+
+ String cultureName = a.CultureName;
+ if (cultureName != null)
+ {
+ if (cultureName == String.Empty)
+ cultureName = "neutral";
+ sb.Append(", Culture=");
+ sb.AppendQuoted(cultureName);
+ }
+
+ byte[] pkt = a.PublicKeyOrToken;
+ if (pkt != null)
+ {
+ if (0 != (a.Flags & AssemblyNameFlags.PublicKey))
+ pkt = ComputePublicKeyToken(pkt);
+
+ if (pkt.Length > PUBLIC_KEY_TOKEN_LEN)
+ throw new ArgumentException();
+
+ sb.Append(", PublicKeyToken=");
+ if (pkt.Length == 0)
+ sb.Append("null");
+ else
+ {
+ foreach (byte b in pkt)
+ {
+ sb.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+ }
+ }
+
+ if (0 != (a.Flags & AssemblyNameFlags.Retargetable))
+ sb.Append(", Retargetable=Yes");
+
+ AssemblyContentType contentType = ExtractAssemblyContentType(a.Flags);
+ if (contentType == AssemblyContentType.WindowsRuntime)
+ sb.Append(", ContentType=WindowsRuntime");
+
+ // NOTE: By design (desktop compat) AssemblyName.FullName and ToString() do not include ProcessorArchitecture.
+
+ return sb.ToString();
+ }
+
+ private static void AppendQuoted(this StringBuilder sb, String s)
+ {
+ bool needsQuoting = false;
+ const char quoteChar = '\"';
+
+ //@todo: App-compat: You can use double or single quotes to quote a name, and Fusion (or rather the IdentityAuthority) picks one
+ // by some algorithm. Rather than guess at it, I'll just use double-quote consistently.
+ if (s != s.Trim() || s.Contains("\"") || s.Contains("\'"))
+ needsQuoting = true;
+
+ if (needsQuoting)
+ sb.Append(quoteChar);
+
+ for (int i = 0; i < s.Length; i++)
+ {
+ bool addedEscape = false;
+ foreach (KeyValuePair<char, String> kv in AssemblyNameLexer.EscapeSequences)
+ {
+ String escapeReplacement = kv.Value;
+ if (!(s[i] == escapeReplacement[0]))
+ continue;
+ if ((s.Length - i) < escapeReplacement.Length)
+ continue;
+ String prefix = s.Substring(i, escapeReplacement.Length);
+ if (prefix == escapeReplacement)
+ {
+ sb.Append('\\');
+ sb.Append(kv.Key);
+ addedEscape = true;
+ }
+ }
+
+ if (!addedEscape)
+ sb.Append(s[i]);
+ }
+
+ if (needsQuoting)
+ sb.Append(quoteChar);
+ }
+
+
+ //
+ // Converts an AssemblyName to a RuntimeAssemblyName that is free from any future mutations on the AssemblyName.
+ //
+ internal static RuntimeAssemblyName ToRuntimeAssemblyName(this AssemblyName assemblyName)
+ {
+ if (assemblyName.Name == null)
+ throw new ArgumentException();
+
+ AssemblyNameFlags flags = assemblyName.Flags;
+ AssemblyContentType contentType = assemblyName.ContentType;
+ ProcessorArchitecture processorArchitecture = assemblyName.ProcessorArchitecture;
+ AssemblyNameFlags combinedFlags = CombineAssemblyNameFlags(flags, contentType, processorArchitecture);
+ byte[] pkOriginal;
+ if (0 != (flags & AssemblyNameFlags.PublicKey))
+ pkOriginal = assemblyName.GetPublicKey();
+ else
+ pkOriginal = assemblyName.GetPublicKeyToken();
+
+ // AssemblyName's PKT property getters do NOT copy the array before giving it out. Make our own copy
+ // as the original is wide open to tampering by anyone.
+ byte[] pkCopy = null;
+ if (pkOriginal != null)
+ {
+ pkCopy = new byte[pkOriginal.Length];
+ ((ICollection<byte>)pkOriginal).CopyTo(pkCopy, 0);
+ }
+
+ return new RuntimeAssemblyName(assemblyName.Name, assemblyName.Version, assemblyName.CultureName, combinedFlags, pkCopy);
+ }
+
+ //
+ // These helpers convert between the combined flags+contentType+processorArchitecture value and the separated parts.
+ //
+ // Since these are only for trusted callers, they do NOT check for out of bound bits.
+ //
+
+ internal static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags)
+ {
+ return (AssemblyContentType)((((int)flags) >> 9) & 0x7);
+ }
+
+ internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags)
+ {
+ return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7);
+ }
+
+ internal static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags)
+ {
+ return combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F);
+ }
+
+ internal static AssemblyNameFlags CombineAssemblyNameFlags(AssemblyNameFlags flags, AssemblyContentType contentType, ProcessorArchitecture processorArchitecture)
+ {
+ return (AssemblyNameFlags)(((int)flags) | (((int)contentType) << 9) | ((int)processorArchitecture << 4));
+ }
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameLexer.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameLexer.cs
new file mode 100644
index 000000000..543ec5478
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameLexer.cs
@@ -0,0 +1,140 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.IO;
+using global::System.Text;
+using global::System.Globalization;
+using global::System.Collections.Generic;
+using global::System.Runtime.InteropServices;
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ //
+ // A simple lexer for assembly display names.
+ //
+ internal struct AssemblyNameLexer
+ {
+ internal AssemblyNameLexer(String s)
+ {
+ // Convert string to char[] with NUL terminator. (An actual NUL terminator in the input string will be treated
+ // as an actual end of string: this is compatible with desktop behavior.)
+ char[] chars = new char[s.Length + 1];
+ s.CopyTo(0, chars, 0, s.Length);
+ _chars = chars;
+ _index = 0;
+ }
+
+ //
+ // Return the next token in assembly name. If you expect the result to be DisplayNameToken.String,
+ // use GetNext(out String) instead.
+ //
+ internal Token GetNext()
+ {
+ String ignore;
+ return GetNext(out ignore);
+ }
+
+ //
+ // Return the next token in assembly name. If the result is DisplayNameToken.String,
+ // sets "tokenString" to the tokenized string.
+ //
+ internal Token GetNext(out String tokenString)
+ {
+ tokenString = null;
+ while (Char.IsWhiteSpace(_chars[_index]))
+ _index++;
+
+ char c = _chars[_index++];
+ if (c == 0)
+ return Token.End;
+ if (c == ',')
+ return Token.Comma;
+ if (c == '=')
+ return Token.Equals;
+
+ StringBuilder sb = new StringBuilder();
+
+ char quoteChar = (char)0;
+ if (c == '\'' || c == '\"')
+ {
+ quoteChar = c;
+ c = _chars[_index++];
+ }
+
+ for (; ;)
+ {
+ if (c == 0)
+ {
+ _index--;
+ break; // Terminate: End of string (desktop compat: if string was quoted, permitted to terminate without end-quote.)
+ }
+
+ if (quoteChar != 0 && c == quoteChar)
+ break; // Terminate: Found closing quote of quoted string.
+
+ if (quoteChar == 0 && (c == ',' || c == '='))
+ {
+ _index--;
+ break; // Terminate: Found start of a new ',' or '=' token.
+ }
+
+ if (quoteChar == 0 && (c == '\'' || c == '\"'))
+ throw new FileLoadException(); // Desktop compat: Unescaped quote illegal unless entire string is quoted.
+
+ if (c == '\\')
+ {
+ c = _chars[_index++];
+ bool matched = false;
+ foreach (KeyValuePair<char, String> kv in EscapeSequences)
+ {
+ if (c == kv.Key)
+ {
+ matched = true;
+ sb.Append(kv.Value);
+ break;
+ }
+ }
+ if (!matched)
+ throw new FileLoadException(); // Unrecognized escape
+ }
+ else
+ {
+ sb.Append(c);
+ }
+
+ c = _chars[_index++];
+ }
+
+ tokenString = sb.ToString();
+ if (quoteChar == 0)
+ tokenString = tokenString.Trim(); // Unless quoted, whitespace at beginning or end doesn't count.
+ return Token.String;
+ }
+
+ internal static KeyValuePair<char, String>[] EscapeSequences =
+ {
+ new KeyValuePair<char, String>('\\', "\\"),
+ new KeyValuePair<char, String>(',', ","),
+ new KeyValuePair<char, String>('=', "="),
+ new KeyValuePair<char, String>('\'', "'"),
+ new KeyValuePair<char, String>('\"', "\""),
+ new KeyValuePair<char, String>('n', Environment.NewLine),
+ new KeyValuePair<char, String>('t', "\t"),
+ };
+
+ // Token categories for display name lexer.
+ internal enum Token
+ {
+ Equals = 1,
+ Comma = 2,
+ String = 3,
+ End = 4,
+ }
+
+ private char[] _chars;
+ private int _index;
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameParser.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameParser.cs
new file mode 100644
index 000000000..5b6c23fb6
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/AssemblyNameParser.cs
@@ -0,0 +1,230 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.IO;
+using global::System.Text;
+using global::System.Diagnostics;
+using global::System.Globalization;
+using global::System.Collections.Generic;
+using global::System.Runtime.InteropServices;
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ //
+ // Parses an assembly name.
+ //
+ internal static class AssemblyNameParser
+ {
+ internal static void Parse(AssemblyName blank, String s)
+ {
+ if (s == null)
+ throw new ArgumentNullException();
+ RuntimeAssemblyName runtimeAssemblyName = Parse(s);
+ runtimeAssemblyName.CopyToAssemblyName(blank);
+ }
+
+ internal static RuntimeAssemblyName Parse(String s)
+ {
+ Debug.Assert(s != null);
+ AssemblyNameLexer lexer = new AssemblyNameLexer(s);
+
+ // Name must come first.
+ String name;
+ AssemblyNameLexer.Token token = lexer.GetNext(out name);
+ if (token != AssemblyNameLexer.Token.String)
+ {
+ if (token == AssemblyNameLexer.Token.End)
+ throw new ArgumentException(SR.Format_StringZeroLength);
+ else
+ throw new FileLoadException();
+ }
+
+ if (name == String.Empty)
+ throw new FileLoadException();
+
+ Version version = null;
+ String cultureName = null;
+ byte[] pkt = null;
+ AssemblyNameFlags flags = 0;
+
+ LowLevelList<String> alreadySeen = new LowLevelList<String>();
+ token = lexer.GetNext();
+ while (token != AssemblyNameLexer.Token.End)
+ {
+ if (token != AssemblyNameLexer.Token.Comma)
+ throw new FileLoadException();
+ String attributeName;
+
+ token = lexer.GetNext(out attributeName);
+ if (token != AssemblyNameLexer.Token.String)
+ throw new FileLoadException();
+ token = lexer.GetNext();
+
+ // Compat note: Inside AppX apps, the desktop CLR's AssemblyName parser skips past any elements that don't follow the "<Something>=<Something>" pattern.
+ // (when running classic Windows apps, such an illegal construction throws an exception as expected.)
+ // Naturally, at least one app unwittingly takes advantage of this.
+ if (token == AssemblyNameLexer.Token.Comma || token == AssemblyNameLexer.Token.End)
+ continue;
+
+ if (token != AssemblyNameLexer.Token.Equals)
+ throw new FileLoadException();
+ String attributeValue;
+ token = lexer.GetNext(out attributeValue);
+ if (token != AssemblyNameLexer.Token.String)
+ throw new FileLoadException();
+
+ if (attributeName == String.Empty)
+ throw new FileLoadException();
+
+ for (int i = 0; i < alreadySeen.Count; i++)
+ {
+ if (alreadySeen[i].Equals(attributeName, StringComparison.OrdinalIgnoreCase))
+ throw new FileLoadException(); // Cannot specify the same attribute twice.
+ }
+ alreadySeen.Add(attributeName);
+
+ if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase))
+ {
+ version = ParseVersion(attributeValue);
+ }
+
+ if (attributeName.Equals("Culture", StringComparison.OrdinalIgnoreCase))
+ {
+ cultureName = ParseCulture(attributeValue);
+ }
+
+ if (attributeName.Equals("PublicKeyToken", StringComparison.OrdinalIgnoreCase))
+ {
+ pkt = ParsePKT(attributeValue);
+ }
+
+ if (attributeName.Equals("ProcessorArchitecture", StringComparison.OrdinalIgnoreCase))
+ {
+ flags |= (AssemblyNameFlags)(((int)ParseProcessorArchitecture(attributeValue)) << 4);
+ }
+
+ if (attributeName.Equals("Retargetable", StringComparison.OrdinalIgnoreCase))
+ {
+ if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase))
+ flags |= AssemblyNameFlags.Retargetable;
+ else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase))
+ {
+ // nothing to do
+ }
+ else
+ throw new FileLoadException();
+ }
+
+ if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase))
+ {
+ if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase))
+ flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9);
+ else
+ throw new FileLoadException();
+ }
+
+ // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it (as long it's not duplicated.)
+ token = lexer.GetNext();
+ }
+ return new RuntimeAssemblyName(name, version, cultureName, flags, pkt);
+ }
+
+ private static Version ParseVersion(String attributeValue)
+ {
+ String[] parts = attributeValue.Split('.');
+ if (parts.Length > 4)
+ throw new FileLoadException();
+ ushort[] versionNumbers = new ushort[4];
+ for (int i = 0; i < versionNumbers.Length; i++)
+ {
+ if (i >= parts.Length)
+ versionNumbers[i] = ushort.MaxValue;
+ else
+ {
+ // Desktop compat: TryParse is a little more forgiving than Fusion.
+ for (int j = 0; j < parts[i].Length; j++)
+ {
+ if (!Char.IsDigit(parts[i][j]))
+ throw new FileLoadException();
+ }
+ if (!(ushort.TryParse(parts[i], out versionNumbers[i])))
+ {
+ if (parts[i] == string.Empty)
+ {
+ // Desktop compat: Empty strings are a synonym for 0
+ versionNumbers[i] = 0;
+ }
+ else
+ {
+ throw new FileLoadException();
+ }
+ }
+ }
+ }
+
+ if (parts.Length == 1)
+ return null; // Desktop compat: if only major version present, treat as no version.
+
+ return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]);
+ }
+
+ private static String ParseCulture(String attributeValue)
+ {
+ if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase))
+ {
+ return "";
+ }
+ else
+ {
+ CultureInfo culture = new CultureInfo(attributeValue); // Force a CultureNotFoundException if not a valid culture.
+ return culture.Name;
+ }
+ }
+
+ private static byte[] ParsePKT(String attributeValue)
+ {
+ if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == String.Empty)
+ return Array.Empty<byte>();
+
+ if (attributeValue.Length != 8 * 2)
+ throw new FileLoadException();
+
+ byte[] pkt = new byte[8];
+ int srcIndex = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ char hi = attributeValue[srcIndex++];
+ char lo = attributeValue[srcIndex++];
+ pkt[i] = (byte)((ParseHexNybble(hi) << 4) | ParseHexNybble(lo));
+ }
+ return pkt;
+ }
+
+ private static ProcessorArchitecture ParseProcessorArchitecture(String attributeValue)
+ {
+ if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase))
+ return ProcessorArchitecture.MSIL;
+ if (attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase))
+ return ProcessorArchitecture.X86;
+ if (attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase))
+ return ProcessorArchitecture.IA64;
+ if (attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase))
+ return ProcessorArchitecture.Amd64;
+ if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase))
+ return ProcessorArchitecture.Arm;
+ throw new FileLoadException();
+ }
+
+ private static byte ParseHexNybble(char c)
+ {
+ if (c >= '0' && c <= '9')
+ return (byte)(c - '0');
+ if (c >= 'a' && c <= 'f')
+ return (byte)(c - 'a' + 10);
+ if (c >= 'A' && c <= 'F')
+ return (byte)(c - 'A' + 10);
+ throw new FileLoadException();
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssembly.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssembly.cs
new file mode 100644
index 000000000..6c0c38aae
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssembly.cs
@@ -0,0 +1,243 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.IO;
+using global::System.Text;
+using global::System.Diagnostics;
+using global::System.Reflection;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Modules;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.TypeParsing;
+using global::System.Reflection.Runtime.CustomAttributes;
+using global::System.Collections.Generic;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Tracing;
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ //
+ // The runtime's implementation of an Assembly.
+ //
+ internal sealed partial class RuntimeAssembly : ExtensibleAssembly, IEquatable<RuntimeAssembly>
+ {
+ private RuntimeAssembly(MetadataReader reader, ScopeDefinitionHandle scope, IEnumerable<QScopeDefinition> overflowScopes)
+ {
+ Scope = new QScopeDefinition(reader, scope);
+ OverflowScopes = overflowScopes;
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.Assembly_CustomAttributes(this);
+
+ foreach (QScopeDefinition scope in AllScopes)
+ {
+ foreach (CustomAttributeData cad in RuntimeCustomAttributeData.GetCustomAttributes(this.ReflectionDomain, scope.Reader, scope.ScopeDefinition.CustomAttributes))
+ yield return cad;
+
+ ExecutionDomain executionDomain = this.ReflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(scope.Reader, scope.Handle))
+ yield return cad;
+ }
+ }
+ }
+ }
+
+ public sealed override IEnumerable<TypeInfo> DefinedTypes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.Assembly_DefinedTypes(this);
+
+ foreach (QScopeDefinition scope in AllScopes)
+ {
+ MetadataReader reader = scope.Reader;
+ ScopeDefinition scopeDefinition = scope.ScopeDefinition;
+ IEnumerable<NamespaceDefinitionHandle> topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition };
+ IEnumerable<NamespaceDefinitionHandle> allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles);
+ IEnumerable<TypeDefinitionHandle> allTopLevelTypes = reader.GetTopLevelTypes(allNamespaceHandles);
+ IEnumerable<TypeDefinitionHandle> allTypes = reader.GetTransitiveTypes(allTopLevelTypes, publicOnly: false);
+ foreach (TypeDefinitionHandle typeDefinitionHandle in allTypes)
+ yield return RuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(reader, typeDefinitionHandle);
+ }
+ }
+ }
+
+ public sealed override IEnumerable<Type> ExportedTypes
+ {
+ get
+ {
+ foreach (QScopeDefinition scope in AllScopes)
+ {
+ MetadataReader reader = scope.Reader;
+ ScopeDefinition scopeDefinition = scope.ScopeDefinition;
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ IEnumerable<NamespaceDefinitionHandle> topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition };
+ IEnumerable<NamespaceDefinitionHandle> allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles);
+ IEnumerable<TypeDefinitionHandle> allTopLevelTypes = reader.GetTopLevelTypes(allNamespaceHandles);
+ IEnumerable<TypeDefinitionHandle> allTypes = reader.GetTransitiveTypes(allTopLevelTypes, publicOnly: true);
+ foreach (TypeDefinitionHandle typeDefinitionHandle in allTypes)
+ yield return reflectionDomain.ResolveTypeDefinition(reader, typeDefinitionHandle);
+ }
+ }
+ }
+
+ public sealed override String FullName
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.Assembly_FullName(this);
+
+ return GetName().FullName;
+ }
+ }
+
+ public sealed override Module ManifestModule
+ {
+ get
+ {
+ return RuntimeModule.GetRuntimeModule(this);
+ }
+ }
+
+ public sealed override IEnumerable<Module> Modules
+ {
+ get
+ {
+ yield return ManifestModule;
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeAssembly other = obj as RuntimeAssembly;
+ return Equals(other);
+ }
+
+ public bool Equals(RuntimeAssembly other)
+ {
+ if (other == null)
+ return false;
+ if (!(this.Scope.Reader == other.Scope.Reader))
+ return false;
+ if (!(this.Scope.Handle.Equals(other.Scope.Handle)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return Scope.Handle.GetHashCode();
+ }
+
+ public sealed override ManifestResourceInfo GetManifestResourceInfo(String resourceName)
+ {
+ ExecutionDomain executionDomain = this.ReflectionDomain as ExecutionDomain;
+ if (executionDomain == null)
+ throw new PlatformNotSupportedException();
+ return executionDomain.ExecutionEnvironment.GetManifestResourceInfo(this, resourceName);
+ }
+
+ public sealed override String[] GetManifestResourceNames()
+ {
+ ExecutionDomain executionDomain = this.ReflectionDomain as ExecutionDomain;
+ if (executionDomain == null)
+ throw new PlatformNotSupportedException();
+ return executionDomain.ExecutionEnvironment.GetManifestResourceNames(this);
+ }
+
+ public sealed override Stream GetManifestResourceStream(String name)
+ {
+ ExecutionDomain executionDomain = this.ReflectionDomain as ExecutionDomain;
+ if (executionDomain == null)
+ throw new PlatformNotSupportedException();
+ return executionDomain.ExecutionEnvironment.GetManifestResourceStream(this, name);
+ }
+
+ public sealed override AssemblyName GetName()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.Assembly_GetName(this);
+
+ return Scope.Handle.ToRuntimeAssemblyName(Scope.Reader).ToAssemblyName();
+ }
+
+ public sealed override Type GetType(String name, bool throwOnError, bool ignoreCase)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.Assembly_GetType(this, name);
+
+ if (name == null)
+ throw new ArgumentNullException();
+ if (name.Length == 0)
+ throw new ArgumentException();
+
+ AssemblyQualifiedTypeName assemblyQualifiedTypeName;
+ try
+ {
+ assemblyQualifiedTypeName = TypeParser.ParseAssemblyQualifiedTypeName(name);
+ if (assemblyQualifiedTypeName.AssemblyName != null)
+ throw new ArgumentException(SR.Argument_AssemblyGetTypeCannotSpecifyAssembly); // Cannot specify an assembly qualifier in a typename passed to Assembly.GetType()
+ }
+ catch (ArgumentException)
+ {
+ if (throwOnError)
+ throw;
+ return null;
+ }
+
+ RuntimeType result;
+ Exception typeLoadException = assemblyQualifiedTypeName.TypeName.TryResolve(this.ReflectionDomain, this, ignoreCase, out result);
+ if (typeLoadException != null)
+ {
+ if (throwOnError)
+ throw typeLoadException;
+ return null;
+ }
+ return result;
+ }
+
+ internal QScopeDefinition Scope { get; private set; }
+
+ internal IEnumerable<QScopeDefinition> OverflowScopes { get; private set; }
+
+ internal IEnumerable<QScopeDefinition> AllScopes
+ {
+ get
+ {
+ yield return Scope;
+
+ foreach (QScopeDefinition overflowScope in OverflowScopes)
+ {
+ yield return overflowScope;
+ }
+ }
+ }
+
+ internal ReflectionDomain ReflectionDomain
+ {
+ get
+ {
+ return ReflectionCoreExecution.ExecutionDomain; //@todo: User Reflection Domains not yet supported.
+ }
+ }
+ }
+}
+
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyName.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyName.cs
new file mode 100644
index 000000000..1c9ee2f43
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyName.cs
@@ -0,0 +1,173 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.IO;
+using global::System.Text;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::Internal.Reflection.Augments;
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ //
+ // This is a private assembly name abstraction that's more suitable for use as keys in our caches.
+ //
+ // - Immutable, unlike the public AssemblyName
+ // - Has a useful Equals() override, unlike the public AssemblyName.
+ //
+ // We use this as our internal interchange type and only convert to and from the public AssemblyName class at public boundaries.
+ //
+ internal sealed class RuntimeAssemblyName : IEquatable<RuntimeAssemblyName>
+ {
+ public RuntimeAssemblyName(String name, Version version, String cultureName, AssemblyNameFlags flags, byte[] publicKeyOrToken)
+ {
+ Debug.Assert(name != null);
+ this.Name = name;
+
+ // Optional version.
+ this.Version = version;
+
+ // Optional culture name.
+ this.CultureName = cultureName;
+
+ // Optional flags (this is actually an OR of the classic flags and the ContentType.)
+ this.Flags = flags;
+
+ // Optional public key (if Flags.PublicKey == true) or public key token.
+ this.PublicKeyOrToken = publicKeyOrToken;
+ }
+
+ // Simple name.
+ public String Name { get; private set; }
+
+ // Optional version.
+ public Version Version { get; private set; }
+
+ // Optional culture name.
+ public String CultureName { get; private set; }
+
+ // Optional flags (this is actually an OR of the classic flags and the ContentType.)
+ public AssemblyNameFlags Flags { get; private set; }
+
+ // Optional public key (if Flags.PublicKey == true) or public key token.
+ public byte[] PublicKeyOrToken { get; private set; }
+
+ // Equality - this compares every bit of data in the RuntimeAssemblyName which is acceptable for use as keys in a cache
+ // where semantic duplication is permissible. This method is *not* meant to define ref->def binding rules or
+ // assembly binding unification rules.
+ public bool Equals(RuntimeAssemblyName other)
+ {
+ if (other == null)
+ return false;
+ if (!this.Name.Equals(other.Name))
+ return false;
+ if (this.Version == null)
+ {
+ if (other.Version != null)
+ return false;
+ }
+ else
+ {
+ if (!this.Version.Equals(other.Version))
+ return false;
+ }
+ if (!String.Equals(this.CultureName, other.CultureName))
+ return false;
+ if (this.Flags != other.Flags)
+ return false;
+
+ byte[] thisPK = this.PublicKeyOrToken;
+ byte[] otherPK = other.PublicKeyOrToken;
+ if (thisPK == null)
+ {
+ if (otherPK != null)
+ return false;
+ }
+ else if (otherPK == null)
+ {
+ return false;
+ }
+ else if (thisPK.Length != otherPK.Length)
+ {
+ return false;
+ }
+ else
+ {
+ for (int i = 0; i < thisPK.Length; i++)
+ {
+ if (thisPK[i] != otherPK[i])
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeAssemblyName other = obj as RuntimeAssemblyName;
+ if (other == null)
+ return false;
+ return Equals(other);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return this.Name.GetHashCode();
+ }
+
+ //
+ // Converts an RuntimeAssemblyName to a freshly allocated AssemblyName with no data aliasing to any other object.
+ //
+ public AssemblyName ToAssemblyName()
+ {
+ AssemblyName assemblyName = new AssemblyName();
+ CopyToAssemblyName(assemblyName);
+ return assemblyName;
+ }
+
+ //
+ // Copies a RuntimeAssemblyName into a freshly allocated AssemblyName with no data aliasing to any other object.
+ //
+ public void CopyToAssemblyName(AssemblyName blank)
+ {
+ blank.Name = this.Name;
+ if (this.Version != null)
+ blank.Version = this.Version;
+ if (this.CultureName != null)
+ blank.CultureName = this.CultureName;
+
+ // Our "Flags" contain both the classic flags and the ProcessorArchitecture + ContentType bits. The public AssemblyName has separate properties for
+ // these. The setters for these properties quietly mask out any bits intended for the other one, so we needn't do that ourselves..
+ blank.Flags = AssemblyNameHelpers.ExtractAssemblyNameFlags(this.Flags);
+ blank.ContentType = AssemblyNameHelpers.ExtractAssemblyContentType(this.Flags);
+ blank.ProcessorArchitecture = AssemblyNameHelpers.ExtractProcessorArchitecture(this.Flags);
+
+ if (this.PublicKeyOrToken != null)
+ {
+ // We must not hand out our own copy of the PKT to AssemblyName as AssemblyName is amazingly trusting and gives untrusted callers
+ // full freedom to scribble on its PKT array. (As do we but we only have trusted callers!)
+ byte[] pkCopy = new byte[this.PublicKeyOrToken.Length];
+ ((ICollection<byte>)(this.PublicKeyOrToken)).CopyTo(pkCopy, 0);
+
+ if (0 != (this.Flags & AssemblyNameFlags.PublicKey))
+ blank.SetPublicKey(pkCopy);
+ else
+ blank.SetPublicKeyToken(pkCopy);
+ }
+
+ return;
+ }
+
+ public String FullName
+ {
+ get
+ {
+ return AssemblyNameHelpers.ComputeDisplayName(this);
+ }
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs
new file mode 100644
index 000000000..5e25a560d
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs
@@ -0,0 +1,148 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Collections.ObjectModel;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+using global::Internal.Reflection.Tracing;
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.CustomAttributes
+{
+ //
+ // Common base class for the Runtime's implementation of CustomAttributeData.
+ //
+ internal abstract partial class RuntimeCustomAttributeData : ExtensibleCustomAttributeData
+ {
+ public abstract override Type AttributeType
+ {
+ get;
+ }
+
+ public sealed override IList<CustomAttributeTypedArgument> ConstructorArguments
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.CustomAttributeData_ConstructorArguments(this);
+
+ return new ReadOnlyCollection<CustomAttributeTypedArgument>(GetConstructorArguments(throwIfMissingMetadata: true));
+ }
+ }
+
+ // Equals/GetHashCode no need to override (they just implement reference equality but desktop never unified these things.)
+
+ public sealed override IList<CustomAttributeNamedArgument> NamedArguments
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.CustomAttributeData_NamedArguments(this);
+
+ return new ReadOnlyCollection<CustomAttributeNamedArgument>(GetNamedArguments(throwIfMissingMetadata: true));
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ try
+ {
+ String ctorArgs = "";
+ IList<CustomAttributeTypedArgument> constructorArguments = GetConstructorArguments(throwIfMissingMetadata: false);
+ if (constructorArguments == null)
+ return base.ToString();
+ for (int i = 0; i < constructorArguments.Count; i++)
+ ctorArgs += String.Format(i == 0 ? "{0}" : ", {0}", ComputeTypedArgumentString(constructorArguments[i], typed: false));
+
+ String namedArgs = "";
+ IList<CustomAttributeNamedArgument> namedArguments = GetNamedArguments(throwIfMissingMetadata: false);
+ if (namedArguments == null)
+ return base.ToString();
+ for (int i = 0; i < namedArguments.Count; i++)
+ {
+ CustomAttributeNamedArgument namedArgument = namedArguments[i];
+
+ // Legacy: Desktop sets "typed" to "namedArgument.ArgumentType != typeof(Object)" - on Project N, this property is not available
+ // (nor conveniently computable as it's not captured in the Project N metadata.) The only consequence is that for
+ // the rare case of fields and properties typed "Object", we won't decorate the argument value with its actual type name.
+ bool typed = true;
+ namedArgs += String.Format(
+ i == 0 && ctorArgs.Length == 0 ? "{0} = {1}" : ", {0} = {1}",
+ namedArgument.MemberName,
+ ComputeTypedArgumentString(namedArgument.TypedValue, typed));
+ }
+
+ return String.Format("[{0}({1}{2})]", AttributeTypeString, ctorArgs, namedArgs);
+ }
+ catch (MissingMetadataException)
+ {
+ return base.ToString();
+ }
+ }
+
+ internal abstract String AttributeTypeString { get; }
+
+ //
+ // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException.
+ //
+ internal abstract IList<CustomAttributeTypedArgument> GetConstructorArguments(bool throwIfMissingMetadata);
+
+ //
+ // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException.
+ //
+ internal abstract IList<CustomAttributeNamedArgument> GetNamedArguments(bool throwIfMissingMetadata);
+
+ //
+ // Computes the ToString() value for a CustomAttributeTypedArgument struct.
+ //
+ private static String ComputeTypedArgumentString(CustomAttributeTypedArgument cat, bool typed)
+ {
+ Type argumentType = cat.ArgumentType;
+ if (argumentType == null)
+ return cat.ToString();
+
+ FoundationTypes foundationTypes = argumentType.AsConfirmedRuntimeType().GetReflectionDomain().FoundationTypes;
+ Object value = cat.Value;
+ TypeInfo argumentTypeInfo = argumentType.GetTypeInfo();
+ if (argumentTypeInfo.IsEnum)
+ return String.Format(typed ? "{0}" : "({1}){0}", value, argumentType.FullName);
+
+ if (value == null)
+ return String.Format(typed ? "null" : "({0})null", argumentType.Name);
+
+ if (argumentType.Equals(foundationTypes.SystemString))
+ return String.Format("\"{0}\"", value);
+
+ if (argumentType.Equals(foundationTypes.SystemChar))
+ return String.Format("'{0}'", value);
+
+ if (argumentType.Equals(foundationTypes.SystemType))
+ return String.Format("typeof({0})", ((Type)value).FullName);
+
+ else if (argumentType.IsArray)
+ {
+ String result = null;
+ IList<CustomAttributeTypedArgument> array = value as IList<CustomAttributeTypedArgument>;
+
+ Type elementType = argumentType.GetElementType();
+ result = String.Format(@"new {0}[{1}] {{ ", elementType.GetTypeInfo().IsEnum ? elementType.FullName : elementType.Name, array.Count);
+
+ for (int i = 0; i < array.Count; i++)
+ result += String.Format(i == 0 ? "{0}" : ", {0}", ComputeTypedArgumentString(array[i], elementType != foundationTypes.SystemObject));
+
+ return result += " }";
+ }
+
+ return String.Format(typed ? "{0}" : "({1}){0}", value, argumentType.Name);
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeNormalCustomAttributeData.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeNormalCustomAttributeData.cs
new file mode 100644
index 000000000..dc6cc0456
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeNormalCustomAttributeData.cs
@@ -0,0 +1,250 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections;
+using global::System.Collections.Generic;
+using global::System.Collections.ObjectModel;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.CustomAttributes
+{
+ //
+ // The Runtime's implementation of CustomAttributeData for normal metadata-based attributes
+ //
+ internal sealed class RuntimeNormalCustomAttributeData : RuntimeCustomAttributeData
+ {
+ internal RuntimeNormalCustomAttributeData(ReflectionDomain reflectionDomain, MetadataReader reader, CustomAttributeHandle customAttributeHandle)
+ {
+ _reflectionDomain = reflectionDomain;
+ _reader = reader;
+ _customAttribute = customAttributeHandle.GetCustomAttribute(reader);
+ }
+
+ public sealed override Type AttributeType
+ {
+ get
+ {
+ Type lazyAttributeType = _lazyAttributeType;
+ if (lazyAttributeType == null)
+ {
+ lazyAttributeType = _lazyAttributeType = _reflectionDomain.Resolve(_reader, _customAttribute.Type, new TypeContext(null, null));
+ }
+ return lazyAttributeType;
+ }
+ }
+
+ internal sealed override String AttributeTypeString
+ {
+ get
+ {
+ return _customAttribute.Type.FormatTypeName(_reader, new TypeContext(null, null), _reflectionDomain);
+ }
+ }
+
+ //
+ // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException.
+ //
+ internal sealed override IList<CustomAttributeTypedArgument> GetConstructorArguments(bool throwIfMissingMetadata)
+ {
+ int index = 0;
+ LowLevelList<Handle> lazyCtorTypeHandles = null;
+ LowLevelListWithIList<CustomAttributeTypedArgument> customAttributeTypedArguments = new LowLevelListWithIList<CustomAttributeTypedArgument>();
+
+ foreach (FixedArgumentHandle fixedArgumentHandle in _customAttribute.FixedArguments)
+ {
+ CustomAttributeTypedArgument customAttributeTypedArgument =
+ ParseFixedArgument(
+ _reader,
+ fixedArgumentHandle,
+ throwIfMissingMetadata,
+ delegate ()
+ {
+ // If we got here, the custom attribute blob lacked type information (this is actually the typical case.) We must fallback to
+ // parsing the constructor's signature to get the type info.
+ if (lazyCtorTypeHandles == null)
+ {
+ IEnumerable<ParameterTypeSignatureHandle> parameterTypeSignatureHandles;
+ HandleType handleType = _customAttribute.Constructor.HandleType;
+ switch (handleType)
+ {
+ case HandleType.Method:
+ parameterTypeSignatureHandles = _customAttribute.Constructor.ToMethodHandle(_reader).GetMethod(_reader).Signature.GetMethodSignature(_reader).Parameters;
+ break;
+
+ case HandleType.MemberReference:
+ parameterTypeSignatureHandles = _customAttribute.Constructor.ToMemberReferenceHandle(_reader).GetMemberReference(_reader).Signature.ToMethodSignatureHandle(_reader).GetMethodSignature(_reader).Parameters;
+ break;
+ default:
+ throw new BadImageFormatException();
+ }
+ LowLevelList<Handle> ctorTypeHandles = new LowLevelList<Handle>();
+ foreach (ParameterTypeSignatureHandle parameterTypeSignatureHandle in parameterTypeSignatureHandles)
+ {
+ ctorTypeHandles.Add(parameterTypeSignatureHandle.GetParameterTypeSignature(_reader).Type);
+ }
+ lazyCtorTypeHandles = ctorTypeHandles;
+ }
+ Handle typeHandle = lazyCtorTypeHandles[index];
+ Exception exception = null;
+ RuntimeType argumentType = _reflectionDomain.TryResolve(_reader, typeHandle, new TypeContext(null, null), ref exception);
+ if (argumentType == null)
+ {
+ if (throwIfMissingMetadata)
+ throw exception;
+ return null;
+ }
+ return argumentType;
+ }
+ );
+
+ if (customAttributeTypedArgument.ArgumentType == null)
+ {
+ Debug.Assert(!throwIfMissingMetadata);
+ return null;
+ }
+
+ customAttributeTypedArguments.Add(customAttributeTypedArgument);
+ index++;
+ }
+
+ return customAttributeTypedArguments;
+ }
+
+ //
+ // If throwIfMissingMetadata is false, returns null rather than throwing a MissingMetadataException.
+ //
+ internal sealed override IList<CustomAttributeNamedArgument> GetNamedArguments(bool throwIfMissingMetadata)
+ {
+ LowLevelListWithIList<CustomAttributeNamedArgument> customAttributeNamedArguments = new LowLevelListWithIList<CustomAttributeNamedArgument>();
+ foreach (NamedArgumentHandle namedArgumentHandle in _customAttribute.NamedArguments)
+ {
+ NamedArgument namedArgument = namedArgumentHandle.GetNamedArgument(_reader);
+ String memberName = namedArgument.Name.GetString(_reader);
+ bool isField = (namedArgument.Flags == NamedArgumentMemberKind.Field);
+ CustomAttributeTypedArgument typedValue =
+ ParseFixedArgument(
+ _reader,
+ namedArgument.Value,
+ throwIfMissingMetadata,
+ delegate ()
+ {
+ // We got here because the custom attribute blob did not inclue type information. For named arguments, this is considered illegal metadata
+ // (ECMA always includes type info for named arguments.)
+ throw new BadImageFormatException();
+ }
+ );
+ if (typedValue.ArgumentType == null)
+ {
+ Debug.Assert(!throwIfMissingMetadata);
+ return null;
+ }
+ customAttributeNamedArguments.Add(ExtensibleCustomAttributeData.CreateCustomAttributeNamedArgument(this.AttributeType, memberName, isField, typedValue));
+ }
+ return customAttributeNamedArguments;
+ }
+
+ // Equals/GetHashCode no need to override (they just implement reference equality but desktop never unified these things.)
+
+ //
+ // Helper for parsing custom attribute arguments.
+ //
+ // If throwIfMissingMetadata is false, returns default(CustomAttributeTypedArgument) rather than throwing a MissingMetadataException.
+ //
+ private CustomAttributeTypedArgument ParseFixedArgument(MetadataReader reader, FixedArgumentHandle fixedArgumentHandle, bool throwIfMissingMetadata, Func<RuntimeType> getTypeFromConstructor)
+ {
+ FixedArgument fixedArgument = fixedArgumentHandle.GetFixedArgument(reader);
+ RuntimeType argumentType = null;
+ if (fixedArgument.Type.IsNull(reader))
+ {
+ argumentType = getTypeFromConstructor();
+ if (argumentType == null)
+ {
+ Debug.Assert(!throwIfMissingMetadata);
+ return default(CustomAttributeTypedArgument);
+ }
+ }
+ else
+ {
+ Exception exception = null;
+ argumentType = _reflectionDomain.TryResolve(reader, fixedArgument.Type, new TypeContext(null, null), ref exception);
+ if (argumentType == null)
+ {
+ if (throwIfMissingMetadata)
+ throw exception;
+ else
+ return default(CustomAttributeTypedArgument);
+ }
+ }
+
+ Object value;
+ Exception e = fixedArgument.Value.TryParseConstantValue(_reflectionDomain, reader, out value);
+ if (e != null)
+ {
+ if (throwIfMissingMetadata)
+ throw e;
+ else
+ return default(CustomAttributeTypedArgument);
+ }
+ return WrapInCustomAttributeTypedArgument(value, argumentType);
+ }
+
+ //
+ // Wrap a custom attribute argument (or an element of an array-typed custom attribute argument) in a CustomAttributeTypeArgument structure
+ // for insertion into a CustomAttributeData value.
+ //
+ private CustomAttributeTypedArgument WrapInCustomAttributeTypedArgument(Object value, Type argumentType)
+ {
+ // To support reflection domains other than the execution domain, we'll have to translate argumentType to one of the values off
+ // _reflectionDomain.FoundationTypes rather than using the direct value of value.GetType(). It's unclear how to do this for
+ // enum types. Cross that bridge if ever get to it.
+ Debug.Assert(_reflectionDomain is ExecutionDomain);
+
+ if (argumentType.Equals(typeof(Object)))
+ {
+ // If the declared attribute type is System.Object, we must report the type based on the runtime value.
+ if (value == null)
+ argumentType = typeof(String); // Why is null reported as System.String? Because that's what the desktop CLR does.
+ else if (value is Type)
+ argumentType = typeof(Type); // value.GetType() will not actually be System.Type - rather it will be some internal implementation type. We only want to report it as System.Type.
+ else
+ argumentType = value.GetType();
+ }
+
+ Array arrayValue = value as Array;
+ if (arrayValue != null)
+ {
+ if (!argumentType.IsArray)
+ throw new BadImageFormatException();
+ Type reportedElementType = argumentType.GetElementType();
+ LowLevelListWithIList<CustomAttributeTypedArgument> elementTypedArguments = new LowLevelListWithIList<CustomAttributeTypedArgument>();
+ foreach (Object elementValue in arrayValue)
+ {
+ CustomAttributeTypedArgument elementTypedArgument = WrapInCustomAttributeTypedArgument(elementValue, reportedElementType);
+ elementTypedArguments.Add(elementTypedArgument);
+ }
+ return ExtensibleCustomAttributeData.CreateCustomAttributeTypedArgument(argumentType, new ReadOnlyCollection<CustomAttributeTypedArgument>(elementTypedArguments));
+ }
+ else
+ {
+ return ExtensibleCustomAttributeData.CreateCustomAttributeTypedArgument(argumentType, value);
+ }
+ }
+
+ private ReflectionDomain _reflectionDomain;
+ private MetadataReader _reader;
+ private CustomAttribute _customAttribute;
+
+ private volatile Type _lazyAttributeType;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs
new file mode 100644
index 000000000..60894f270
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs
@@ -0,0 +1,68 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Collections.ObjectModel;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.CustomAttributes
+{
+ //
+ // The Runtime's implementation of a pseudo-CustomAttributeData.
+ //
+ internal sealed class RuntimePseudoCustomAttributeData : RuntimeCustomAttributeData
+ {
+ public RuntimePseudoCustomAttributeData(RuntimeType attributeType, IList<CustomAttributeTypedArgument> constructorArguments, IList<CustomAttributeNamedArgument> namedArguments)
+ {
+ _attributeType = attributeType;
+ if (constructorArguments == null)
+ constructorArguments = Array.Empty<CustomAttributeTypedArgument>();
+ _constructorArguments = new ReadOnlyCollection<CustomAttributeTypedArgument>(constructorArguments);
+ if (namedArguments == null)
+ namedArguments = Array.Empty<CustomAttributeNamedArgument>();
+ _namedArguments = new ReadOnlyCollection<CustomAttributeNamedArgument>(namedArguments);
+ return;
+ }
+
+ public sealed override Type AttributeType
+ {
+ get
+ {
+ return _attributeType;
+ }
+ }
+
+ internal sealed override String AttributeTypeString
+ {
+ get
+ {
+ return _attributeType.FormatTypeName();
+ }
+ }
+
+ internal sealed override IList<CustomAttributeTypedArgument> GetConstructorArguments(bool throwIfMissingMetadata)
+ {
+ return _constructorArguments;
+ }
+
+ internal sealed override IList<CustomAttributeNamedArgument> GetNamedArguments(bool throwIfMissingMetadata)
+ {
+ return _namedArguments;
+ }
+
+ // Equals/GetHashCode no need to override (they just implement reference equality but desktop never unified these things.)
+
+ private RuntimeType _attributeType;
+ private ReadOnlyCollection<CustomAttributeTypedArgument> _constructorArguments;
+ private ReadOnlyCollection<CustomAttributeNamedArgument> _namedArguments;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs
new file mode 100644
index 000000000..d542ec8e4
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // For now, this is the dispenser policy used inside S.R.R.
+ //
+ internal sealed class DefaultDispenserPolicy : DispenserPolicy
+ {
+ public sealed override DispenserAlgorithm GetAlgorithm(DispenserScenario scenario)
+ {
+#if TEST_CODEGEN_OPTIMIZATION
+ return DispenserAlgorithm.CreateAlways;
+#else
+ switch (scenario)
+ {
+ // Type.GetTypeInfo() for Runtime types.
+ case DispenserScenario.Type_TypeInfo:
+ return DispenserAlgorithm.LatchesTypeInfoInsideType;
+
+ // Metadata typedef handle to RuntimeTypeInfo
+ case DispenserScenario.TypeDef_TypeInfo:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // TypeInfo + Name to EventInfo
+ case DispenserScenario.TypeInfoAndName_EventInfo:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // TypeInfo + Name to FieldInfo
+ case DispenserScenario.TypeInfoAndName_FieldInfo:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // TypeInfo + Name to MethodInfo
+ case DispenserScenario.TypeInfoAndName_MethodInfo:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // TypeInfo + Name to PropertyInfo
+ case DispenserScenario.TypeInfoAndName_PropertyInfo:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // Assembly + NamespaceTypeName to Type
+ case DispenserScenario.AssemblyAndNamespaceTypeName_Type:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // Assembly refName to Assembly
+ case DispenserScenario.AssemblyRefName_Assembly:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ // RuntimeAssembly to CaseInsensitiveTypeDictionary
+ case DispenserScenario.RuntimeAssembly_CaseInsensitiveTypeDictionary:
+ return DispenserAlgorithm.ReuseAlways;
+
+ // Scope definition handle to RuntimeAssembly
+ case DispenserScenario.Scope_Assembly:
+ return DispenserAlgorithm.ReuseAsLongAsValueIsAlive;
+
+ default:
+ return DispenserAlgorithm.CreateAlways;
+ }
+#endif //!TEST_CODEGEN_OPTIMIZATION
+
+ }
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/Dispenser.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/Dispenser.cs
new file mode 100644
index 000000000..f8806d37d
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/Dispenser.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // Abstract base for reflection caches.
+ //
+ internal abstract class Dispenser<K, V>
+ where K : IEquatable<K>
+ where V : class
+ {
+ public abstract V GetOrAdd(K key);
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs
new file mode 100644
index 000000000..ac59b2d43
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // A parameterizable monikor for the various cache algorithms available.
+ //
+ internal sealed class DispenserAlgorithm
+ {
+ public static readonly DispenserAlgorithm CreateAlways = new DispenserAlgorithm(); // Always create a new object (i.e. no caching at all.)
+ public static readonly DispenserAlgorithm ReuseAlways = new DispenserAlgorithm(); // Every object is saved permanently (i.e. complete unification.)
+ public static readonly DispenserAlgorithm ReuseAsLongAsValueIsAlive = new DispenserAlgorithm(); // Every object is saved using weak references.
+
+ //
+ // Associates the value with key using a hash table but does not prevent key from gc'd.
+ // Restriction: The algorithm uses ConditionalWeakTable so it is subject to the following limitations:
+ // The key cannot be a value type.
+ // Keys are compared using Object.ReferenceEquals.
+ //
+ public static readonly DispenserAlgorithm ReuseAsLongAsKeyIsAlive = new DispenserAlgorithm();
+
+
+ // ONLY usable for Dispenser<RuntimeType,RuntimeTypeInfo> - RuntimeType object stores its RuntimeTypeInfo.
+ public static readonly DispenserAlgorithm LatchesTypeInfoInsideType = new DispenserAlgorithm();
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs
new file mode 100644
index 000000000..0ac772c48
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Reflection.Runtime.TypeInfos;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // Creates the appropriate Dispenser for a scenario, based on the dispenser policy.
+ //
+ internal static class DispenserFactory
+ {
+ //
+ // Note: If your K is a valuetype, use CreateDispenserV() instead. Some algorithms will not be available for use.
+ //
+ public static Dispenser<K, V> CreateDispenser<K, V>(DispenserScenario scenario, Func<K, V> factory)
+ where K : class, IEquatable<K>
+ where V : class
+ {
+ DispenserAlgorithm algorithm = _dispenserPolicy.GetAlgorithm(scenario);
+ if (algorithm == DispenserAlgorithm.ReuseAsLongAsKeyIsAlive)
+ return new DispenserThatReusesAsLongAsKeyIsAlive<K, V>(factory);
+ else
+ return CreateDispenserV<K, V>(scenario, factory);
+
+ throw new Exception();
+ }
+
+
+ //
+ // This is similar to CreateDispenser() except it doesn't constrain the key to be a reference type.
+ // As a result, some algorithms will not be available for use.
+ //
+ public static Dispenser<K, V> CreateDispenserV<K, V>(DispenserScenario scenario, Func<K, V> factory)
+ where K : IEquatable<K>
+ where V : class
+ {
+ DispenserAlgorithm algorithm = _dispenserPolicy.GetAlgorithm(scenario);
+
+ Debug.Assert(algorithm != DispenserAlgorithm.ReuseAsLongAsKeyIsAlive,
+ "Use CreateDispenser() if you want to use this algorithm. The key must not be a valuetype.");
+
+ if (algorithm == DispenserAlgorithm.CreateAlways)
+ return new DispenserThatAlwaysCreates<K, V>(factory);
+ else if (algorithm == DispenserAlgorithm.ReuseAlways)
+ return new DispenserThatAlwaysReuses<K, V>(factory);
+ else if (algorithm == DispenserAlgorithm.ReuseAsLongAsValueIsAlive)
+ return new DispenserThatReusesAsLongAsValueIsAlive<K, V>(factory);
+ else if (algorithm == DispenserAlgorithm.LatchesTypeInfoInsideType)
+ return (Dispenser<K, V>)(Object)(new DispenserThatLatchesTypeInfosInsideTypes((Func<RuntimeType, RuntimeTypeInfo>)(Object)factory));
+
+ throw new Exception();
+ }
+
+
+ private static DispenserPolicy _dispenserPolicy = new DefaultDispenserPolicy();
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs
new file mode 100644
index 000000000..527dba170
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // Base class for a policy that maps dispense scenarios to the caching algorithm used.
+ //
+ internal abstract class DispenserPolicy
+ {
+ public abstract DispenserAlgorithm GetAlgorithm(DispenserScenario scenario);
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs
new file mode 100644
index 000000000..7578bee4b
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // A monikor for each reflection cache. The name should follow the style "key" followed by underscore followed by "value".
+ //
+ internal enum DispenserScenario
+ {
+ // Type.GetTypeInfo() for Runtime types.
+ Type_TypeInfo,
+
+ // Metadata typedef handle to RuntimeTypeInfo
+ TypeDef_TypeInfo,
+
+ // TypeInfo + Name to EventInfo
+ TypeInfoAndName_EventInfo,
+
+ // TypeInfo + Name to FieldInfo
+ TypeInfoAndName_FieldInfo,
+
+ // TypeInfo + Name to MethodInfo
+ TypeInfoAndName_MethodInfo,
+
+ // TypeInfo + Name to PropertyInfo
+ TypeInfoAndName_PropertyInfo,
+
+ // Assembly + NamespaceTypeName to Type
+ AssemblyAndNamespaceTypeName_Type,
+
+ // Assembly refName to Assembly
+ AssemblyRefName_Assembly,
+
+ // RuntimeAssembly to CaseInsensitiveTypeDictionary
+ RuntimeAssembly_CaseInsensitiveTypeDictionary,
+
+ // Scope definition handle to RuntimeAssembly
+ Scope_Assembly,
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs
new file mode 100644
index 000000000..36381209a
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // This dispenser always creates things anew.
+ //
+ internal sealed class DispenserThatAlwaysCreates<K, V> : Dispenser<K, V>
+ where K : IEquatable<K>
+ where V : class
+ {
+ public DispenserThatAlwaysCreates(Func<K, V> factory)
+ {
+ _factory = factory;
+ }
+
+ public sealed override V GetOrAdd(K key)
+ {
+ return _factory(key);
+ }
+
+ private Func<K, V> _factory;
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs
new file mode 100644
index 000000000..08425b433
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Collections.Concurrent;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // This dispenser stores every instance permanently.
+ //
+ internal sealed class DispenserThatAlwaysReuses<K, V> : Dispenser<K, V>
+ where K : IEquatable<K>
+ where V : class
+ {
+ public DispenserThatAlwaysReuses(Func<K, V> factory)
+ {
+ _concurrentUnifier = new FactoryConcurrentUnifier(factory);
+ }
+
+ public sealed override V GetOrAdd(K key)
+ {
+ return _concurrentUnifier.GetOrAdd(key);
+ }
+
+ private sealed class FactoryConcurrentUnifier : ConcurrentUnifier<K, V>
+ {
+ public FactoryConcurrentUnifier(Func<K, V> factory)
+ {
+ _factory = factory;
+ }
+
+ protected sealed override V Factory(K key)
+ {
+ return _factory(key);
+ }
+
+ private Func<K, V> _factory;
+ }
+
+ private FactoryConcurrentUnifier _concurrentUnifier;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatLatchesTypeInfosInsideTypes.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatLatchesTypeInfosInsideTypes.cs
new file mode 100644
index 000000000..d5ec45aef
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatLatchesTypeInfosInsideTypes.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Reflection.Runtime.TypeInfos;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // This dispenser uses RuntimeType to store a reference to its RuntimeTypeInfo.
+ //
+ internal sealed class DispenserThatLatchesTypeInfosInsideTypes : Dispenser<RuntimeType, RuntimeTypeInfo>
+ {
+ public DispenserThatLatchesTypeInfosInsideTypes(Func<RuntimeType, RuntimeTypeInfo> factory)
+ {
+ _factory = factory;
+ }
+
+ public sealed override RuntimeTypeInfo GetOrAdd(RuntimeType key)
+ {
+ return key.InternalGetLatchedRuntimeTypeInfo<RuntimeTypeInfo>(_factory);
+ }
+
+ private Func<RuntimeType, RuntimeTypeInfo> _factory;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs
new file mode 100644
index 000000000..7b26af79b
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Runtime.CompilerServices;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ internal sealed class DispenserThatReusesAsLongAsKeyIsAlive<K, V> : Dispenser<K, V>
+ where K : class, IEquatable<K>
+ where V : class
+ {
+ public DispenserThatReusesAsLongAsKeyIsAlive(Func<K, V> factory)
+ {
+ _createValueCallback = CreateValue;
+ _conditionalWeakTable = new ConditionalWeakTable<K, V>();
+ _factory = factory;
+ }
+
+ public sealed override V GetOrAdd(K key)
+ {
+ return _conditionalWeakTable.GetValue(key, _createValueCallback);
+ }
+
+ private V CreateValue(K key)
+ {
+ return _factory(key);
+ }
+
+ private Func<K, V> _factory;
+ private ConditionalWeakTable<K, V> _conditionalWeakTable;
+ private ConditionalWeakTable<K, V>.CreateValueCallback _createValueCallback;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs
new file mode 100644
index 000000000..27f703ebf
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs
@@ -0,0 +1,3 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs
new file mode 100644
index 000000000..406ca294b
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Collections.Concurrent;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.Dispensers
+{
+ //
+ // This dispenser stores every instance using weak references.
+ //
+ internal sealed class DispenserThatReusesAsLongAsValueIsAlive<K, V> : Dispenser<K, V>
+ where K : IEquatable<K>
+ where V : class
+ {
+ public DispenserThatReusesAsLongAsValueIsAlive(Func<K, V> factory)
+ {
+ _concurrentUnifier = new FactoryConcurrentUnifierW(factory);
+ }
+
+ public sealed override V GetOrAdd(K key)
+ {
+ return _concurrentUnifier.GetOrAdd(key);
+ }
+
+ private sealed class FactoryConcurrentUnifierW : ConcurrentUnifierW<K, V>
+ {
+ public FactoryConcurrentUnifierW(Func<K, V> factory)
+ {
+ _factory = factory;
+ }
+
+ protected sealed override V Factory(K key)
+ {
+ return _factory(key);
+ }
+
+ private Func<K, V> _factory;
+ }
+
+ private FactoryConcurrentUnifierW _concurrentUnifier;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs
new file mode 100644
index 000000000..bd2faae86
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs
@@ -0,0 +1,260 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Extensibility;
+using global::Internal.Reflection.Tracing;
+
+namespace System.Reflection.Runtime.EventInfos
+{
+ //
+ // The runtime's implementation of EventInfo's
+ //
+ internal sealed partial class RuntimeEventInfo : ExtensibleEventInfo, ITraceableTypeMember
+ {
+ //
+ // eventHandle - the "tkEventDef" that identifies the event.
+ // definingType - the "tkTypeDef" that defined the field (this is where you get the metadata reader that created eventHandle.)
+ // contextType - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
+ // get your raw information from "definingType", you report "contextType" as your DeclaringType property.
+ //
+ // For example:
+ //
+ // typeof(Foo<>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType and contextType are both Foo<>
+ //
+ // typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType is "Foo<,>"
+ // The contextType is "Foo<int,String>"
+ //
+ // We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
+ //
+ private RuntimeEventInfo(EventHandle eventHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ _eventHandle = eventHandle;
+ _definingTypeInfo = definingTypeInfo;
+ _contextTypeInfo = contextTypeInfo;
+ _reader = definingTypeInfo.Reader;
+ _event = eventHandle.GetEvent(_reader);
+ }
+
+ public sealed override void AddEventHandler(Object target, Delegate handler)
+ {
+ MethodInfo addMethod = this.AddMethod;
+ if (!addMethod.IsPublic)
+ throw new InvalidOperationException(SR.InvalidOperation_NoPublicAddMethod);
+ addMethod.Invoke(target, new Object[] { handler });
+ }
+
+ public sealed override MethodInfo AddMethod
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.EventInfo_AddMethod(this);
+
+ foreach (MethodSemanticsHandle methodSemanticsHandle in _event.MethodSemantics)
+ {
+ MethodSemantics methodSemantics = methodSemanticsHandle.GetMethodSemantics(_reader);
+ if (methodSemantics.Attributes == MethodSemanticsAttributes.AddOn)
+ {
+ return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(methodSemantics.Method, _definingTypeInfo, _contextTypeInfo);
+ }
+ }
+ throw new BadImageFormatException(); // Added is a required method.
+ }
+ }
+
+ public sealed override EventAttributes Attributes
+ {
+ get
+ {
+ return _event.Flags;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.EventInfo_CustomAttributes(this);
+
+ foreach (CustomAttributeData cad in RuntimeCustomAttributeData.GetCustomAttributes(_definingTypeInfo.ReflectionDomain, _reader, _event.CustomAttributes))
+ yield return cad;
+ ExecutionDomain executionDomain = _definingTypeInfo.ReflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(_reader, _eventHandle, _definingTypeInfo.TypeDefinitionHandle))
+ yield return cad;
+ }
+ }
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.EventInfo_DeclaringType(this);
+
+ return _contextTypeInfo.AsType();
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeEventInfo other = obj as RuntimeEventInfo;
+ if (other == null)
+ return false;
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._eventHandle.Equals(other._eventHandle)))
+ return false;
+ if (!(this._contextTypeInfo.Equals(other._contextTypeInfo)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _eventHandle.GetHashCode();
+ }
+
+ public sealed override Type EventHandlerType
+ {
+ get
+ {
+ return _definingTypeInfo.ReflectionDomain.Resolve(_reader, _event.Type, _contextTypeInfo.TypeContext);
+ }
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return _definingTypeInfo.Module;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.EventInfo_Name(this);
+
+ return _event.Name.GetString(_reader);
+ }
+ }
+
+ public sealed override MethodInfo RaiseMethod
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.EventInfo_RaiseMethod(this);
+
+ foreach (MethodSemanticsHandle methodSemanticsHandle in _event.MethodSemantics)
+ {
+ MethodSemantics methodSemantics = methodSemanticsHandle.GetMethodSemantics(_reader);
+ if (methodSemantics.Attributes == MethodSemanticsAttributes.Fire)
+ {
+ return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(methodSemantics.Method, _definingTypeInfo, _contextTypeInfo);
+ }
+ }
+ return null;
+ }
+ }
+
+ public sealed override void RemoveEventHandler(Object target, Delegate handler)
+ {
+ MethodInfo removeMethod = this.RemoveMethod;
+ if (!removeMethod.IsPublic)
+ throw new InvalidOperationException(SR.InvalidOperation_NoPublicRemoveMethod);
+ removeMethod.Invoke(target, new Object[] { handler });
+ }
+
+ public sealed override MethodInfo RemoveMethod
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.EventInfo_RemoveMethod(this);
+
+ foreach (MethodSemanticsHandle methodSemanticsHandle in _event.MethodSemantics)
+ {
+ MethodSemantics methodSemantics = methodSemanticsHandle.GetMethodSemantics(_reader);
+ if (methodSemantics.Attributes == MethodSemanticsAttributes.RemoveOn)
+ {
+ return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(methodSemantics.Method, _definingTypeInfo, _contextTypeInfo);
+ }
+ }
+ throw new BadImageFormatException(); // Removed is a required method.
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ MethodInfo addMethod = this.AddMethod;
+ ParameterInfo[] parameters = addMethod.GetParameters();
+ if (parameters.Length == 0)
+ throw new InvalidOperationException(); // Legacy: Why is a ToString() intentionally throwing an exception?
+ RuntimeParameterInfo runtimeParameterInfo = (RuntimeParameterInfo)(parameters[0]);
+ return runtimeParameterInfo.ParameterTypeString + " " + this.Name;
+ }
+
+ String ITraceableTypeMember.MemberName
+ {
+ get
+ {
+ return _event.Name.GetString(_reader);
+ }
+ }
+
+ Type ITraceableTypeMember.ContainingType
+ {
+ get
+ {
+ return _contextTypeInfo.AsType();
+ }
+ }
+
+ private RuntimeEventInfo WithDebugName()
+ {
+#if DEBUG
+ if (_debugName == null)
+ {
+ _debugName = "Constructing..."; // Protect against any inadvertent reentrancy.
+ _debugName = ((ITraceableTypeMember)this).MemberName;
+ }
+#endif
+ return this;
+ }
+
+ private RuntimeNamedTypeInfo _definingTypeInfo;
+ private EventHandle _eventHandle;
+ private RuntimeTypeInfo _contextTypeInfo;
+
+ private MetadataReader _reader;
+ private Event _event;
+
+#if DEBUG
+ private String _debugName;
+#endif
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/LiteralFieldAccessor.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/LiteralFieldAccessor.cs
new file mode 100644
index 000000000..bd1bb23e0
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/LiteralFieldAccessor.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+using FieldAccessException = global::System.MemberAccessException;
+
+namespace System.Reflection.Runtime.FieldInfos
+{
+ internal sealed class LiteralFieldAccessor : FieldAccessor
+ {
+ public LiteralFieldAccessor(Object value)
+ {
+ _value = value;
+ }
+
+ public sealed override Object GetField(Object obj)
+ {
+ return _value;
+ }
+
+ public sealed override void SetField(Object obj, Object value)
+ {
+ throw new FieldAccessException(SR.Acc_ReadOnly);
+ }
+
+ private Object _value;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs
new file mode 100644
index 000000000..545d3cc03
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs
@@ -0,0 +1,256 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+
+using global::Internal.Reflection.Tracing;
+
+namespace System.Reflection.Runtime.FieldInfos
+{
+ //
+ // The Runtime's implementation of fields.
+ //
+ internal sealed partial class RuntimeFieldInfo : ExtensibleFieldInfo, ITraceableTypeMember
+ {
+ //
+ // fieldHandle - the "tkFieldDef" that identifies the field.
+ // definingType - the "tkTypeDef" that defined the field (this is where you get the metadata reader that created fieldHandle.)
+ // contextType - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
+ // get your raw information from "definingType", you report "contextType" as your DeclaringType property.
+ //
+ // For example:
+ //
+ // typeof(Foo<>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType and contextType are both Foo<>
+ //
+ // typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType is "Foo<,>"
+ // The contextType is "Foo<int,String>"
+ //
+ // We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
+ //
+ private RuntimeFieldInfo(FieldHandle fieldHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ _fieldHandle = fieldHandle;
+ _definingTypeInfo = definingTypeInfo;
+ _contextTypeInfo = contextTypeInfo;
+ _reader = definingTypeInfo.Reader;
+ _field = fieldHandle.GetField(_reader);
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.FieldInfo_CustomAttributes(this);
+
+ ReflectionDomain reflectionDomain = _definingTypeInfo.ReflectionDomain;
+ IEnumerable<CustomAttributeData> customAttributes = RuntimeCustomAttributeData.GetCustomAttributes(reflectionDomain, _reader, _field.CustomAttributes);
+ foreach (CustomAttributeData cad in customAttributes)
+ yield return cad;
+ ExecutionDomain executionDomain = _definingTypeInfo.ReflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(_reader, _fieldHandle, _definingTypeInfo.TypeDefinitionHandle))
+ yield return cad;
+ }
+ }
+ }
+
+ public sealed override FieldAttributes Attributes
+ {
+ get
+ {
+ return _field.Flags;
+ }
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.FieldInfo_DeclaringType(this);
+
+ return _contextTypeInfo.AsType();
+ }
+ }
+
+ public sealed override Type FieldType
+ {
+ get
+ {
+ return this.FieldRuntimeType;
+ }
+ }
+
+ public sealed override Object GetValue(Object obj)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.FieldInfo_GetValue(this, obj);
+
+ FieldAccessor fieldAccessor = this.FieldAccessor;
+ return fieldAccessor.GetField(obj);
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return _definingTypeInfo.Module;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.FieldInfo_Name(this);
+
+ return _field.Name.GetString(_reader);
+ }
+ }
+
+ public sealed override void SetValue(Object obj, Object value)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.FieldInfo_SetValue(this, obj, value);
+
+ FieldAccessor fieldAccessor = this.FieldAccessor;
+ fieldAccessor.SetField(obj, value);
+ }
+
+ public sealed override String ToString()
+ {
+ TypeContext typeContext = _contextTypeInfo.TypeContext;
+ Handle typeHandle = _field.Signature.GetFieldSignature(_reader).Type;
+ return typeHandle.FormatTypeName(_reader, typeContext, _definingTypeInfo.ReflectionDomain) + " " + this.Name;
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeFieldInfo other = obj as RuntimeFieldInfo;
+ if (other == null)
+ return false;
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._fieldHandle.Equals(other._fieldHandle)))
+ return false;
+ if (!(this._contextTypeInfo.Equals(other._contextTypeInfo)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _fieldHandle.GetHashCode();
+ }
+
+ String ITraceableTypeMember.MemberName
+ {
+ get
+ {
+ return _field.Name.GetString(_reader);
+ }
+ }
+
+ Type ITraceableTypeMember.ContainingType
+ {
+ get
+ {
+ return _contextTypeInfo.AsType();
+ }
+ }
+
+ private FieldAccessor FieldAccessor
+ {
+ get
+ {
+ FieldAccessor fieldAccessor = _lazyFieldAccessor;
+ if (fieldAccessor == null)
+ {
+ if (this.IsLiteral)
+ {
+ if (!(_definingTypeInfo.ReflectionDomain is ExecutionDomain))
+ throw new NotSupportedException(); // Cannot instantiate a boxed enum on a non-execution domain.
+ // Legacy: ECMA335 does not require that the metadata literal match the type of the field that declares it.
+ // For desktop compat, we return the metadata literal as is and do not attempt to convert or validate against the Field type.
+
+ Object defaultValue;
+ if (!ReflectionCoreExecution.ExecutionEnvironment.GetDefaultValueIfAny(
+ _reader,
+ _fieldHandle,
+ this.FieldType,
+ this.CustomAttributes,
+ out defaultValue))
+ {
+ throw new BadImageFormatException(); // Field marked literal but has no default value.
+ }
+
+ _lazyFieldAccessor = fieldAccessor = new LiteralFieldAccessor(defaultValue);
+ }
+ else
+ {
+ _lazyFieldAccessor = fieldAccessor = ReflectionCoreExecution.ExecutionEnvironment.TryGetFieldAccessor(this.DeclaringType.TypeHandle, this.FieldType.TypeHandle, _fieldHandle);
+ if (fieldAccessor == null)
+ throw this._definingTypeInfo.ReflectionDomain.CreateNonInvokabilityException(this);
+ }
+ }
+ return fieldAccessor;
+ }
+ }
+
+ private RuntimeType FieldRuntimeType
+ {
+ get
+ {
+ TypeContext typeContext = _contextTypeInfo.TypeContext;
+ Handle typeHandle = _field.Signature.GetFieldSignature(_reader).Type;
+ return _definingTypeInfo.ReflectionDomain.Resolve(_reader, typeHandle, typeContext);
+ }
+ }
+
+ private RuntimeFieldInfo WithDebugName()
+ {
+#if DEBUG
+ if (_debugName == null)
+ {
+ _debugName = "Constructing..."; // Protect against any inadvertent reentrancy.
+ _debugName = ((ITraceableTypeMember)this).MemberName;
+ }
+#endif
+ return this;
+ }
+
+ private RuntimeNamedTypeInfo _definingTypeInfo;
+ private FieldHandle _fieldHandle;
+ private RuntimeTypeInfo _contextTypeInfo;
+
+ private MetadataReader _reader;
+ private Field _field;
+
+ private volatile FieldAccessor _lazyFieldAccessor = null;
+
+#if DEBUG
+ private String _debugName;
+#endif
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs
new file mode 100644
index 000000000..16e80353e
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs
@@ -0,0 +1,405 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Reflection;
+using System.Diagnostics;
+using System.Reflection.Runtime.Types;
+using System.Reflection.Runtime.TypeInfos;
+
+using Internal.Reflection.Core;
+
+namespace System.Reflection.Runtime.General
+{
+ internal static class Assignability
+ {
+ public static bool IsAssignableFrom(TypeInfo toTypeInfo, TypeInfo fromTypeInfo, FoundationTypes foundationTypes)
+ {
+ if (toTypeInfo == null)
+ throw new NullReferenceException();
+ if (fromTypeInfo == null)
+ return false; // It would be more appropriate to throw ArgumentNullException here, but returning "false" is the desktop-compat behavior.
+
+ if (fromTypeInfo.Equals(toTypeInfo))
+ return true;
+
+ if (toTypeInfo.IsGenericTypeDefinition)
+ {
+ // Asking whether something can cast to a generic type definition is arguably meaningless. The desktop CLR Reflection layer converts all
+ // generic type definitions to generic type instantiations closed over the formal generic type parameters. The .NET Native framework
+ // keeps the two separate. Fortunately, under either interpretation, returning "false" unless the two types are identical is still a
+ // defensible behavior. To avoid having the rest of the code deal with the differing interpretations, we'll short-circuit this now.
+ return false;
+ }
+
+ if (fromTypeInfo.IsGenericTypeDefinition)
+ {
+ // The desktop CLR Reflection layer converts all generic type definitions to generic type instantiations closed over the formal
+ // generic type parameters. The .NET Native framework keeps the two separate. For the purpose of IsAssignableFrom(),
+ // it makes sense to unify the two for the sake of backward compat. We'll just make the transform here so that the rest of code
+ // doesn't need to know about this quirk.
+ fromTypeInfo = fromTypeInfo.GetGenericTypeDefinition().MakeGenericType(fromTypeInfo.GenericTypeParameters).GetTypeInfo();
+ }
+
+ if (fromTypeInfo.CanCastTo(toTypeInfo, foundationTypes))
+ return true;
+
+ Type toType = toTypeInfo.AsType();
+ Type fromType = fromTypeInfo.AsType();
+
+ // Desktop compat: IsAssignableFrom() considers T as assignable to Nullable<T> (but does not check if T is a generic parameter.)
+ if (!fromType.IsGenericParameter)
+ {
+ Type nullableUnderlyingType = Nullable.GetUnderlyingType(toType);
+ if (nullableUnderlyingType != null && nullableUnderlyingType.Equals(fromType))
+ return true;
+ }
+ return false;
+ }
+
+ private static bool CanCastTo(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes)
+ {
+ if (fromTypeInfo.Equals(toTypeInfo))
+ return true;
+
+ if (fromTypeInfo.IsArray)
+ {
+ if (toTypeInfo.IsInterface)
+ return fromTypeInfo.CanCastArrayToInterface(toTypeInfo, foundationTypes);
+
+ Type toType = toTypeInfo.AsType();
+ if (fromTypeInfo.IsSubclassOf(toType))
+ return true; // T[] is castable to Array or Object.
+
+ if (!toTypeInfo.IsArray)
+ return false;
+
+ int rank = fromTypeInfo.GetArrayRank();
+ if (rank != toTypeInfo.GetArrayRank())
+ return false;
+
+ bool fromTypeIsSzArray = fromTypeInfo.IsSzArray(foundationTypes);
+ bool toTypeIsSzArray = toTypeInfo.IsSzArray(foundationTypes);
+ if (fromTypeIsSzArray != toTypeIsSzArray)
+ {
+ // T[] is assignable to T[*] but not vice-versa.
+ if (!(rank == 1 && !toTypeIsSzArray))
+ {
+ return false; // T[*] is not castable to T[]
+ }
+ }
+
+ TypeInfo toElementTypeInfo = toTypeInfo.GetElementType().GetTypeInfo();
+ TypeInfo fromElementTypeInfo = fromTypeInfo.GetElementType().GetTypeInfo();
+ return fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo, foundationTypes);
+ }
+
+ if (fromTypeInfo.IsByRef)
+ {
+ if (!toTypeInfo.IsByRef)
+ return false;
+
+ TypeInfo toElementTypeInfo = toTypeInfo.GetElementType().GetTypeInfo();
+ TypeInfo fromElementTypeInfo = fromTypeInfo.GetElementType().GetTypeInfo();
+ return fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo, foundationTypes);
+ }
+
+ if (fromTypeInfo.IsPointer)
+ {
+ Type toType = toTypeInfo.AsType();
+ if (toType.Equals(foundationTypes.SystemObject))
+ return true; // T* is castable to Object.
+
+ if (toType.Equals(foundationTypes.SystemUIntPtr))
+ return true; // T* is castable to UIntPtr (but not IntPtr)
+
+ if (!toTypeInfo.IsPointer)
+ return false;
+
+ TypeInfo toElementTypeInfo = toTypeInfo.GetElementType().GetTypeInfo();
+ TypeInfo fromElementTypeInfo = fromTypeInfo.GetElementType().GetTypeInfo();
+ return fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo, foundationTypes);
+ }
+
+ if (fromTypeInfo.IsGenericParameter)
+ {
+ //
+ // A generic parameter can be cast to any of its constraints, or object, if none are specified, or ValueType if the "struct" constraint is
+ // specified.
+ //
+ // This has to be coded as its own case as TypeInfo.BaseType on a generic parameter doesn't always return what you'd expect.
+ //
+ Type toType = toTypeInfo.AsType();
+ if (toType.Equals(foundationTypes.SystemObject))
+ return true;
+
+ if (toType.Equals(foundationTypes.SystemValueType))
+ {
+ GenericParameterAttributes attributes = fromTypeInfo.GenericParameterAttributes;
+ if ((attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+ return true;
+ }
+
+ foreach (Type constraintType in fromTypeInfo.GetGenericParameterConstraints())
+ {
+ if (constraintType.GetTypeInfo().CanCastTo(toTypeInfo, foundationTypes))
+ return true;
+ }
+
+ return false;
+ }
+
+ if (toTypeInfo.IsArray || toTypeInfo.IsByRef || toTypeInfo.IsPointer || toTypeInfo.IsGenericParameter)
+ return false;
+
+ if (fromTypeInfo.MatchesWithVariance(toTypeInfo, foundationTypes))
+ return true;
+
+ if (toTypeInfo.IsInterface)
+ {
+ foreach (Type ifc in fromTypeInfo.ImplementedInterfaces)
+ {
+ if (ifc.GetTypeInfo().MatchesWithVariance(toTypeInfo, foundationTypes))
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ // Interfaces are always castable to System.Object. The code below will not catch this as interfaces report their BaseType as null.
+ if (toTypeInfo.AsType().Equals(foundationTypes.SystemObject) && fromTypeInfo.IsInterface)
+ return true;
+
+ TypeInfo walk = fromTypeInfo;
+ for (;;)
+ {
+ Type baseType = walk.BaseType;
+ if (baseType == null)
+ return false;
+ walk = baseType.GetTypeInfo();
+ if (walk.MatchesWithVariance(toTypeInfo, foundationTypes))
+ return true;
+ }
+ }
+ }
+
+ private static bool IsSzArray(this TypeInfo typeInfo, FoundationTypes foundationTypes)
+ {
+ if (!typeInfo.IsArray)
+ return false;
+
+ if (typeInfo.GetArrayRank() != 1)
+ return false;
+
+ if (((RuntimeTypeInfo)typeInfo).RuntimeType.InternalIsMultiDimArray)
+ return false;
+
+ return true;
+ }
+
+ //
+ // Check a base type or implemented interface type for equivalence (taking into account variance for generic instantiations.)
+ // Does not check ancestors recursively.
+ //
+ private static bool MatchesWithVariance(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes)
+ {
+ Debug.Assert(!(fromTypeInfo.IsArray || fromTypeInfo.IsByRef || fromTypeInfo.IsPointer || fromTypeInfo.IsGenericParameter));
+ Debug.Assert(!(toTypeInfo.IsArray || toTypeInfo.IsByRef || toTypeInfo.IsPointer || toTypeInfo.IsGenericParameter));
+
+ if (fromTypeInfo.Equals(toTypeInfo))
+ return true;
+
+ if (!(fromTypeInfo.AsType().IsConstructedGenericType && toTypeInfo.AsType().IsConstructedGenericType))
+ return false;
+
+ TypeInfo genericTypeDefinition = fromTypeInfo.GetGenericTypeDefinition().GetTypeInfo();
+ if (!genericTypeDefinition.AsType().Equals(toTypeInfo.GetGenericTypeDefinition()))
+ return false;
+
+ Type[] fromTypeArguments = fromTypeInfo.GenericTypeArguments;
+ Type[] toTypeArguments = toTypeInfo.GenericTypeArguments;
+ Type[] genericTypeParameters = genericTypeDefinition.GenericTypeParameters;
+ for (int i = 0; i < genericTypeParameters.Length; i++)
+ {
+ TypeInfo fromTypeArgumentInfo = fromTypeArguments[i].GetTypeInfo();
+ TypeInfo toTypeArgumentInfo = toTypeArguments[i].GetTypeInfo();
+
+ GenericParameterAttributes attributes = genericTypeParameters[i].GetTypeInfo().GenericParameterAttributes;
+ switch (attributes & GenericParameterAttributes.VarianceMask)
+ {
+ case GenericParameterAttributes.Covariant:
+ if (!(fromTypeArgumentInfo.IsGcReferenceTypeAndCastableTo(toTypeArgumentInfo, foundationTypes)))
+ return false;
+ break;
+
+ case GenericParameterAttributes.Contravariant:
+ if (!(toTypeArgumentInfo.IsGcReferenceTypeAndCastableTo(fromTypeArgumentInfo, foundationTypes)))
+ return false;
+ break;
+
+ case GenericParameterAttributes.None:
+ if (!(fromTypeArgumentInfo.Equals(toTypeArgumentInfo)))
+ return false;
+ break;
+
+ default:
+ throw new BadImageFormatException(); // Unexpected variance value in metadata.
+ }
+ }
+ return true;
+ }
+
+ //
+ // A[] can cast to B[] if one of the following are true:
+ //
+ // A can cast to B under variance rules.
+ //
+ // A and B are both integers or enums and have the same reduced type (i.e. represent the same-sized integer, ignoring signed/unsigned differences.)
+ // "char" is not interchangable with short/ushort. "bool" is not interchangable with byte/sbyte.
+ //
+ // For desktop compat, A& and A* follow the same rules.
+ //
+ private static bool IsElementTypeCompatibleWith(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes)
+ {
+ if (fromTypeInfo.IsGcReferenceTypeAndCastableTo(toTypeInfo, foundationTypes))
+ return true;
+
+ Type reducedFromType = fromTypeInfo.AsType().ReducedType(foundationTypes);
+ Type reducedToType = toTypeInfo.AsType().ReducedType(foundationTypes);
+ if (reducedFromType.Equals(reducedToType))
+ return true;
+
+ return false;
+ }
+
+ private static Type ReducedType(this Type t, FoundationTypes foundationTypes)
+ {
+ if (t.GetTypeInfo().IsEnum)
+ t = Enum.GetUnderlyingType(t);
+
+ if (t.Equals(foundationTypes.SystemByte))
+ return foundationTypes.SystemSByte;
+
+ if (t.Equals(foundationTypes.SystemUInt16))
+ return foundationTypes.SystemInt16;
+
+ if (t.Equals(foundationTypes.SystemUInt32))
+ return foundationTypes.SystemInt32;
+
+ if (t.Equals(foundationTypes.SystemUInt64))
+ return foundationTypes.SystemInt64;
+
+ if (t.Equals(foundationTypes.SystemUIntPtr) || t.Equals(foundationTypes.SystemIntPtr))
+ {
+#if WIN64
+ return foundationTypes.SystemInt64;
+#else
+ return foundationTypes.SystemInt32;
+#endif
+ }
+
+ return t;
+ }
+
+ //
+ // Contra/CoVariance.
+ //
+ // IEnumerable<D> can cast to IEnumerable<B> if D can cast to B and if there's no possibility that D is a value type.
+ //
+ private static bool IsGcReferenceTypeAndCastableTo(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes)
+ {
+ if (fromTypeInfo.Equals(toTypeInfo))
+ return true;
+
+ if (fromTypeInfo.ProvablyAGcReferenceType(foundationTypes))
+ return fromTypeInfo.CanCastTo(toTypeInfo, foundationTypes);
+
+ return false;
+ }
+
+ //
+ // A true result indicates that a type can never be a value type. This is important when testing variance-compatibility.
+ //
+ private static bool ProvablyAGcReferenceType(this TypeInfo t, FoundationTypes foundationTypes)
+ {
+ if (t.IsGenericParameter)
+ {
+ GenericParameterAttributes attributes = t.GenericParameterAttributes;
+ if ((attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
+ return true; // generic parameter with a "class" constraint.
+ }
+
+ return t.ProvablyAGcReferenceTypeHelper(foundationTypes);
+ }
+
+ private static bool ProvablyAGcReferenceTypeHelper(this TypeInfo t, FoundationTypes foundationTypes)
+ {
+ if (t.IsArray)
+ return true;
+
+ if (t.IsByRef || t.IsPointer)
+ return false;
+
+ if (t.IsGenericParameter)
+ {
+ // We intentionally do not check for a "class" constraint on generic parameter ancestors.
+ // That's because this property does not propagate up the constraining hierarchy.
+ // (e.g. "class A<S, T> where S : T, where T : class" does not guarantee that S is a class.)
+
+ foreach (Type constraintType in t.GetGenericParameterConstraints())
+ {
+ if (constraintType.GetTypeInfo().ProvablyAGcReferenceTypeHelper(foundationTypes))
+ return true;
+ }
+ return false;
+ }
+
+ return t.IsClass && !t.Equals(foundationTypes.SystemObject) && !t.Equals(foundationTypes.SystemValueType) && !t.Equals(foundationTypes.SystemEnum);
+ }
+
+ //
+ // T[] casts to IList<T>. This could be handled by the normal ancestor-walking code
+ // but for one complication: T[] also casts to IList<U> if T[] casts to U[].
+ //
+ private static bool CanCastArrayToInterface(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes)
+ {
+ Debug.Assert(fromTypeInfo.IsArray);
+ Debug.Assert(toTypeInfo.IsInterface);
+
+ Type toType = toTypeInfo.AsType();
+
+ if (toType.IsConstructedGenericType)
+ {
+ Type[] toTypeGenericTypeArguments = toTypeInfo.GenericTypeArguments;
+ if (toTypeGenericTypeArguments.Length != 1)
+ return false;
+ TypeInfo toElementTypeInfo = toTypeGenericTypeArguments[0].GetTypeInfo();
+
+ Type toTypeGenericTypeDefinition = toTypeInfo.GetGenericTypeDefinition();
+ TypeInfo fromElementTypeInfo = fromTypeInfo.GetElementType().GetTypeInfo();
+ foreach (Type ifc in fromTypeInfo.ImplementedInterfaces)
+ {
+ if (ifc.IsConstructedGenericType)
+ {
+ Type ifcGenericTypeDefinition = ifc.GetGenericTypeDefinition();
+ if (ifcGenericTypeDefinition.Equals(toTypeGenericTypeDefinition))
+ {
+ if (fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo, foundationTypes))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ else
+ {
+ foreach (Type ifc in fromTypeInfo.ImplementedInterfaces)
+ {
+ if (ifc.Equals(toType))
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
new file mode 100644
index 000000000..9da335371
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
@@ -0,0 +1,614 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.IO;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.Dispensers;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.PropertyInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+
+using global::Internal.Metadata.NativeFormat;
+
+//=================================================================================================================
+// This file collects the various chokepoints that create the various Runtime*Info objects. This allows
+// easy reviewing of the overall caching and unification policy.
+//
+// The dispenser functions are defined as static members of the associated Info class. This permits us
+// to keep the constructors private to ensure that these really are the only ways to obtain these objects.
+//=================================================================================================================
+
+namespace System.Reflection.Runtime.Assemblies
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // Assemblies (maps 1-1 with a MetadataReader/ScopeDefinitionHandle.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeAssembly : ExtensibleAssembly
+ {
+ internal static RuntimeAssembly GetRuntimeAssembly(ReflectionDomain reflectionDomain, RuntimeAssemblyName assemblyRefName)
+ {
+ RuntimeAssembly result;
+ Exception assemblyLoadException = TryGetRuntimeAssembly(reflectionDomain, assemblyRefName, out result);
+ if (assemblyLoadException != null)
+ throw assemblyLoadException;
+ return result;
+ }
+
+ internal static Exception TryGetRuntimeAssembly(ReflectionDomain reflectionDomain, RuntimeAssemblyName assemblyRefName, out RuntimeAssembly result)
+ {
+ Debug.Assert(reflectionDomain == ReflectionCoreExecution.ExecutionDomain, "User Reflection Domains not yet implemented.");
+ result = _assemblyRefNameToAssemblyDispenser.GetOrAdd(assemblyRefName);
+ if (result != null)
+ return null;
+ else
+ return new FileNotFoundException(SR.Format(SR.FileNotFound_AssemblyNotFound, assemblyRefName.FullName));
+ }
+
+ private static Dispenser<RuntimeAssemblyName, RuntimeAssembly> _assemblyRefNameToAssemblyDispenser =
+ DispenserFactory.CreateDispenser<RuntimeAssemblyName, RuntimeAssembly>(
+ DispenserScenario.AssemblyRefName_Assembly,
+ delegate (RuntimeAssemblyName assemblyRefName)
+ {
+ ReflectionDomain reflectionDomain = ReflectionCoreExecution.ExecutionDomain; //@todo: Need to use the correct reflection domain!
+ AssemblyBinder binder = reflectionDomain.ReflectionDomainSetup.AssemblyBinder;
+ AssemblyName convertedAssemblyRefName = assemblyRefName.ToAssemblyName();
+ MetadataReader reader;
+ ScopeDefinitionHandle scope;
+ Exception exception;
+ IEnumerable<QScopeDefinition> overflowScopes;
+ if (!binder.Bind(convertedAssemblyRefName, out reader, out scope, out overflowScopes, out exception))
+ return null;
+ return GetRuntimeAssembly(reader, scope, overflowScopes, reflectionDomain);
+ }
+ );
+
+
+ private static RuntimeAssembly GetRuntimeAssembly(MetadataReader reader, ScopeDefinitionHandle scope, IEnumerable<QScopeDefinition> overflows, ReflectionDomain reflectionDomain)
+ {
+ return _scopeToAssemblyDispenser.GetOrAdd(new RuntimeAssemblyKey(reader, scope, overflows));
+ }
+
+ private static Dispenser<RuntimeAssemblyKey, RuntimeAssembly> _scopeToAssemblyDispenser =
+ DispenserFactory.CreateDispenserV<RuntimeAssemblyKey, RuntimeAssembly>(
+ DispenserScenario.Scope_Assembly,
+ delegate (RuntimeAssemblyKey qScopeDefinition)
+ {
+ return new RuntimeAssembly(qScopeDefinition.Reader, qScopeDefinition.Handle, qScopeDefinition.Overflows);
+ }
+ );
+
+ //-----------------------------------------------------------------------------------------------------------
+ // Captures a qualified scope (a reader plus a handle) representing the canonical definition of an assembly,
+ // plus a set of "overflow" scopes representing additional pieces of the assembly.
+ //-----------------------------------------------------------------------------------------------------------
+ private struct RuntimeAssemblyKey : IEquatable<RuntimeAssemblyKey>
+ {
+ public RuntimeAssemblyKey(MetadataReader reader, ScopeDefinitionHandle handle, IEnumerable<QScopeDefinition> overflows)
+ {
+ _reader = reader;
+ _handle = handle;
+ _overflows = overflows;
+ }
+
+ public MetadataReader Reader { get { return _reader; } }
+ public ScopeDefinitionHandle Handle { get { return _handle; } }
+ public IEnumerable<QScopeDefinition> Overflows { get { return _overflows; } }
+ public ScopeDefinition ScopeDefinition
+ {
+ get
+ {
+ return _handle.GetScopeDefinition(_reader);
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is RuntimeAssemblyKey))
+ return false;
+ return Equals((RuntimeAssemblyKey)obj);
+ }
+
+
+ public bool Equals(RuntimeAssemblyKey other)
+ {
+ // Equality depends only on the canonical definition of an assembly, not
+ // the overflows.
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._handle.Equals(other._handle)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _handle.GetHashCode();
+ }
+
+ private readonly MetadataReader _reader;
+ private readonly ScopeDefinitionHandle _handle;
+ private readonly IEnumerable<QScopeDefinition> _overflows;
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.Modules
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // Modules (these exist only because Modules still exist in the Win8P surface area. There is a 1-1
+ // mapping between Assemblies and Modules.)
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeModule : ExtensibleModule
+ {
+ internal static RuntimeModule GetRuntimeModule(RuntimeAssembly assembly)
+ {
+ return new RuntimeModule(assembly);
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos in general.
+ //-----------------------------------------------------------------------------------------------------------
+ internal abstract partial class RuntimeTypeInfo : ExtensibleTypeInfo
+ {
+ internal static RuntimeTypeInfo GetRuntimeTypeInfo(RuntimeType runtimeType)
+ {
+ RuntimeTypeInfo runtimeTypeInfo = _typeToTypeInfoDispenser.GetOrAdd(runtimeType);
+#if DEBUG
+ if (runtimeType != null)
+ runtimeTypeInfo.EstablishDebugName();
+#endif
+ return runtimeTypeInfo;
+ }
+
+ private static Dispenser<RuntimeType, RuntimeTypeInfo> _typeToTypeInfoDispenser =
+ DispenserFactory.CreateDispenser<RuntimeType, RuntimeTypeInfo>(DispenserScenario.Type_TypeInfo, CreateRuntimeTypeInfo);
+
+ private static RuntimeTypeInfo CreateRuntimeTypeInfo(RuntimeType runtimeType)
+ {
+ if (runtimeType.HasElementType)
+ {
+ if (runtimeType.IsArray)
+ return RuntimeArrayTypeInfo.GetRuntimeArrayTypeInfo(runtimeType);
+ else
+ return RuntimeHasElementTypeInfo.GetRuntimeHasElementypeInfo(runtimeType);
+ }
+ else if (runtimeType.IsConstructedGenericType)
+ {
+ RuntimeTypeHandle typeHandle;
+ if (runtimeType.InternalTryGetTypeHandle(out typeHandle) && ReflectionCoreExecution.ExecutionEnvironment.IsReflectionBlocked(typeHandle))
+ return RuntimeBlockedTypeInfo.GetRuntimeBlockedTypeInfo(runtimeType);
+ return RuntimeConstructedGenericTypeInfo.GetRuntimeConstructedGenericTypeInfo(runtimeType);
+ }
+ else
+ {
+ RuntimeInspectionOnlyNamedType inspectionOnlyNamedType = runtimeType as RuntimeInspectionOnlyNamedType;
+ if (inspectionOnlyNamedType != null)
+ {
+ return inspectionOnlyNamedType.GetInspectionOnlyNamedRuntimeTypeInfo();
+ }
+ else
+ {
+ RuntimeGenericParameterType genericParameterType = runtimeType as RuntimeGenericParameterType;
+ if (genericParameterType != null)
+ {
+ return RuntimeGenericParameterTypeInfo.GetRuntimeGenericParameterTypeInfo(genericParameterType);
+ }
+ else
+ {
+ MetadataReader reader;
+ TypeDefinitionHandle typeDefHandle;
+ if (ReflectionCoreExecution.ExecutionEnvironment.TryGetMetadataForNamedType(runtimeType.TypeHandle, out reader, out typeDefHandle))
+ return RuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(reader, typeDefHandle);
+ if (ReflectionCoreExecution.ExecutionEnvironment.IsReflectionBlocked(runtimeType.TypeHandle))
+ return RuntimeBlockedTypeInfo.GetRuntimeBlockedTypeInfo(runtimeType);
+ else
+ return RuntimeNoMetadataNamedTypeInfo.GetRuntimeNoMetadataNamedTypeInfo(runtimeType);
+ }
+ }
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos for type definitions (i.e. "Foo" and "Foo<>" but not "Foo<int>")
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeNamedTypeInfo : RuntimeTypeInfo
+ {
+ internal static RuntimeNamedTypeInfo GetRuntimeNamedTypeInfo(MetadataReader metadataReader, TypeDefinitionHandle typeDefHandle)
+ {
+ return _typeDefToRuntimeTypeInfoDispenser.GetOrAdd(new QTypeDefinition(metadataReader, typeDefHandle));
+ }
+
+ private static Dispenser<QTypeDefinition, RuntimeNamedTypeInfo> _typeDefToRuntimeTypeInfoDispenser =
+ DispenserFactory.CreateDispenserV<QTypeDefinition, RuntimeNamedTypeInfo>(
+ DispenserScenario.TypeDef_TypeInfo,
+ delegate (QTypeDefinition qTypeDefinition)
+ {
+ return new RuntimeNamedTypeInfo(qTypeDefinition.Reader, qTypeDefinition.Handle);
+ }
+ );
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos for type definitions (i.e. "Foo" and "Foo<>" but not "Foo<int>") that aren't opted into metadata.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeNoMetadataNamedTypeInfo : RuntimeTypeInfo
+ {
+ internal static RuntimeNoMetadataNamedTypeInfo GetRuntimeNoMetadataNamedTypeInfo(RuntimeType runtimeType)
+ {
+ return new RuntimeNoMetadataNamedTypeInfo(runtimeType);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos that represent type definitions (i.e. Foo or Foo<>) or constructed generic types (Foo<int>)
+ // that can never be reflection-enabled due to the framework Reflection block.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeBlockedTypeInfo : RuntimeTypeInfo
+ {
+ internal static RuntimeBlockedTypeInfo GetRuntimeBlockedTypeInfo(RuntimeType runtimeType)
+ {
+ return new RuntimeBlockedTypeInfo(runtimeType);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos for Array, Pointer and ByRef types.
+ //-----------------------------------------------------------------------------------------------------------
+ internal partial class RuntimeHasElementTypeInfo : RuntimeTypeInfo
+ {
+ internal static RuntimeHasElementTypeInfo GetRuntimeHasElementypeInfo(RuntimeType hasElementType)
+ {
+ return new RuntimeHasElementTypeInfo(hasElementType);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos for Array types.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeArrayTypeInfo : RuntimeHasElementTypeInfo
+ {
+ internal static RuntimeArrayTypeInfo GetRuntimeArrayTypeInfo(RuntimeType hasElementType)
+ {
+ return new RuntimeArrayTypeInfo(hasElementType);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos for Constructed generic types ("Foo<int>")
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeConstructedGenericTypeInfo : RuntimeTypeInfo
+ {
+ internal static RuntimeConstructedGenericTypeInfo GetRuntimeConstructedGenericTypeInfo(RuntimeType runtimeConstructedGenericType)
+ {
+ return new RuntimeConstructedGenericTypeInfo(runtimeConstructedGenericType);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // TypeInfos for Generic type parameters (for both types and methods.)
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeGenericParameterTypeInfo : RuntimeTypeInfo
+ {
+ internal static RuntimeGenericParameterTypeInfo GetRuntimeGenericParameterTypeInfo(RuntimeGenericParameterType runtimeGenericParameterType)
+ {
+ return new RuntimeGenericParameterTypeInfo(runtimeGenericParameterType);
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.Types
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // Types for named types that don't have EETypes.
+ //-----------------------------------------------------------------------------------------------------------
+ internal partial class RuntimeInspectionOnlyNamedType : RuntimeType
+ {
+ internal static RuntimeInspectionOnlyNamedType GetRuntimeInspectionOnlyNamedType(MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle)
+ {
+ return new RuntimeInspectionOnlyNamedType(reader, typeDefinitionHandle);
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.FieldInfos
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // FieldInfos
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeFieldInfo : ExtensibleFieldInfo
+ {
+ internal static RuntimeFieldInfo GetRuntimeFieldInfo(FieldHandle fieldHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ return new RuntimeFieldInfo(fieldHandle, definingTypeInfo, contextTypeInfo).WithDebugName();
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // ConstructorInfos
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimePlainConstructorInfo : RuntimeConstructorInfo
+ {
+ internal static RuntimePlainConstructorInfo GetRuntimePlainConstructorInfo(MethodHandle methodHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ return new RuntimePlainConstructorInfo(methodHandle, definingTypeInfo, contextTypeInfo);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // Constructors for array types.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeSyntheticConstructorInfo : RuntimeConstructorInfo
+ {
+ internal static RuntimeSyntheticConstructorInfo GetRuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeType declaringType, RuntimeType[] runtimeParameterTypesAndReturn, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ {
+ return new RuntimeSyntheticConstructorInfo(syntheticMethodId, declaringType, runtimeParameterTypesAndReturn, options, invoker);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // MethodInfos for method definitions (i.e. Foo.Moo() or Foo.Moo<>() but not Foo.Moo<int>)
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeNamedMethodInfo : RuntimeMethodInfo
+ {
+ internal static RuntimeNamedMethodInfo GetRuntimeNamedMethodInfo(MethodHandle methodHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ RuntimeNamedMethodInfo method = new RuntimeNamedMethodInfo(methodHandle, definingTypeInfo, contextTypeInfo);
+ method.WithDebugName();
+ return method;
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // MethodInfos for constructed generic methods (Foo.Moo<int> but not Foo.Moo<>)
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeConstructedGenericMethodInfo : RuntimeMethodInfo
+ {
+ internal static RuntimeMethodInfo GetRuntimeConstructedGenericMethodInfo(RuntimeNamedMethodInfo genericMethodDefinition, RuntimeType[] genericTypeArguments)
+ {
+ return new RuntimeConstructedGenericMethodInfo(genericMethodDefinition, genericTypeArguments).WithDebugName();
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // MethodInfos for the Get/Set methods on array types.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeSyntheticMethodInfo : RuntimeMethodInfo
+ {
+ internal static RuntimeMethodInfo GetRuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeType declaringType, RuntimeType[] runtimeParameterTypesAndReturn, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ {
+ return new RuntimeSyntheticMethodInfo(syntheticMethodId, name, declaringType, runtimeParameterTypesAndReturn, options, invoker).WithDebugName();
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.PropertyInfos
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // PropertyInfos
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimePropertyInfo : ExtensiblePropertyInfo
+ {
+ internal static RuntimePropertyInfo GetRuntimePropertyInfo(PropertyHandle propertyHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ return new RuntimePropertyInfo(propertyHandle, definingTypeInfo, contextTypeInfo).WithDebugName();
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.EventInfos
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // EventInfos
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeEventInfo : ExtensibleEventInfo
+ {
+ internal static RuntimeEventInfo GetRuntimeEventInfo(EventHandle eventHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ return new RuntimeEventInfo(eventHandle, definingTypeInfo, contextTypeInfo).WithDebugName();
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // ParameterInfos for MethodBase objects with no Parameter metadata.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeThinMethodParameterInfo : RuntimeMethodParameterInfo
+ {
+ internal static RuntimeThinMethodParameterInfo GetRuntimeThinMethodParameterInfo(MethodBase member, int position, ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeHandle, TypeContext typeContext)
+ {
+ return new RuntimeThinMethodParameterInfo(member, position, reflectionDomain, reader, typeHandle, typeContext);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // ParameterInfos for MethodBase objects with Parameter metadata.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeFatMethodParameterInfo : RuntimeMethodParameterInfo
+ {
+ internal static RuntimeFatMethodParameterInfo GetRuntimeFatMethodParameterInfo(MethodBase member, MethodHandle methodHandle, int position, ParameterHandle parameterHandle, ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeHandle, TypeContext typeContext)
+ {
+ return new RuntimeFatMethodParameterInfo(member, methodHandle, position, parameterHandle, reflectionDomain, reader, typeHandle, typeContext);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // ParameterInfos returned by PropertyInfo.GetIndexParameters()
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimePropertyIndexParameterInfo : RuntimeParameterInfo
+ {
+ internal static RuntimePropertyIndexParameterInfo GetRuntimePropertyIndexParameterInfo(RuntimePropertyInfo member, RuntimeParameterInfo backingParameter)
+ {
+ return new RuntimePropertyIndexParameterInfo(member, backingParameter);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------
+ // ParameterInfos returned by Get/Set methods on array types.
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class RuntimeSyntheticParameterInfo : RuntimeParameterInfo
+ {
+ internal static RuntimeSyntheticParameterInfo GetRuntimeSyntheticParameterInfo(MemberInfo member, int position, RuntimeType parameterType)
+ {
+ return new RuntimeSyntheticParameterInfo(member, position, parameterType);
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.CustomAttributes
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // CustomAttributeData objects returned by various CustomAttributes properties.
+ //-----------------------------------------------------------------------------------------------------------
+ internal abstract partial class RuntimeCustomAttributeData : ExtensibleCustomAttributeData
+ {
+ internal static IEnumerable<CustomAttributeData> GetCustomAttributes(ReflectionDomain reflectionDomain, MetadataReader reader, IEnumerable<CustomAttributeHandle> customAttributeHandles)
+ {
+ foreach (CustomAttributeHandle customAttributeHandle in customAttributeHandles)
+ yield return GetCustomAttributeData(reflectionDomain, reader, customAttributeHandle);
+ }
+
+ private static CustomAttributeData GetCustomAttributeData(ReflectionDomain reflectionDomain, MetadataReader reader, CustomAttributeHandle customAttributeHandle)
+ {
+ return new RuntimeNormalCustomAttributeData(reflectionDomain, reader, customAttributeHandle);
+ }
+ }
+}
+
+namespace System.Reflection.Runtime.TypeParsing
+{
+ //-----------------------------------------------------------------------------------------------------------
+ // Name looks of namespace types. (Affects both type reference resolution and Type.GetType() calls.)
+ //-----------------------------------------------------------------------------------------------------------
+ internal sealed partial class NamespaceTypeName : NamedTypeName
+ {
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = _runtimeNamespaceTypeByNameDispenser.GetOrAdd(new NamespaceTypeNameKey(reflectionDomain, currentAssembly, this));
+ if (result != null)
+ return null;
+ if (!ignoreCase)
+ return new TypeLoadException(SR.Format(SR.TypeLoad_TypeNotFound, this.ToString(), currentAssembly.FullName));
+
+ return TryResolveCaseInsensitive(reflectionDomain, currentAssembly, out result);
+ }
+
+ private static Dispenser<NamespaceTypeNameKey, RuntimeType> _runtimeNamespaceTypeByNameDispenser =
+ DispenserFactory.CreateDispenserV<NamespaceTypeNameKey, RuntimeType>(
+ DispenserScenario.AssemblyAndNamespaceTypeName_Type,
+ delegate (NamespaceTypeNameKey key)
+ {
+ RuntimeType result;
+ Exception typeLoadException = key.NamespaceTypeName.UncachedTryResolveCaseSensitive(key.ReflectionDomain, key.RuntimeAssembly, out result);
+ if (typeLoadException != null)
+ return null;
+ else
+ return result;
+ }
+ );
+
+ private static LowLevelDictionary<String, QHandle> GetCaseInsensitiveTypeDictionary(RuntimeAssembly assembly)
+ {
+ return _caseInsensitiveTypeDictionaryDispenser.GetOrAdd(assembly);
+ }
+
+ private static Dispenser<RuntimeAssembly, LowLevelDictionary<String, QHandle>> _caseInsensitiveTypeDictionaryDispenser =
+ DispenserFactory.CreateDispenserV<RuntimeAssembly, LowLevelDictionary<String, QHandle>>(
+ DispenserScenario.RuntimeAssembly_CaseInsensitiveTypeDictionary,
+ CreateCaseInsensitiveTypeDictionary
+ );
+
+
+ //
+ // Hash key for resolving NamespaceTypeNames to RuntimeTypes.
+ //
+ private struct NamespaceTypeNameKey : IEquatable<NamespaceTypeNameKey>
+ {
+ public NamespaceTypeNameKey(ReflectionDomain reflectionDomain, RuntimeAssembly runtimeAssembly, NamespaceTypeName namespaceTypeName)
+ {
+ _reflectionDomain = reflectionDomain;
+ _runtimeAssembly = runtimeAssembly;
+ _namespaceTypeName = namespaceTypeName;
+ }
+
+ public ReflectionDomain ReflectionDomain
+ {
+ get
+ {
+ return _reflectionDomain;
+ }
+ }
+
+ public RuntimeAssembly RuntimeAssembly
+ {
+ get
+ {
+ return _runtimeAssembly;
+ }
+ }
+
+ public NamespaceTypeName NamespaceTypeName
+ {
+ get
+ {
+ return _namespaceTypeName;
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is NamespaceTypeNameKey))
+ return false;
+ return Equals((NamespaceTypeNameKey)obj);
+ }
+
+ public bool Equals(NamespaceTypeNameKey other)
+ {
+ if (!(this._namespaceTypeName._name.Equals(other._namespaceTypeName._name)))
+ return false;
+ if (!(this._namespaceTypeName._namespaceParts.Length == other._namespaceTypeName._namespaceParts.Length))
+ return false;
+ int count = this._namespaceTypeName._namespaceParts.Length;
+ for (int i = 0; i < count; i++)
+ {
+ if (!(this._namespaceTypeName._namespaceParts[i] == other._namespaceTypeName._namespaceParts[i]))
+ return false;
+ }
+ if (!(this._runtimeAssembly.Equals(other._runtimeAssembly)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _namespaceTypeName._name.GetHashCode();
+ }
+
+ private ReflectionDomain _reflectionDomain;
+ private RuntimeAssembly _runtimeAssembly;
+ private NamespaceTypeName _namespaceTypeName;
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs
new file mode 100644
index 000000000..541aa70d2
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs
@@ -0,0 +1,548 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Text;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.TypeParsing;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.General
+{
+ //
+ // Collect various metadata reading tasks for better chunking...
+ //
+ internal static class MetadataReaderExtensions
+ {
+ public static string GetString(this ConstantStringValueHandle handle, MetadataReader reader)
+ {
+ return reader.GetConstantStringValue(handle).Value;
+ }
+
+ // Useful for namespace Name string which can be a null handle.
+ public static String GetStringOrNull(this ConstantStringValueHandle handle, MetadataReader reader)
+ {
+ if (reader.IsNull(handle))
+ return null;
+ return reader.GetConstantStringValue(handle).Value;
+ }
+
+ public static bool StringOrNullEquals(this ConstantStringValueHandle handle, String valueOrNull, MetadataReader reader)
+ {
+ if (valueOrNull == null)
+ return handle.IsNull(reader);
+ if (handle.IsNull(reader))
+ return false;
+ return handle.StringEquals(valueOrNull, reader);
+ }
+
+ // Needed for RuntimeMappingTable access
+ public static int AsInt(this TypeDefinitionHandle typeDefinitionHandle)
+ {
+ unsafe
+ {
+ return *(int*)&typeDefinitionHandle;
+ }
+ }
+
+ public static TypeDefinitionHandle AsTypeDefinitionHandle(this int i)
+ {
+ unsafe
+ {
+ return *(TypeDefinitionHandle*)&i;
+ }
+ }
+
+ public static int AsInt(this MethodHandle methodHandle)
+ {
+ unsafe
+ {
+ return *(int*)&methodHandle;
+ }
+ }
+
+ public static MethodHandle AsMethodHandle(this int i)
+ {
+ unsafe
+ {
+ return *(MethodHandle*)&i;
+ }
+ }
+
+ public static int AsInt(this FieldHandle fieldHandle)
+ {
+ unsafe
+ {
+ return *(int*)&fieldHandle;
+ }
+ }
+
+ public static FieldHandle AsFieldHandle(this int i)
+ {
+ unsafe
+ {
+ return *(FieldHandle*)&i;
+ }
+ }
+
+
+ public static bool IsTypeDefRefOrSpecHandle(this Handle handle, MetadataReader reader)
+ {
+ HandleType handleType = handle.HandleType;
+ return handleType == HandleType.TypeDefinition ||
+ handleType == HandleType.TypeReference ||
+ handleType == HandleType.TypeSpecification;
+ }
+
+ public static bool IsNamespaceDefinitionHandle(this Handle handle, MetadataReader reader)
+ {
+ HandleType handleType = handle.HandleType;
+ return handleType == HandleType.NamespaceDefinition;
+ }
+
+ public static bool IsNamespaceReferenceHandle(this Handle handle, MetadataReader reader)
+ {
+ HandleType handleType = handle.HandleType;
+ return handleType == HandleType.NamespaceReference;
+ }
+
+ // Conversion where a invalid handle type indicates bad metadata rather a mistake by the caller.
+ public static ScopeReferenceHandle ToExpectedScopeReferenceHandle(this Handle handle, MetadataReader reader)
+ {
+ try
+ {
+ return handle.ToScopeReferenceHandle(reader);
+ }
+ catch (ArgumentException)
+ {
+ throw new BadImageFormatException();
+ }
+ }
+
+ // Conversion where a invalid handle type indicates bad metadata rather a mistake by the caller.
+ public static NamespaceReferenceHandle ToExpectedNamespaceReferenceHandle(this Handle handle, MetadataReader reader)
+ {
+ try
+ {
+ return handle.ToNamespaceReferenceHandle(reader);
+ }
+ catch (ArgumentException)
+ {
+ throw new BadImageFormatException();
+ }
+ }
+
+ // Conversion where a invalid handle type indicates bad metadata rather a mistake by the caller.
+ public static TypeDefinitionHandle ToExpectedTypeDefinitionHandle(this Handle handle, MetadataReader reader)
+ {
+ try
+ {
+ return handle.ToTypeDefinitionHandle(reader);
+ }
+ catch (ArgumentException)
+ {
+ throw new BadImageFormatException();
+ }
+ }
+
+ public static MethodSignature ParseMethodSignature(this Handle handle, MetadataReader reader)
+ {
+ return handle.ToMethodSignatureHandle(reader).GetMethodSignature(reader);
+ }
+
+ public static FieldSignature ParseFieldSignature(this Handle handle, MetadataReader reader)
+ {
+ return handle.ToFieldSignatureHandle(reader).GetFieldSignature(reader);
+ }
+
+ public static PropertySignature ParsePropertySignature(this Handle handle, MetadataReader reader)
+ {
+ return handle.ToPropertySignatureHandle(reader).GetPropertySignature(reader);
+ }
+
+ //
+ // Used to split methods between DeclaredMethods and DeclaredConstructors.
+ //
+ public static bool IsConstructor(this MethodHandle methodHandle, MetadataReader reader)
+ {
+ Method method = methodHandle.GetMethod(reader);
+ return IsConstructor(ref method, reader);
+ }
+
+ // This is specially designed for a hot path so we make some compromises in the signature:
+ //
+ // - "method" is passed by reference even though no side-effects are intended.
+ //
+ public static bool IsConstructor(ref Method method, MetadataReader reader)
+ {
+ if ((method.Flags & (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) != (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName))
+ return false;
+
+ ConstantStringValueHandle nameHandle = method.Name;
+ return nameHandle.StringEquals(ConstructorInfo.ConstructorName, reader) || nameHandle.StringEquals(ConstructorInfo.TypeConstructorName, reader);
+ }
+
+ public static Object ParseConstantValue(this Handle handle, ReflectionDomain reflectionDomain, MetadataReader reader)
+ {
+ Object value;
+ Exception exception = handle.TryParseConstantValue(reflectionDomain, reader, out value);
+ if (exception != null)
+ throw exception;
+ return value;
+ }
+
+ public static Exception TryParseConstantValue(this Handle handle, ReflectionDomain reflectionDomain, MetadataReader reader, out Object value)
+ {
+ HandleType handleType = handle.HandleType;
+ switch (handleType)
+ {
+ case HandleType.ConstantBooleanValue:
+ value = handle.ToConstantBooleanValueHandle(reader).GetConstantBooleanValue(reader).Value;
+ return null;
+ case HandleType.ConstantStringValue:
+ value = handle.ToConstantStringValueHandle(reader).GetConstantStringValue(reader).Value;
+ return null;
+ case HandleType.ConstantCharValue:
+ value = handle.ToConstantCharValueHandle(reader).GetConstantCharValue(reader).Value;
+ return null;
+ case HandleType.ConstantByteValue:
+ value = handle.ToConstantByteValueHandle(reader).GetConstantByteValue(reader).Value;
+ return null;
+ case HandleType.ConstantSByteValue:
+ value = handle.ToConstantSByteValueHandle(reader).GetConstantSByteValue(reader).Value;
+ return null;
+ case HandleType.ConstantInt16Value:
+ value = handle.ToConstantInt16ValueHandle(reader).GetConstantInt16Value(reader).Value;
+ return null;
+ case HandleType.ConstantUInt16Value:
+ value = handle.ToConstantUInt16ValueHandle(reader).GetConstantUInt16Value(reader).Value;
+ return null;
+ case HandleType.ConstantInt32Value:
+ value = handle.ToConstantInt32ValueHandle(reader).GetConstantInt32Value(reader).Value;
+ return null;
+ case HandleType.ConstantUInt32Value:
+ value = handle.ToConstantUInt32ValueHandle(reader).GetConstantUInt32Value(reader).Value;
+ return null;
+ case HandleType.ConstantInt64Value:
+ value = handle.ToConstantInt64ValueHandle(reader).GetConstantInt64Value(reader).Value;
+ return null;
+ case HandleType.ConstantUInt64Value:
+ value = handle.ToConstantUInt64ValueHandle(reader).GetConstantUInt64Value(reader).Value;
+ return null;
+ case HandleType.ConstantSingleValue:
+ value = handle.ToConstantSingleValueHandle(reader).GetConstantSingleValue(reader).Value;
+ return null;
+ case HandleType.ConstantDoubleValue:
+ value = handle.ToConstantDoubleValueHandle(reader).GetConstantDoubleValue(reader).Value;
+ return null;
+ case HandleType.TypeDefinition:
+ case HandleType.TypeReference:
+ case HandleType.TypeSpecification:
+ {
+ Exception exception = null;
+ value = reflectionDomain.TryResolve(reader, handle, new TypeContext(null, null), ref exception);
+ return (value == null) ? exception : null;
+ }
+ case HandleType.ConstantReferenceValue:
+ value = null;
+ return null;
+ default:
+ {
+ Exception exception;
+ value = handle.TryParseConstantArray(reflectionDomain, reader, out exception);
+ if (value == null)
+ return exception;
+ return null;
+ }
+ }
+ }
+
+ public static IEnumerable TryParseConstantArray(this Handle handle, ReflectionDomain reflectionDomain, MetadataReader reader, out Exception exception)
+ {
+ exception = null;
+
+ HandleType handleType = handle.HandleType;
+ switch (handleType)
+ {
+ case HandleType.ConstantBooleanArray:
+ return handle.ToConstantBooleanArrayHandle(reader).GetConstantBooleanArray(reader).Value;
+
+ case HandleType.ConstantStringArray:
+ return handle.ToConstantStringArrayHandle(reader).GetConstantStringArray(reader).Value;
+
+ case HandleType.ConstantCharArray:
+ return handle.ToConstantCharArrayHandle(reader).GetConstantCharArray(reader).Value;
+
+ case HandleType.ConstantByteArray:
+ return handle.ToConstantByteArrayHandle(reader).GetConstantByteArray(reader).Value;
+
+ case HandleType.ConstantSByteArray:
+ return handle.ToConstantSByteArrayHandle(reader).GetConstantSByteArray(reader).Value;
+
+ case HandleType.ConstantInt16Array:
+ return handle.ToConstantInt16ArrayHandle(reader).GetConstantInt16Array(reader).Value;
+
+ case HandleType.ConstantUInt16Array:
+ return handle.ToConstantUInt16ArrayHandle(reader).GetConstantUInt16Array(reader).Value;
+
+ case HandleType.ConstantInt32Array:
+ return handle.ToConstantInt32ArrayHandle(reader).GetConstantInt32Array(reader).Value;
+
+ case HandleType.ConstantUInt32Array:
+ return handle.ToConstantUInt32ArrayHandle(reader).GetConstantUInt32Array(reader).Value;
+
+ case HandleType.ConstantInt64Array:
+ return handle.ToConstantInt64ArrayHandle(reader).GetConstantInt64Array(reader).Value;
+
+ case HandleType.ConstantUInt64Array:
+ return handle.ToConstantUInt64ArrayHandle(reader).GetConstantUInt64Array(reader).Value;
+
+ case HandleType.ConstantSingleArray:
+ return handle.ToConstantSingleArrayHandle(reader).GetConstantSingleArray(reader).Value;
+
+ case HandleType.ConstantDoubleArray:
+ return handle.ToConstantDoubleArrayHandle(reader).GetConstantDoubleArray(reader).Value;
+
+ case HandleType.ConstantHandleArray:
+ {
+ Handle[] constantHandles = handle.ToConstantHandleArrayHandle(reader).GetConstantHandleArray(reader).Value.ToArray();
+ object[] elements = new object[constantHandles.Length];
+ for (int i = 0; i < constantHandles.Length; i++)
+ {
+ exception = constantHandles[i].TryParseConstantValue(reflectionDomain, reader, out elements[i]);
+ if (exception != null)
+ return null;
+ }
+ return elements;
+ }
+ default:
+ throw new BadImageFormatException();
+ }
+ }
+
+ //
+ // Lightweight check to see if a custom attribute's is of a well-known type.
+ //
+ // This check performs without instantating the Type object and bloating memory usage. On the flip side,
+ // it doesn't check on whether the type is defined in a paricular assembly. The desktop CLR typically doesn't
+ // check this either so this is useful from a compat persective as well.
+ //
+ public static bool IsCustomAttributeOfType(this CustomAttributeHandle customAttributeHandle,
+ MetadataReader reader,
+ String ns,
+ String name)
+ {
+ String[] namespaceParts = ns.Split('.');
+ Handle typeHandle = customAttributeHandle.GetCustomAttribute(reader).Type;
+ HandleType handleType = typeHandle.HandleType;
+ if (handleType == HandleType.TypeDefinition)
+ {
+ TypeDefinition typeDefinition = typeHandle.ToTypeDefinitionHandle(reader).GetTypeDefinition(reader);
+ if (!typeDefinition.Name.StringEquals(name, reader))
+ return false;
+ NamespaceDefinitionHandle nsHandle = typeDefinition.NamespaceDefinition;
+ int idx = namespaceParts.Length;
+ while (idx-- != 0)
+ {
+ String namespacePart = namespaceParts[idx];
+ NamespaceDefinition namespaceDefinition = nsHandle.GetNamespaceDefinition(reader);
+ if (!namespaceDefinition.Name.StringOrNullEquals(namespacePart, reader))
+ return false;
+ if (!namespaceDefinition.ParentScopeOrNamespace.IsNamespaceDefinitionHandle(reader))
+ return false;
+ nsHandle = namespaceDefinition.ParentScopeOrNamespace.ToNamespaceDefinitionHandle(reader);
+ }
+ if (!nsHandle.GetNamespaceDefinition(reader).Name.StringOrNullEquals(null, reader))
+ return false;
+ return true;
+ }
+ else if (handleType == HandleType.TypeReference)
+ {
+ TypeReference typeReference = typeHandle.ToTypeReferenceHandle(reader).GetTypeReference(reader);
+ if (!typeReference.TypeName.StringEquals(name, reader))
+ return false;
+ if (!typeReference.ParentNamespaceOrType.IsNamespaceReferenceHandle(reader))
+ return false;
+ NamespaceReferenceHandle nsHandle = typeReference.ParentNamespaceOrType.ToNamespaceReferenceHandle(reader);
+ int idx = namespaceParts.Length;
+ while (idx-- != 0)
+ {
+ String namespacePart = namespaceParts[idx];
+ NamespaceReference namespaceReference = nsHandle.GetNamespaceReference(reader);
+ if (!namespaceReference.Name.StringOrNullEquals(namespacePart, reader))
+ return false;
+ if (!namespaceReference.ParentScopeOrNamespace.IsNamespaceReferenceHandle(reader))
+ return false;
+ nsHandle = namespaceReference.ParentScopeOrNamespace.ToNamespaceReferenceHandle(reader);
+ }
+ if (!nsHandle.GetNamespaceReference(reader).Name.StringOrNullEquals(null, reader))
+ return false;
+ return true;
+ }
+ else
+ throw new NotSupportedException();
+ }
+
+
+ public static String ToNamespaceName(this NamespaceDefinitionHandle namespaceDefinitionHandle, MetadataReader reader)
+ {
+ String ns = "";
+ for (; ;)
+ {
+ NamespaceDefinition currentNamespaceDefinition = namespaceDefinitionHandle.GetNamespaceDefinition(reader);
+ String name = currentNamespaceDefinition.Name.GetStringOrNull(reader);
+ if (name != null)
+ {
+ if (ns.Length != 0)
+ ns = "." + ns;
+ ns = name + ns;
+ }
+ Handle nextHandle = currentNamespaceDefinition.ParentScopeOrNamespace;
+ HandleType handleType = nextHandle.HandleType;
+ if (handleType == HandleType.ScopeDefinition)
+ break;
+ if (handleType == HandleType.NamespaceDefinition)
+ {
+ namespaceDefinitionHandle = nextHandle.ToNamespaceDefinitionHandle(reader);
+ continue;
+ }
+
+ throw new BadImageFormatException(SR.Bif_InvalidMetadata);
+ }
+ return ns;
+ }
+
+ public static IEnumerable<NamespaceDefinitionHandle> GetTransitiveNamespaces(this MetadataReader reader, IEnumerable<NamespaceDefinitionHandle> namespaceHandles)
+ {
+ foreach (NamespaceDefinitionHandle namespaceHandle in namespaceHandles)
+ {
+ yield return namespaceHandle;
+
+ NamespaceDefinition namespaceDefinition = namespaceHandle.GetNamespaceDefinition(reader);
+ foreach (NamespaceDefinitionHandle childNamespaceHandle in GetTransitiveNamespaces(reader, namespaceDefinition.NamespaceDefinitions))
+ yield return childNamespaceHandle;
+ }
+ }
+
+ public static IEnumerable<TypeDefinitionHandle> GetTopLevelTypes(this MetadataReader reader, IEnumerable<NamespaceDefinitionHandle> namespaceHandles)
+ {
+ foreach (NamespaceDefinitionHandle namespaceHandle in namespaceHandles)
+ {
+ NamespaceDefinition namespaceDefinition = namespaceHandle.GetNamespaceDefinition(reader);
+ foreach (TypeDefinitionHandle typeDefinitionHandle in namespaceDefinition.TypeDefinitions)
+ {
+ yield return typeDefinitionHandle;
+ }
+ }
+ }
+
+ public static IEnumerable<TypeDefinitionHandle> GetTransitiveTypes(this MetadataReader reader, IEnumerable<TypeDefinitionHandle> typeDefinitionHandles, bool publicOnly)
+ {
+ foreach (TypeDefinitionHandle typeDefinitionHandle in typeDefinitionHandles)
+ {
+ TypeDefinition typeDefinition = typeDefinitionHandle.GetTypeDefinition(reader);
+
+ if (publicOnly)
+ {
+ TypeAttributes visibility = typeDefinition.Flags & TypeAttributes.VisibilityMask;
+ if (visibility != TypeAttributes.Public && visibility != TypeAttributes.NestedPublic)
+ continue;
+ }
+
+ yield return typeDefinitionHandle;
+
+ foreach (TypeDefinitionHandle nestedTypeDefinitionHandle in GetTransitiveTypes(reader, typeDefinition.NestedTypes, publicOnly))
+ yield return nestedTypeDefinitionHandle;
+ }
+ }
+
+ public static AssemblyQualifiedTypeName ToAssemblyQualifiedTypeName(this NamespaceReferenceHandle namespaceReferenceHandle, String typeName, MetadataReader reader)
+ {
+ LowLevelList<String> namespaceParts = new LowLevelList<String>(8);
+ NamespaceReference namespaceReference;
+ for (; ;)
+ {
+ namespaceReference = namespaceReferenceHandle.GetNamespaceReference(reader);
+ String namespacePart = namespaceReference.Name.GetStringOrNull(reader);
+ if (namespacePart == null)
+ break;
+ namespaceParts.Add(namespacePart);
+ namespaceReferenceHandle = namespaceReference.ParentScopeOrNamespace.ToExpectedNamespaceReferenceHandle(reader);
+ }
+
+ ScopeReferenceHandle scopeReferenceHandle = namespaceReference.ParentScopeOrNamespace.ToExpectedScopeReferenceHandle(reader);
+ RuntimeAssemblyName assemblyName = scopeReferenceHandle.ToRuntimeAssemblyName(reader);
+ return new AssemblyQualifiedTypeName(new NamespaceTypeName(namespaceParts.ToArray(), typeName), assemblyName);
+ }
+
+ public static RuntimeAssemblyName ToRuntimeAssemblyName(this ScopeDefinitionHandle scopeDefinitionHandle, MetadataReader reader)
+ {
+ ScopeDefinition scopeDefinition = scopeDefinitionHandle.GetScopeDefinition(reader);
+ return CreateRuntimeAssemblyNameFromMetadata(
+ reader,
+ scopeDefinition.Name,
+ scopeDefinition.MajorVersion,
+ scopeDefinition.MinorVersion,
+ scopeDefinition.BuildNumber,
+ scopeDefinition.RevisionNumber,
+ scopeDefinition.Culture,
+ scopeDefinition.PublicKey,
+ scopeDefinition.Flags
+ );
+ }
+
+ public static RuntimeAssemblyName ToRuntimeAssemblyName(this ScopeReferenceHandle scopeReferenceHandle, MetadataReader reader)
+ {
+ ScopeReference scopeReference = scopeReferenceHandle.GetScopeReference(reader);
+ return CreateRuntimeAssemblyNameFromMetadata(
+ reader,
+ scopeReference.Name,
+ scopeReference.MajorVersion,
+ scopeReference.MinorVersion,
+ scopeReference.BuildNumber,
+ scopeReference.RevisionNumber,
+ scopeReference.Culture,
+ scopeReference.PublicKeyOrToken,
+ scopeReference.Flags
+ );
+ }
+
+ private static RuntimeAssemblyName CreateRuntimeAssemblyNameFromMetadata(
+ MetadataReader reader,
+ ConstantStringValueHandle name,
+ ushort majorVersion,
+ ushort minorVersion,
+ ushort buildNumber,
+ ushort revisionNumber,
+ ConstantStringValueHandle culture,
+ IEnumerable<byte> publicKeyOrToken,
+ AssemblyFlags assemblyFlags)
+ {
+ AssemblyNameFlags assemblyNameFlags = AssemblyNameFlags.None;
+ if (0 != (assemblyFlags & AssemblyFlags.PublicKey))
+ assemblyNameFlags |= AssemblyNameFlags.PublicKey;
+ if (0 != (assemblyFlags & AssemblyFlags.Retargetable))
+ assemblyNameFlags |= AssemblyNameFlags.Retargetable;
+ int contentType = ((int)assemblyFlags) & 0x00000E00;
+ assemblyNameFlags |= (AssemblyNameFlags)contentType;
+
+ return new RuntimeAssemblyName(
+ name.GetString(reader),
+ new Version(majorVersion, minorVersion, buildNumber, revisionNumber),
+ culture.GetStringOrNull(reader),
+ assemblyNameFlags,
+ publicKeyOrToken.ToArray()
+ );
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs
new file mode 100644
index 000000000..5b8246b14
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs
@@ -0,0 +1,80 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Text;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.General
+{
+ //
+ // Since computation of the fullname and the declaring assembly both require walking up the namespace chain,
+ // cache both results the first time we walk the chain.
+ //
+ internal sealed class NamespaceChain
+ {
+ internal NamespaceChain(MetadataReader reader, NamespaceDefinitionHandle innerMostNamespaceHandle)
+ {
+ NamespaceDefinition currentNamespaceDefinition = innerMostNamespaceHandle.GetNamespaceDefinition(reader);
+ ConstantStringValueHandle currentNameHandle = currentNamespaceDefinition.Name;
+ Handle currentNamespaceHandle = innerMostNamespaceHandle.ToHandle(reader);
+ LowLevelList<String> names = new LowLevelList<String>();
+ for (; ;)
+ {
+ String name = currentNameHandle.GetStringOrNull(reader);
+ names.Add(name);
+ currentNamespaceHandle = currentNamespaceDefinition.ParentScopeOrNamespace;
+ HandleType handleType = currentNamespaceHandle.HandleType;
+ if (handleType == HandleType.ScopeDefinition)
+ break;
+ if (handleType == HandleType.NamespaceDefinition)
+ {
+ NamespaceDefinitionHandle nsHandle = currentNamespaceHandle.ToNamespaceDefinitionHandle(reader);
+ currentNamespaceDefinition = nsHandle.GetNamespaceDefinition(reader);
+ currentNameHandle = currentNamespaceDefinition.Name;
+ continue;
+ }
+
+ throw new BadImageFormatException(SR.Bif_InvalidMetadata);
+ }
+
+ DefiningScope = currentNamespaceHandle.ToScopeDefinitionHandle(reader);
+
+ int count = names.Count;
+ if (count == 0)
+ {
+ // Every namespace chain has to start with the root namespace.
+ throw new BadImageFormatException();
+ }
+ else if (count == 1)
+ {
+ // The root namespace. For compat with the desktop, TypeInfo.NameSpaces returns null in this case.
+ NameSpace = null;
+ }
+ else
+ {
+ // Namespace has at least one non-root component.
+ StringBuilder sb = new StringBuilder();
+ int idx = count - 1;
+ while (idx-- != 0)
+ {
+ String name = names[idx];
+ if (name == null)
+ throw new BadImageFormatException(); // null namespace fragment found in middle.
+ sb.Append(name);
+ if (idx != 0)
+ sb.Append('.');
+ }
+ NameSpace = sb.ToString();
+ }
+ }
+
+ internal String NameSpace { get; private set; }
+ internal ScopeDefinitionHandle DefiningScope { get; private set; }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QHandles.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QHandles.cs
new file mode 100644
index 000000000..2b90c771e
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QHandles.cs
@@ -0,0 +1,193 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// Collection of "qualified handle" tuples.
+//
+
+using global::System;
+using global::System.Collections.Generic;
+using global::System.Diagnostics;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace Internal.Reflection.Core
+{
+ public struct QScopeDefinition : IEquatable<QScopeDefinition>
+ {
+ public QScopeDefinition(MetadataReader reader, ScopeDefinitionHandle handle)
+ {
+ _reader = reader;
+ _handle = handle;
+ }
+
+ public MetadataReader Reader { get { return _reader; } }
+ public ScopeDefinitionHandle Handle { get { return _handle; } }
+ public ScopeDefinition ScopeDefinition
+ {
+ get
+ {
+ return _handle.GetScopeDefinition(_reader);
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is QScopeDefinition))
+ return false;
+ return Equals((QScopeDefinition)obj);
+ }
+
+ public bool Equals(QScopeDefinition other)
+ {
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._handle.Equals(other._handle)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _handle.GetHashCode();
+ }
+
+ private MetadataReader _reader;
+ private ScopeDefinitionHandle _handle;
+ }
+}
+
+namespace System.Reflection.Runtime.General
+{
+ internal struct QHandle : IEquatable<QHandle>
+ {
+ public QHandle(MetadataReader reader, Handle handle)
+ {
+ _reader = reader;
+ _handle = handle;
+ }
+
+ public MetadataReader Reader { get { return _reader; } }
+ public Handle Handle { get { return _handle; } }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is QHandle))
+ return false;
+ return Equals((QHandle)obj);
+ }
+
+ public bool Equals(QHandle other)
+ {
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._handle.Equals(other._handle)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _handle.GetHashCode();
+ }
+
+ private MetadataReader _reader;
+ private Handle _handle;
+ }
+
+
+ internal struct QTypeDefinition : IEquatable<QTypeDefinition>
+ {
+ public QTypeDefinition(MetadataReader reader, TypeDefinitionHandle handle)
+ {
+ _reader = reader;
+ _handle = handle;
+ }
+
+ public MetadataReader Reader { get { return _reader; } }
+ public TypeDefinitionHandle Handle { get { return _handle; } }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is QTypeDefinition))
+ return false;
+ return Equals((QTypeDefinition)obj);
+ }
+
+ public bool Equals(QTypeDefinition other)
+ {
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._handle.Equals(other._handle)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _handle.GetHashCode();
+ }
+
+ private MetadataReader _reader;
+ private TypeDefinitionHandle _handle;
+ }
+
+
+ internal struct QTypeDefRefOrSpec
+ {
+ public QTypeDefRefOrSpec(MetadataReader reader, Handle handle, bool skipCheck = false)
+ {
+ if (!skipCheck)
+ {
+ if (!handle.IsTypeDefRefOrSpecHandle(reader))
+ throw new BadImageFormatException();
+ }
+ Debug.Assert(handle.IsTypeDefRefOrSpecHandle(reader));
+ _reader = reader;
+ _handle = handle;
+ }
+
+ public MetadataReader Reader { get { return _reader; } }
+ public Handle Handle { get { return _handle; } }
+
+ public static readonly QTypeDefRefOrSpec Null = default(QTypeDefRefOrSpec);
+
+ private MetadataReader _reader;
+ private Handle _handle;
+ }
+
+ internal struct QGenericParameter : IEquatable<QGenericParameter>
+ {
+ public QGenericParameter(MetadataReader reader, GenericParameterHandle handle)
+ {
+ _reader = reader;
+ _handle = handle;
+ }
+
+ public MetadataReader Reader { get { return _reader; } }
+ public GenericParameterHandle Handle { get { return _handle; } }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is QGenericParameter))
+ return false;
+ return Equals((QGenericParameter)obj);
+ }
+
+ public bool Equals(QGenericParameter other)
+ {
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._handle.Equals(other._handle)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _handle.GetHashCode();
+ }
+
+ private MetadataReader _reader;
+ private GenericParameterHandle _handle;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs
new file mode 100644
index 000000000..4b9b33e6e
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs
@@ -0,0 +1,161 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.FieldInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+
+using global::Internal.Reflection.Augments;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.General
+{
+ internal sealed class ReflectionCoreCallbacksImplementation : ReflectionCoreCallbacks
+ {
+ internal ReflectionCoreCallbacksImplementation()
+ {
+ }
+
+ public sealed override TypeInfo GetTypeInfo(Type type)
+ {
+ RuntimeType runtimeType = type as RuntimeType;
+ if (runtimeType != null)
+ return runtimeType.GetRuntimeTypeInfo();
+ IReflectableType reflectableType = type as IReflectableType;
+ if (reflectableType != null)
+ return reflectableType.GetTypeInfo();
+
+ throw runtimeType.GetReflectionDomain().CreateMissingMetadataException(type);
+ }
+
+ public sealed override Assembly Load(AssemblyName refName)
+ {
+ if (refName == null)
+ throw new ArgumentNullException("assemblyRef");
+ return RuntimeAssembly.GetRuntimeAssembly(ReflectionCoreExecution.ExecutionDomain, refName.ToRuntimeAssemblyName());
+ }
+
+ //
+ // 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 sealed override MethodBase GetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle)
+ {
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ MethodHandle methodHandle;
+ RuntimeTypeHandle declaringTypeHandle;
+ RuntimeTypeHandle[] genericMethodTypeArgumentHandles;
+ if (!executionEnvironment.TryGetMethodFromHandle(runtimeMethodHandle, out declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ throw new ArgumentException(SR.Argument_InvalidHandle);
+
+ MethodBase methodBase = ReflectionCoreExecution.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 sealed override MethodBase GetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle)
+ {
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ MethodHandle methodHandle;
+ RuntimeTypeHandle[] genericMethodTypeArgumentHandles;
+ if (!executionEnvironment.TryGetMethodFromHandleAndType(runtimeMethodHandle, declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ {
+ // 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,
+ ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(declaringTypeHandle),
+ ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(actualDeclaringTypeHandle)));
+ }
+
+ MethodBase methodBase = ReflectionCoreExecution.ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles);
+ return methodBase;
+ }
+
+ //
+ // 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 sealed override 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 sealed override FieldInfo GetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, RuntimeTypeHandle declaringTypeHandle)
+ {
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ FieldHandle fieldHandle;
+ if (!executionEnvironment.TryGetFieldFromHandleAndType(runtimeFieldHandle, declaringTypeHandle, out fieldHandle))
+ {
+ // 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,
+ ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(declaringTypeHandle),
+ ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(actualDeclaringTypeHandle)));
+ }
+
+ FieldInfo fieldInfo = GetFieldInfo(declaringTypeHandle, fieldHandle);
+ return fieldInfo;
+ }
+
+ public sealed override void InitializeAssemblyName(AssemblyName blank, String fullName)
+ {
+ RuntimeAssemblyName runtimeAssemblyName = AssemblyNameParser.Parse(fullName);
+ runtimeAssemblyName.CopyToAssemblyName(blank);
+ }
+
+ public sealed override String ComputeAssemblyNameFullName(AssemblyName assemblyName)
+ {
+ return AssemblyNameHelpers.ComputeDisplayName(assemblyName.ToRuntimeAssemblyName());
+ }
+
+ public sealed override byte[] ComputePublicKeyToken(byte[] publicKey)
+ {
+ return AssemblyNameHelpers.ComputePublicKeyToken(publicKey);
+ }
+
+ private FieldInfo GetFieldInfo(RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle)
+ {
+ RuntimeType declaringType = ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(declaringTypeHandle);
+ RuntimeTypeInfo contextTypeInfo = declaringType.GetRuntimeTypeInfo();
+ RuntimeNamedTypeInfo definingTypeInfo = contextTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
+ MetadataReader reader = definingTypeInfo.Reader;
+ return RuntimeFieldInfo.GetRuntimeFieldInfo(fieldHandle, definingTypeInfo, contextTypeInfo);
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeNamespaceInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeNamespaceInfo.cs
new file mode 100644
index 000000000..27f703ebf
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeNamespaceInfo.cs
@@ -0,0 +1,3 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeExtensions.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeExtensions.cs
new file mode 100644
index 000000000..4d2735cd0
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeExtensions.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Reflection.Runtime.TypeInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.General
+{
+ internal static class RuntimeTypeExtensions
+ {
+ public static RuntimeTypeInfo GetRuntimeTypeInfo(this RuntimeType runtimeType)
+ {
+ return RuntimeTypeInfo.GetRuntimeTypeInfo(runtimeType);
+ }
+
+ public static RUNTIMETYPEINFO GetRuntimeTypeInfo<RUNTIMETYPEINFO>(this Type type)
+ where RUNTIMETYPEINFO : RuntimeTypeInfo
+ {
+ Debug.Assert(type is RuntimeType);
+ return (RUNTIMETYPEINFO)(type.GetTypeInfo());
+ }
+
+ public static ReflectionDomain GetReflectionDomain(this RuntimeType runtimeType)
+ {
+ return ReflectionCoreExecution.ExecutionDomain; //@todo: User Reflection Domains not yet supported.
+ }
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeUnifierEx.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeUnifierEx.cs
new file mode 100644
index 000000000..5c9961100
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeUnifierEx.cs
@@ -0,0 +1,115 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Collections.Generic;
+using global::System.Collections.Concurrent;
+using global::System.Runtime.CompilerServices;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.General
+{
+ //
+ // ! If you change this policy to not unify all instances, you must change the implementation of Equals/GetHashCode in the runtime type classes.
+ //
+ // The RuntimeTypeUnifier and its companion RuntimeTypeUnifierEx maintains a record of all System.Type objects
+ // created by the runtime. The split into two classes is an artifact of reflection being implemented partly in System.Private.CoreLib and
+ // partly in S.R.R.
+ //
+ // Though the present incarnation enforces the "one instance per semantic identity rule", its surface area is also designed
+ // to be able to switch to a non-unified model if desired.
+ //
+ // ! If you do switch away from a "one instance per semantic identity rule", you must also change the implementation
+ // ! of RuntimeType.Equals() and RuntimeType.GetHashCode().
+ //
+
+ internal static class RuntimeTypeUnifierEx
+ {
+ //
+ // Retrieves the unified Type object for a named type that has metadata associated with it.
+ //
+ public static RuntimeType GetNamedType(MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle)
+ {
+ return TypeTableForNamedTypes.Table.GetOrAdd(new QTypeDefinition(reader, typeDefinitionHandle)).WithDebugName();
+ }
+
+ //
+ // Type table for all named types that have metadata associated with it.
+ //
+ private sealed class TypeTableForNamedTypes : ConcurrentUnifierW<QTypeDefinition, RuntimeType>
+ {
+ private TypeTableForNamedTypes() { }
+
+ protected sealed override RuntimeType Factory(QTypeDefinition qTypeDefinition)
+ {
+ RuntimeTypeHandle runtimeTypeHandle;
+ if (ReflectionCoreExecution.ExecutionEnvironment.TryGetNamedTypeForMetadata(qTypeDefinition.Reader, qTypeDefinition.Handle, out runtimeTypeHandle))
+ return ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(runtimeTypeHandle);
+ else
+ return RuntimeInspectionOnlyNamedType.GetRuntimeInspectionOnlyNamedType(qTypeDefinition.Reader, qTypeDefinition.Handle);
+ }
+
+ public static TypeTableForNamedTypes Table = new TypeTableForNamedTypes();
+ }
+
+
+
+ //
+ // Retrieves the unified Type object for a generic type parameter type.
+ //
+ internal static RuntimeType GetRuntimeGenericParameterTypeForTypes(RuntimeNamedTypeInfo typeOwner, GenericParameterHandle genericParameterHandle)
+ {
+ RuntimeGenericParameterTypeForTypes.UnificationKey key = new RuntimeGenericParameterTypeForTypes.UnificationKey(typeOwner.Reader, typeOwner.TypeDefinitionHandle, genericParameterHandle);
+ return GenericParameterTypeForTypesTable.Table.GetOrAdd(key).WithDebugName();
+ }
+
+ private sealed class GenericParameterTypeForTypesTable : ConcurrentUnifierW<RuntimeGenericParameterTypeForTypes.UnificationKey, RuntimeGenericParameterTypeForTypes>
+ {
+ protected sealed override RuntimeGenericParameterTypeForTypes Factory(RuntimeGenericParameterTypeForTypes.UnificationKey key)
+ {
+ RuntimeNamedTypeInfo typeOwner = RuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(key.Reader, key.TypeDefinitionHandle);
+ return new RuntimeGenericParameterTypeForTypes(key.Reader, key.GenericParameterHandle, typeOwner);
+ }
+
+ public static GenericParameterTypeForTypesTable Table = new GenericParameterTypeForTypesTable();
+ }
+
+
+ //
+ // Retrieves the unified Type object for a generic method parameter type.
+ //
+ internal static RuntimeGenericParameterTypeForMethods GetRuntimeGenericParameterTypeForMethods(RuntimeNamedMethodInfo methodOwner, MetadataReader reader, GenericParameterHandle genericParameterHandle)
+ {
+ RuntimeGenericParameterTypeForMethods.UnificationKey key = new RuntimeGenericParameterTypeForMethods.UnificationKey(methodOwner, reader, genericParameterHandle);
+ return GenericParameterTypeForMethodsTable.Table.GetOrAdd(key);
+ }
+
+ private sealed class GenericParameterTypeForMethodsTable : ConcurrentUnifierWKeyed<RuntimeGenericParameterTypeForMethods.UnificationKey, RuntimeGenericParameterTypeForMethods>
+ {
+ protected sealed override RuntimeGenericParameterTypeForMethods Factory(RuntimeGenericParameterTypeForMethods.UnificationKey key)
+ {
+ return new RuntimeGenericParameterTypeForMethods(key.Reader, key.GenericParameterHandle, key.MethodOwner);
+ }
+
+ public static GenericParameterTypeForMethodsTable Table = new GenericParameterTypeForMethodsTable();
+ }
+
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static RuntimeType WithDebugName(this RuntimeType runtimeType)
+ {
+#if DEBUG
+ if (runtimeType != null)
+ runtimeType.EstablishDebugName();
+#endif
+ return runtimeType;
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs
new file mode 100644
index 000000000..42e70b21c
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs
@@ -0,0 +1,104 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.TypeParsing;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.General
+{
+ internal static class ToStringUtils
+ {
+ //
+ // This is a port of the desktop CLR's RuntimeType.FormatTypeName() routine. This routine is used by various Reflection ToString() methods
+ // to display the name of a type. Do not use for any other purpose as it inherits some pretty quirky desktop behavior.
+ //
+ // The Project N version takes a raw metadata handle rather than a completed type so that it remains robust in the face of missing metadata.
+ //
+ public static String FormatTypeName(this Handle typeDefRefOrSpecHandle, MetadataReader reader, TypeContext typeContext, ReflectionDomain reflectionDomain)
+ {
+ try
+ {
+ // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions
+ // (non-error exceptions are very annoying when debugging.)
+
+ Exception exception = null;
+ RuntimeType runtimeType = reflectionDomain.TryResolve(reader, typeDefRefOrSpecHandle, typeContext, ref exception);
+ if (runtimeType == null)
+ return UnavailableType;
+
+ // Because this runtimeType came from a successful TryResolve() call, it is safe to querying the TypeInfo's of the type and its component parts.
+ // If we're wrong, we do have the safety net of a try-catch.
+ return runtimeType.FormatTypeName();
+ }
+ catch (Exception)
+ {
+ return UnavailableType;
+ }
+ }
+
+ //
+ // This is a port of the desktop CLR's RuntimeType.FormatTypeName() routine. This routine is used by various Reflection ToString() methods
+ // to display the name of a type. Do not use for any other purpose as it inherits some pretty quirky desktop behavior.
+ //
+ // The Project N version takes a raw metadata handle rather than a completed type so that it remains robust in the face of missing metadata.
+ //
+ public static String FormatTypeName(this RuntimeType runtimeType)
+ {
+ try
+ {
+ // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions
+ // (non-error exceptions are very annoying when debugging.)
+
+ ReflectionDomain reflectionDomain = runtimeType.GetReflectionDomain();
+
+ // Legacy: this doesn't make sense, why use only Name for nested types but otherwise
+ // ToString() which contains namespace.
+ RuntimeType rootElementType = runtimeType;
+ while (rootElementType.HasElementType)
+ rootElementType = rootElementType.InternalRuntimeElementType;
+ if (rootElementType.IsNested)
+ {
+ String name = runtimeType.InternalNameIfAvailable;
+ return name == null ? UnavailableType : name;
+ }
+
+ // Legacy: why removing "System"? Is it just because C# has keywords for these types?
+ // If so why don't we change it to lower case to match the C# keyword casing?
+ FoundationTypes foundationTypes = reflectionDomain.FoundationTypes;
+ String typeName = runtimeType.ToString();
+ if (typeName.StartsWith("System."))
+ {
+ foreach (Type pt in reflectionDomain.PrimitiveTypes)
+ {
+ if (pt.Equals(rootElementType) || rootElementType.Equals(foundationTypes.SystemVoid))
+ {
+ typeName = typeName.Substring("System.".Length);
+ break;
+ }
+ }
+ }
+ return typeName;
+ }
+ catch (Exception)
+ {
+ return UnavailableType;
+ }
+ }
+
+ public const String UnavailableType = "UnknownType";
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeContext.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeContext.cs
new file mode 100644
index 000000000..00ef752c5
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeContext.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.General
+{
+ //
+ // Passed as an argument to code that parses signatures or typespecs. Specifies the subsitution values for ET_VAR and ET_MVAR elements inside the signature.
+ // Both may be null if no generic parameters are expected.
+ //
+
+ internal struct TypeContext
+ {
+ internal TypeContext(RuntimeType[] genericTypeArguments, RuntimeType[] genericMethodArguments)
+ {
+ _genericTypeArguments = genericTypeArguments;
+ _genericMethodArguments = genericMethodArguments;
+ }
+
+ internal RuntimeType[] GenericTypeArguments
+ {
+ get
+ {
+ return _genericTypeArguments;
+ }
+ }
+
+ internal RuntimeType[] GenericMethodArguments
+ {
+ get
+ {
+ return _genericMethodArguments;
+ }
+ }
+
+ private RuntimeType[] _genericTypeArguments;
+ private RuntimeType[] _genericMethodArguments;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeExtensions.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeExtensions.cs
new file mode 100644
index 000000000..2a7af61ba
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeExtensions.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.General
+{
+ internal static class TypeExtensions
+ {
+ public static RuntimeType AsConfirmedRuntimeType(this Type type)
+ {
+ RuntimeType runtimeType = type as RuntimeType;
+ if (runtimeType == null)
+ throw new InvalidOperationException();
+ return runtimeType;
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs
new file mode 100644
index 000000000..ed78c1219
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs
@@ -0,0 +1,212 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.TypeParsing;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.General
+{
+ internal static class TypeResolver
+ {
+ //
+ // Main routine to resolve a typeDef/Ref/Spec.
+ //
+ internal static RuntimeType Resolve(this ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeDefRefOrSpec, TypeContext typeContext)
+ {
+ Exception exception = null;
+ RuntimeType runtimeType = reflectionDomain.TryResolve(reader, typeDefRefOrSpec, typeContext, ref exception);
+ if (runtimeType == null)
+ throw exception;
+ return runtimeType;
+ }
+
+ internal static RuntimeType TryResolve(this ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeDefRefOrSpec, TypeContext typeContext, ref Exception exception)
+ {
+ HandleType handleType = typeDefRefOrSpec.HandleType;
+ if (handleType == HandleType.TypeDefinition)
+ return reflectionDomain.ResolveTypeDefinition(reader, typeDefRefOrSpec.ToTypeDefinitionHandle(reader));
+ else if (handleType == HandleType.TypeReference)
+ return reflectionDomain.TryResolveTypeReference(reader, typeDefRefOrSpec.ToTypeReferenceHandle(reader), ref exception);
+ else if (handleType == HandleType.TypeSpecification)
+ return reflectionDomain.TryResolveTypeSignature(reader, typeDefRefOrSpec.ToTypeSpecificationHandle(reader), typeContext, ref exception);
+ else
+ throw new BadImageFormatException(); // Expected TypeRef, Def or Spec.
+ }
+
+
+ //
+ // Main routine to resolve a typeDefinition.
+ //
+ internal static RuntimeType ResolveTypeDefinition(this ReflectionDomain reflectionDomain, MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle)
+ {
+ return RuntimeTypeUnifierEx.GetNamedType(reader, typeDefinitionHandle);
+ }
+
+ //
+ // Main routine to parse a metadata type specification signature.
+ //
+ private static RuntimeType TryResolveTypeSignature(this ReflectionDomain reflectionDomain, MetadataReader reader, TypeSpecificationHandle typeSpecHandle, TypeContext typeContext, ref Exception exception)
+ {
+ Handle typeHandle = typeSpecHandle.GetTypeSpecification(reader).Signature;
+ switch (typeHandle.HandleType)
+ {
+ case HandleType.ArraySignature:
+ {
+ ArraySignature sig = typeHandle.ToArraySignatureHandle(reader).GetArraySignature(reader);
+ int rank = sig.Rank;
+ if (rank <= 0)
+ throw new BadImageFormatException(); // Bad rank.
+ RuntimeType elementType = reflectionDomain.TryResolve(reader, sig.ElementType, typeContext, ref exception);
+ if (elementType == null)
+ return null;
+ return ReflectionCoreNonPortable.GetMultiDimArrayType(elementType, rank);
+ }
+
+ case HandleType.ByReferenceSignature:
+ {
+ ByReferenceSignature sig = typeHandle.ToByReferenceSignatureHandle(reader).GetByReferenceSignature(reader);
+ RuntimeType targetType = reflectionDomain.TryResolve(reader, sig.Type, typeContext, ref exception);
+ if (targetType == null)
+ return null;
+ return ReflectionCoreNonPortable.GetByRefType(targetType);
+ }
+
+ case HandleType.MethodTypeVariableSignature:
+ {
+ MethodTypeVariableSignature sig = typeHandle.ToMethodTypeVariableSignatureHandle(reader).GetMethodTypeVariableSignature(reader);
+ return typeContext.GenericMethodArguments[sig.Number];
+ }
+
+ case HandleType.PointerSignature:
+ {
+ PointerSignature sig = typeHandle.ToPointerSignatureHandle(reader).GetPointerSignature(reader);
+ RuntimeType targetType = reflectionDomain.TryResolve(reader, sig.Type, typeContext, ref exception);
+ if (targetType == null)
+ return null;
+ return ReflectionCoreNonPortable.GetPointerType(targetType);
+ }
+
+ case HandleType.SZArraySignature:
+ {
+ SZArraySignature sig = typeHandle.ToSZArraySignatureHandle(reader).GetSZArraySignature(reader);
+ RuntimeType elementType = reflectionDomain.TryResolve(reader, sig.ElementType, typeContext, ref exception);
+ if (elementType == null)
+ return null;
+ return ReflectionCoreNonPortable.GetArrayType(elementType);
+ }
+
+ case HandleType.TypeDefinition:
+ {
+ return reflectionDomain.ResolveTypeDefinition(reader, typeHandle.ToTypeDefinitionHandle(reader));
+ }
+
+ case HandleType.TypeInstantiationSignature:
+ {
+ TypeInstantiationSignature sig = typeHandle.ToTypeInstantiationSignatureHandle(reader).GetTypeInstantiationSignature(reader);
+ RuntimeType genericTypeDefinition = reflectionDomain.TryResolve(reader, sig.GenericType, typeContext, ref exception);
+ if (genericTypeDefinition == null)
+ return null;
+ LowLevelList<RuntimeType> genericTypeArguments = new LowLevelList<RuntimeType>();
+ foreach (Handle genericTypeArgumentHandle in sig.GenericTypeArguments)
+ {
+ RuntimeType genericTypeArgument = reflectionDomain.TryResolve(reader, genericTypeArgumentHandle, typeContext, ref exception);
+ if (genericTypeArgument == null)
+ return null;
+ genericTypeArguments.Add(genericTypeArgument);
+ }
+ return ReflectionCoreNonPortable.GetConstructedGenericType(genericTypeDefinition, genericTypeArguments.ToArray());
+ }
+
+ case HandleType.TypeReference:
+ {
+ return reflectionDomain.TryResolveTypeReference(reader, typeHandle.ToTypeReferenceHandle(reader), ref exception);
+ }
+
+ case HandleType.TypeVariableSignature:
+ {
+ TypeVariableSignature sig = typeHandle.ToTypeVariableSignatureHandle(reader).GetTypeVariableSignature(reader);
+ return typeContext.GenericTypeArguments[sig.Number];
+ }
+
+ default:
+ throw new NotSupportedException(); // Unexpected Type signature type.
+ }
+ }
+
+ //
+ // Main routine to resolve a typeReference.
+ //
+ private static RuntimeType TryResolveTypeReference(this ReflectionDomain reflectionDomain, MetadataReader reader, TypeReferenceHandle typeReferenceHandle, ref Exception exception)
+ {
+ {
+ ExecutionDomain executionDomain = reflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ RuntimeTypeHandle resolvedRuntimeTypeHandle;
+ if (executionDomain.ExecutionEnvironment.TryGetNamedTypeForTypeReference(reader, typeReferenceHandle, out resolvedRuntimeTypeHandle))
+ return ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(resolvedRuntimeTypeHandle);
+ }
+ }
+
+ TypeReference typeReference = typeReferenceHandle.GetTypeReference(reader);
+ String name = typeReference.TypeName.GetString(reader);
+ Handle parent = typeReference.ParentNamespaceOrType;
+ HandleType parentType = parent.HandleType;
+ TypeInfo outerTypeInfo = null;
+
+ // Check if this is a reference to a nested type.
+
+ if (parentType == HandleType.TypeDefinition)
+ {
+ outerTypeInfo = RuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(reader, parent.ToTypeDefinitionHandle(reader));
+ }
+ else if (parentType == HandleType.TypeReference)
+ {
+ RuntimeType outerType = reflectionDomain.TryResolveTypeReference(reader, parent.ToTypeReferenceHandle(reader), ref exception);
+ if (outerType == null)
+ return null;
+ outerTypeInfo = outerType.GetTypeInfo(); // Since we got to outerType via a metadata reference, we're assured GetTypeInfo() won't throw a MissingMetadataException.
+ }
+ if (outerTypeInfo != null)
+ {
+ // It was a nested type. We've already resolved the containing type recursively - just find the nested among its direct children.
+ TypeInfo resolvedTypeInfo = outerTypeInfo.GetDeclaredNestedType(name);
+ if (resolvedTypeInfo == null)
+ {
+ exception = reflectionDomain.CreateMissingMetadataException(outerTypeInfo, name);
+ return null;
+ }
+ return (RuntimeType)(resolvedTypeInfo.AsType());
+ }
+
+
+ // If we got here, the typeReference was to a non-nested type.
+ if (parentType == HandleType.NamespaceReference)
+ {
+ AssemblyQualifiedTypeName assemblyQualifiedTypeName = parent.ToNamespaceReferenceHandle(reader).ToAssemblyQualifiedTypeName(name, reader);
+ RuntimeType runtimeType;
+ exception = assemblyQualifiedTypeName.TryResolve(reflectionDomain, null, /*ignoreCase: */false, out runtimeType);
+ if (exception != null)
+ return null;
+ return runtimeType;
+ }
+
+ throw new BadImageFormatException(); // Expected TypeReference parent to be typeRef, typeDef or namespaceRef.
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs
new file mode 100644
index 000000000..42215e92b
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ internal sealed class OpenMethodInvoker : MethodInvoker
+ {
+ public sealed override Object Invoke(Object thisObject, Object[] arguments)
+ {
+ throw new InvalidOperationException(SR.Arg_UnboundGenParam);
+ }
+
+ public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, Object target, bool isStatic, bool isVirtual, bool isOpen)
+ {
+ throw new InvalidOperationException(SR.Arg_UnboundGenParam);
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs
new file mode 100644
index 000000000..705469dd8
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs
@@ -0,0 +1,168 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // The runtime's implementation of non-constructor MethodInfo's that represent an open or closed costruction of a generic method.
+ //
+ internal sealed partial class RuntimeConstructedGenericMethodInfo : RuntimeMethodInfo
+ {
+ private RuntimeConstructedGenericMethodInfo(RuntimeNamedMethodInfo genericMethodDefinition, RuntimeType[] genericTypeArguments)
+ {
+ _genericMethodDefinition = genericMethodDefinition;
+ _genericTypeArguments = genericTypeArguments;
+ }
+
+ public sealed override MethodAttributes Attributes
+ {
+ get
+ {
+ return _genericMethodDefinition.Attributes;
+ }
+ }
+
+ public sealed override CallingConventions CallingConvention
+ {
+ get
+ {
+ return _genericMethodDefinition.CallingConvention;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return _genericMethodDefinition.CustomAttributes;
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeConstructedGenericMethodInfo other = obj as RuntimeConstructedGenericMethodInfo;
+ if (other == null)
+ return false;
+ if (!this._genericMethodDefinition.Equals(other._genericMethodDefinition))
+ return false;
+ if (this._genericTypeArguments.Length != other._genericTypeArguments.Length)
+ return false;
+ for (int i = 0; i < _genericTypeArguments.Length; i++)
+ {
+ if (!this._genericTypeArguments[i].Equals(other._genericTypeArguments[i]))
+ return false;
+ }
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _genericMethodDefinition.GetHashCode();
+ }
+
+ public sealed override MethodInfo GetGenericMethodDefinition()
+ {
+ return _genericMethodDefinition;
+ }
+
+ public sealed override bool IsGenericMethod
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public sealed override bool IsGenericMethodDefinition
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericMethodDefinition, this));
+ }
+
+ public sealed override MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return _genericMethodDefinition.MethodImplementationFlags;
+ }
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return _genericMethodDefinition.Module;
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ return _genericMethodDefinition.ComputeToString(this);
+ }
+
+ protected sealed override MethodInvoker UncachedMethodInvoker
+ {
+ get
+ {
+ return ReflectionCoreExecution.ExecutionEnvironment.GetMethodInvoker(
+ _genericMethodDefinition.Reader,
+ _genericMethodDefinition.RuntimeDeclaringType,
+ _genericMethodDefinition.MethodHandle,
+ _genericTypeArguments,
+ this);
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeDeclaringType
+ {
+ get
+ {
+ return _genericMethodDefinition.RuntimeDeclaringType;
+ }
+ }
+
+ internal sealed override RuntimeType[] RuntimeGenericArgumentsOrParameters
+ {
+ get
+ {
+ return _genericTypeArguments;
+ }
+ }
+
+ internal sealed override String RuntimeName
+ {
+ get
+ {
+ return _genericMethodDefinition.RuntimeName;
+ }
+ }
+
+ internal sealed override RuntimeParameterInfo[] GetRuntimeParametersAndReturn(RuntimeMethodInfo contextMethod)
+ {
+ return _genericMethodDefinition.GetRuntimeParametersAndReturn(this);
+ }
+
+ private RuntimeNamedMethodInfo _genericMethodDefinition;
+ private RuntimeType[] _genericTypeArguments;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs
new file mode 100644
index 000000000..34d42d94f
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs
@@ -0,0 +1,151 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Tracing;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // The runtime's implementation of ConstructorInfo.
+ //
+ internal abstract partial class RuntimeConstructorInfo : ExtensibleConstructorInfo
+ {
+ public abstract override MethodAttributes Attributes { get; }
+
+ public abstract override CallingConventions CallingConvention { get; }
+
+ public sealed override bool ContainsGenericParameters
+ {
+ get
+ {
+ return DeclaringType.GetTypeInfo().ContainsGenericParameters;
+ }
+ }
+
+ public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; }
+
+ public abstract override Type DeclaringType { get; }
+
+ public sealed override Type[] GetGenericArguments()
+ {
+ // Constructors cannot be generic. Desktop compat dictates that We throw NotSupported rather than returning a 0-length array.
+ throw new NotSupportedException();
+ }
+
+ public sealed override ParameterInfo[] GetParameters()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_GetParameters(this);
+
+ RuntimeParameterInfo[] runtimeParametersAndReturn = this.RuntimeParametersAndReturn;
+ if (runtimeParametersAndReturn.Length == 1)
+ return Array.Empty<ParameterInfo>();
+ ParameterInfo[] result = new ParameterInfo[runtimeParametersAndReturn.Length - 1];
+ for (int i = 0; i < result.Length; i++)
+ result[i] = runtimeParametersAndReturn[i + 1];
+ return result;
+ }
+
+ public abstract override Object Invoke(Object[] parameters);
+
+ public sealed override Object Invoke(Object obj, Object[] parameters)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_Invoke(this, obj, parameters);
+
+ if (parameters == null)
+ parameters = Array.Empty<Object>();
+ MethodInvoker methodInvoker;
+ try
+ {
+ methodInvoker = this.MethodInvoker;
+ }
+ catch (Exception)
+ {
+ //
+ // Project N compat note: On the desktop, ConstructorInfo.Invoke(Object[]) specifically forbids invoking static constructors (and
+ // for us, that check is embedded inside the MethodInvoker property call.) Howver, MethodBase.Invoke(Object, Object[]) allows it. This was
+ // probably an oversight on the desktop. We choose not to support this loophole on Project N for the following reasons:
+ //
+ // 1. The Project N toolchain aggressively replaces static constructors with static initialization data whenever possible.
+ // So the static constructor may no longer exist.
+ //
+ // 2. Invoking the static constructor through Reflection is not very useful as it invokes the static constructor whether or not
+ // it was already run. Since static constructors are specifically one-shot deals, this will almost certainly mess up the
+ // type's internal assumptions.
+ //
+
+ if (this.IsStatic)
+ throw new PlatformNotSupportedException(SR.Acc_NotClassInit);
+ throw;
+ }
+
+ return methodInvoker.Invoke(obj, parameters);
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return DeclaringType.GetTypeInfo().Module;
+ }
+ }
+
+ public sealed override bool IsGenericMethod
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public sealed override bool IsGenericMethodDefinition
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public abstract override MethodImplAttributes MethodImplementationFlags { get; }
+
+ public abstract override String Name { get; }
+
+ public abstract override bool Equals(Object obj);
+
+ public abstract override int GetHashCode();
+
+ public abstract override String ToString();
+
+ protected MethodInvoker MethodInvoker
+ {
+ get
+ {
+ if (_lazyMethodInvoker == null)
+ {
+ _lazyMethodInvoker = UncachedMethodInvoker;
+ }
+ return _lazyMethodInvoker;
+ }
+ }
+
+ protected abstract RuntimeParameterInfo[] RuntimeParametersAndReturn { get; }
+
+ protected abstract MethodInvoker UncachedMethodInvoker { get; }
+
+ private volatile MethodInvoker _lazyMethodInvoker = null;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodCommon.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodCommon.cs
new file mode 100644
index 000000000..97b67f77c
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodCommon.cs
@@ -0,0 +1,308 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Text;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // Implements methods and properties common to RuntimeMethodInfo and RuntimeConstructorInfo. In a sensible world, this
+ // struct would be a common base class for RuntimeMethodInfo and RuntimeConstructorInfo. But those types are forced
+ // to derive from MethodInfo and ConstructorInfo because of the way the Reflection API are designed. Hence,
+ // we use containment as a substitute.
+ //
+ internal struct RuntimeMethodCommon
+ {
+ //
+ // methodHandle - the "tkMethodDef" that identifies the method.
+ // definingType - the "tkTypeDef" that defined the method (this is where you get the metadata reader that created methodHandle.)
+ // contextType - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
+ // get your raw information from "definingType", you report "contextType" as your DeclaringType property.
+ //
+ // For example:
+ //
+ // typeof(Foo<>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType and contextType are both Foo<>
+ //
+ // typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType is "Foo<,>"
+ // The contextType is "Foo<int,String>"
+ //
+ // We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
+ //
+ public RuntimeMethodCommon(MethodHandle methodHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ _definingTypeInfo = definingTypeInfo;
+ _methodHandle = methodHandle;
+ _contextTypeInfo = contextTypeInfo;
+ _reader = definingTypeInfo.Reader;
+ _method = methodHandle.GetMethod(_reader);
+ }
+
+ public MethodAttributes Attributes
+ {
+ get
+ {
+ return _method.Flags;
+ }
+ }
+
+ public CallingConventions CallingConvention
+ {
+ get
+ {
+ return MethodSignature.CallingConvention;
+ }
+ }
+
+ // Compute the ToString() value in a pay-to-play-safe way.
+ public String ComputeToString(MethodBase contextMethod, RuntimeType[] methodTypeArguments)
+ {
+ RuntimeParameterInfo[] runtimeParametersAndReturn = this.GetRuntimeParametersAndReturn(contextMethod, methodTypeArguments);
+ return ComputeToString(contextMethod, methodTypeArguments, runtimeParametersAndReturn);
+ }
+
+
+ public static String ComputeToString(MethodBase contextMethod, RuntimeType[] methodTypeArguments, RuntimeParameterInfo[] runtimeParametersAndReturn)
+ {
+ StringBuilder sb = new StringBuilder(30);
+ sb.Append(runtimeParametersAndReturn[0].ParameterTypeString);
+ sb.Append(' ');
+ sb.Append(contextMethod.Name);
+ if (methodTypeArguments.Length != 0)
+ {
+ String sep = "";
+ sb.Append('[');
+ foreach (RuntimeType methodTypeArgument in methodTypeArguments)
+ {
+ sb.Append(sep);
+ sep = ",";
+ String name = methodTypeArgument.InternalNameIfAvailable;
+ if (name == null)
+ name = ToStringUtils.UnavailableType;
+ sb.Append(methodTypeArgument.Name);
+ }
+ sb.Append(']');
+ }
+ sb.Append('(');
+ sb.Append(ComputeParametersString(runtimeParametersAndReturn, 1));
+ sb.Append(')');
+
+ return sb.ToString();
+ }
+
+ // Used by method and property ToString() methods to display the list of parameter types. Replicates the behavior of MethodBase.ConstructParameters()
+ // but in a pay-to-play-safe way.
+ public static String ComputeParametersString(RuntimeParameterInfo[] runtimeParametersAndReturn, int startIndex)
+ {
+ StringBuilder sb = new StringBuilder(30);
+ for (int i = startIndex; i < runtimeParametersAndReturn.Length; i++)
+ {
+ if (i != startIndex)
+ sb.Append(", ");
+ String parameterTypeString = runtimeParametersAndReturn[i].ParameterTypeString;
+
+ // Legacy: Why use "ByRef" for by ref parameters? What language is this?
+ // VB uses "ByRef" but it should precede (not follow) the parameter name.
+ // Why don't we just use "&"?
+ if (parameterTypeString.EndsWith("&"))
+ parameterTypeString = parameterTypeString.Substring(0, parameterTypeString.Length - 1) + " ByRef";
+ sb.Append(parameterTypeString);
+ }
+ return sb.ToString();
+ }
+
+ public RuntimeTypeInfo ContextTypeInfo
+ {
+ get
+ {
+ return _contextTypeInfo;
+ }
+ }
+
+ public IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ IEnumerable<CustomAttributeData> customAttributes = RuntimeCustomAttributeData.GetCustomAttributes(_definingTypeInfo.ReflectionDomain, _reader, _method.CustomAttributes);
+ foreach (CustomAttributeData cad in customAttributes)
+ yield return cad;
+ ExecutionDomain executionDomain = this.DefiningTypeInfo.ReflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(_reader, _methodHandle, _definingTypeInfo.TypeDefinitionHandle))
+ yield return cad;
+ }
+ }
+ }
+
+ public RuntimeType DeclaringType
+ {
+ get
+ {
+ return _contextTypeInfo.RuntimeType;
+ }
+ }
+
+ public RuntimeNamedTypeInfo DefiningTypeInfo
+ {
+ get
+ {
+ return _definingTypeInfo;
+ }
+ }
+
+ public MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return _method.ImplFlags;
+ }
+ }
+
+ public Module Module
+ {
+ get
+ {
+ return _definingTypeInfo.Module;
+ }
+ }
+
+ //
+ // Returns the ParameterInfo objects for the return parameter (in element 0), and the method parameters (in elements 1..length).
+ //
+ // The ParameterInfo objects will report "contextMethod" as their Member property and use it to get type variable information from
+ // the contextMethod's declaring type. The actual metadata, however, comes from "this."
+ //
+ // The methodTypeArguments provides the fill-ins for any method type variable elements in the parameter type signatures.
+ //
+ // Does not array-copy.
+ //
+ public RuntimeMethodParameterInfo[] GetRuntimeParametersAndReturn(MethodBase contextMethod, RuntimeType[] methodTypeArguments)
+ {
+ MetadataReader reader = _reader;
+ TypeContext typeContext = contextMethod.DeclaringType.GetRuntimeTypeInfo<RuntimeTypeInfo>().TypeContext;
+ typeContext = new TypeContext(typeContext.GenericTypeArguments, methodTypeArguments);
+ ReflectionDomain reflectionDomain = _definingTypeInfo.ReflectionDomain;
+ MethodSignature methodSignature = this.MethodSignature;
+ LowLevelList<Handle> typeSignatures = new LowLevelList<Handle>(10);
+ typeSignatures.Add(methodSignature.ReturnType.GetReturnTypeSignature(_reader).Type);
+ foreach (ParameterTypeSignatureHandle parameterTypeSignatureHandle in methodSignature.Parameters)
+ {
+ typeSignatures.Add(parameterTypeSignatureHandle.GetParameterTypeSignature(_reader).Type);
+ }
+ int count = typeSignatures.Count;
+
+ RuntimeMethodParameterInfo[] result = new RuntimeMethodParameterInfo[count];
+ foreach (ParameterHandle parameterHandle in _method.Parameters)
+ {
+ Parameter parameterRecord = parameterHandle.GetParameter(_reader);
+ int index = parameterRecord.Sequence;
+ result[index] =
+ RuntimeFatMethodParameterInfo.GetRuntimeFatMethodParameterInfo(
+ contextMethod,
+ _methodHandle,
+ index - 1,
+ parameterHandle,
+ reflectionDomain,
+ reader,
+ typeSignatures[index],
+ typeContext);
+ }
+ for (int i = 0; i < count; i++)
+ {
+ if (result[i] == null)
+ {
+ result[i] =
+ RuntimeThinMethodParameterInfo.GetRuntimeThinMethodParameterInfo(
+ contextMethod,
+ i - 1,
+ reflectionDomain,
+ reader,
+ typeSignatures[i],
+ typeContext);
+ }
+ }
+ return result;
+ }
+
+ public String Name
+ {
+ get
+ {
+ return _method.Name.GetString(_reader);
+ }
+ }
+
+ public MetadataReader Reader
+ {
+ get
+ {
+ return _reader;
+ }
+ }
+
+ public MethodHandle MethodHandle
+ {
+ get
+ {
+ return _methodHandle;
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is RuntimeMethodCommon))
+ return false;
+ return Equals((RuntimeMethodCommon)obj);
+ }
+
+ public bool Equals(RuntimeMethodCommon other)
+ {
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._methodHandle.Equals(other._methodHandle)))
+ return false;
+ if (!(this._contextTypeInfo.Equals(other._contextTypeInfo)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return _methodHandle.GetHashCode() ^ _contextTypeInfo.GetHashCode();
+ }
+
+ private MethodSignature MethodSignature
+ {
+ get
+ {
+ return _method.Signature.GetMethodSignature(_reader);
+ }
+ }
+
+ private RuntimeNamedTypeInfo _definingTypeInfo;
+ private MethodHandle _methodHandle;
+ private RuntimeTypeInfo _contextTypeInfo;
+
+ private MetadataReader _reader;
+
+ private Method _method;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
new file mode 100644
index 000000000..a482f17ba
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
@@ -0,0 +1,402 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // Abstract base class for RuntimeNamedMethodInfo, RuntimeConstructedGenericMethodInfo.
+ //
+ internal abstract class RuntimeMethodInfo : ExtensibleMethodInfo, ITraceableTypeMember
+ {
+ protected RuntimeMethodInfo()
+ {
+ }
+
+ public abstract override MethodAttributes Attributes
+ {
+ get;
+ }
+
+ public abstract override CallingConventions CallingConvention
+ {
+ get;
+ }
+
+ public sealed override bool ContainsGenericParameters
+ {
+ get
+ {
+ if (DeclaringType.GetTypeInfo().ContainsGenericParameters)
+ return true;
+
+ if (!IsGenericMethod)
+ return false;
+
+ Type[] pis = GetGenericArguments();
+ for (int i = 0; i < pis.Length; i++)
+ {
+ if (pis[i].GetTypeInfo().ContainsGenericParameters)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public sealed override Delegate CreateDelegate(Type delegateType)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodInfo_CreateDelegate(this, delegateType);
+
+ // Legacy: The only difference between calling CreateDelegate(type) and CreateDelegate(type, null) is that the former
+ // disallows closed instance delegates for V1.1 backward compatibility.
+ return CreateDelegate(delegateType, null, allowClosedInstanceDelegates: false);
+ }
+
+ public sealed override Delegate CreateDelegate(Type delegateType, Object target)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodInfo_CreateDelegate(this, delegateType, target);
+
+ return CreateDelegate(delegateType, target, allowClosedInstanceDelegates: true);
+ }
+
+ public abstract override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get;
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_DeclaringType(this);
+ return this.RuntimeDeclaringType;
+ }
+ }
+
+ public abstract override bool Equals(object obj);
+
+ public sealed override Type[] GetGenericArguments()
+ {
+ RuntimeType[] genericArgumentsOrParameters = this.RuntimeGenericArgumentsOrParameters;
+ if (genericArgumentsOrParameters.Length == 0)
+ return Array.Empty<Type>();
+ Type[] result = new Type[genericArgumentsOrParameters.Length];
+ for (int i = 0; i < genericArgumentsOrParameters.Length; i++)
+ result[i] = genericArgumentsOrParameters[i];
+ return result;
+ }
+
+ public abstract override MethodInfo GetGenericMethodDefinition();
+
+ public abstract override int GetHashCode();
+
+ public sealed override ParameterInfo[] GetParameters()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_GetParameters(this);
+
+ RuntimeParameterInfo[] runtimeParameterInfos = this.GetRuntimeParametersAndReturn(this);
+ if (runtimeParameterInfos.Length == 1)
+ return Array.Empty<ParameterInfo>();
+ ParameterInfo[] result = new ParameterInfo[runtimeParameterInfos.Length - 1];
+ for (int i = 0; i < result.Length; i++)
+ result[i] = runtimeParameterInfos[i + 1];
+ return result;
+ }
+
+ public sealed override Object Invoke(Object obj, Object[] parameters)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_Invoke(this, obj, parameters);
+
+ if (parameters == null)
+ parameters = Array.Empty<Object>();
+ MethodInvoker methodInvoker = this.MethodInvoker;
+ return methodInvoker.Invoke(obj, parameters);
+ }
+
+ public abstract override bool IsGenericMethod
+ {
+ get;
+ }
+
+ public abstract override bool IsGenericMethodDefinition
+ {
+ get;
+ }
+
+ public abstract override MethodInfo MakeGenericMethod(params Type[] typeArguments);
+
+ public abstract override MethodImplAttributes MethodImplementationFlags
+ {
+ get;
+ }
+
+ public abstract override Module Module
+ {
+ get;
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_Name(this);
+ return this.RuntimeName;
+ }
+ }
+
+ public sealed override ParameterInfo ReturnParameter
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodInfo_ReturnParameter(this);
+
+ return this.GetRuntimeParametersAndReturn(this)[0];
+ }
+ }
+
+ public sealed override Type ReturnType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodInfo_ReturnType(this);
+
+ return ReturnParameter.ParameterType;
+ }
+ }
+
+ public abstract override String ToString();
+
+ Type ITraceableTypeMember.ContainingType
+ {
+ get
+ {
+ return this.RuntimeDeclaringType;
+ }
+ }
+
+ String ITraceableTypeMember.MemberName
+ {
+ get
+ {
+ return this.RuntimeName;
+ }
+ }
+
+ internal abstract RuntimeType RuntimeDeclaringType
+ {
+ get;
+ }
+
+ internal abstract String RuntimeName
+ {
+ get;
+ }
+
+ protected abstract MethodInvoker UncachedMethodInvoker { get; }
+
+ //
+ // The non-public version of MethodInfo.GetGenericArguments() (does not array-copy and has a more truthful name.)
+ //
+ internal abstract RuntimeType[] RuntimeGenericArgumentsOrParameters { get; }
+
+ //
+ // The non-public version of MethodInfo.GetParameters() (does not array-copy.)
+ // The first element is actually the ReturnParameter value.
+ //
+ internal abstract RuntimeParameterInfo[] GetRuntimeParametersAndReturn(RuntimeMethodInfo contextMethod);
+
+ internal MethodInvoker MethodInvoker
+ {
+ get
+ {
+ MethodInvoker methodInvoker = _lazyMethodInvoker;
+ if (methodInvoker == null)
+ {
+ if (ReturnType.IsByRef)
+ throw new NotSupportedException(SR.NotSupported_ByRefReturn);
+ methodInvoker = _lazyMethodInvoker = this.UncachedMethodInvoker;
+ }
+ return methodInvoker;
+ }
+ }
+
+ private volatile MethodInvoker _lazyMethodInvoker = null;
+
+
+ //
+ // Common CreateDelegate worker.
+ //
+ private Delegate CreateDelegate(Type delegateType, Object target, bool allowClosedInstanceDelegates)
+ {
+ if (delegateType == null)
+ throw new ArgumentNullException("delegateType");
+
+ ExecutionEnvironment executionEnvironment = ReflectionCoreExecution.ExecutionEnvironment;
+ RuntimeTypeHandle delegateTypeHandle = delegateType.TypeHandle;
+ if (!executionEnvironment.IsAssignableFrom(typeof(Delegate).TypeHandle, delegateTypeHandle))
+ throw new ArgumentException(SR.Arg_MustBeDelegate);
+ IEnumerator<MethodInfo> invokeMethodEnumerator = delegateType.GetTypeInfo().GetDeclaredMethods("Invoke").GetEnumerator();
+ if (!invokeMethodEnumerator.MoveNext())
+ {
+ // No Invoke method found. Since delegate types are compiler constructed, the most likely cause is missing metadata rather than
+ // a missing Invoke method.
+
+ // We're deliberating calling FullName rather than ToString() because if it's the type that's missing metadata,
+ // the FullName property constructs a more informative MissingMetadataException than we can.
+ String fullName = delegateType.FullName;
+ throw new MissingMetadataException(SR.Format(SR.Arg_InvokeMethodMissingMetadata, fullName)); // No invoke method found.
+ }
+ MethodInfo invokeMethod = invokeMethodEnumerator.Current;
+ if (invokeMethodEnumerator.MoveNext())
+ throw new ArgumentException(SR.Arg_MustBeDelegate); // Multiple invoke methods found.
+
+ // Make sure the return type is assignment-compatible.
+ CheckIsAssignableFrom(executionEnvironment, invokeMethod.ReturnParameter.ParameterType, this.ReturnParameter.ParameterType);
+
+ IList<ParameterInfo> delegateParameters = invokeMethod.GetParameters();
+ IList<ParameterInfo> targetParameters = this.GetParameters();
+ IEnumerator<ParameterInfo> delegateParameterEnumerator = delegateParameters.GetEnumerator();
+ IEnumerator<ParameterInfo> targetParameterEnumerator = targetParameters.GetEnumerator();
+
+ bool isStatic = this.IsStatic;
+ bool isOpen;
+ if (isStatic)
+ {
+ if (delegateParameters.Count == targetParameters.Count)
+ {
+ // Open static: This is the "typical" case of calling a static method.
+ isOpen = true;
+ if (target != null)
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ }
+ else
+ {
+ // Closed static: This is the "weird" v2.0 case where the delegate is closed over the target method's first parameter.
+ // (it make some kinda sense if you think of extension methods.)
+ isOpen = false;
+ if (!targetParameterEnumerator.MoveNext())
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ if (target != null)
+ CheckIsAssignableFrom(executionEnvironment, targetParameterEnumerator.Current.ParameterType, target.GetType());
+ }
+ }
+ else
+ {
+ if (delegateParameters.Count == targetParameters.Count)
+ {
+ // Closed instance: This is the "typical" case of invoking an instance method.
+ isOpen = false;
+ if (!allowClosedInstanceDelegates)
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ if (target != null)
+ CheckIsAssignableFrom(executionEnvironment, this.DeclaringType, target.GetType());
+ }
+ else
+ {
+ // Open instance: This is the "weird" v2.0 case where the delegate has a leading extra parameter that's assignable to the target method's
+ // declaring type.
+ if (!delegateParameterEnumerator.MoveNext())
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ isOpen = true;
+ CheckIsAssignableFrom(executionEnvironment, this.DeclaringType, delegateParameterEnumerator.Current.ParameterType);
+ if (target != null)
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ }
+ }
+
+ // Verify that the parameters that the delegate and method have in common are assignment-compatible.
+ while (delegateParameterEnumerator.MoveNext())
+ {
+ if (!targetParameterEnumerator.MoveNext())
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ CheckIsAssignableFrom(executionEnvironment, targetParameterEnumerator.Current.ParameterType, delegateParameterEnumerator.Current.ParameterType);
+ }
+ if (targetParameterEnumerator.MoveNext())
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+
+ return this.MethodInvoker.CreateDelegate(delegateType.TypeHandle, target, isStatic: isStatic, isVirtual: false, isOpen: isOpen);
+ }
+
+
+ private static void CheckIsAssignableFrom(ExecutionEnvironment executionEnvironment, Type dstType, Type srcType)
+ {
+ // byref types do not have a TypeHandle so we must treat these separately.
+ if (dstType.IsByRef && srcType.IsByRef)
+ {
+ if (!dstType.Equals(srcType))
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ }
+
+ // Enable pointers (which don't necessarily have typehandles). todo:be able to handle intptr <-> pointer, check if we need to handle
+ // casts via pointer where the pointer types aren't identical
+ if (dstType.Equals(srcType))
+ {
+ return;
+ }
+
+ // If assignment compatible in the normal way, allow
+ if (executionEnvironment.IsAssignableFrom(dstType.TypeHandle, srcType.TypeHandle))
+ {
+ return;
+ }
+
+ // they are not compatible yet enums can go into each other if their underlying element type is the same
+ // or into their equivalent integral type
+ Type dstTypeUnderlying = dstType;
+ if (dstType.GetTypeInfo().IsEnum)
+ {
+ dstTypeUnderlying = Enum.GetUnderlyingType(dstType);
+ }
+ Type srcTypeUnderlying = srcType;
+ if (srcType.GetTypeInfo().IsEnum)
+ {
+ srcTypeUnderlying = Enum.GetUnderlyingType(srcType);
+ }
+ if (dstTypeUnderlying.Equals(srcTypeUnderlying))
+ {
+ return;
+ }
+
+ throw new ArgumentException(SR.Arg_DlgtTargMeth);
+ }
+
+ protected RuntimeMethodInfo WithDebugName()
+ {
+#if DEBUG
+ if (_debugName == null)
+ {
+ _debugName = "Constructing..."; // Protect against any inadvertent reentrancy.
+ _debugName = ((ITraceableTypeMember)this).MemberName;
+ }
+#endif
+ return this;
+ }
+
+#if DEBUG
+ private String _debugName;
+#endif
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
new file mode 100644
index 000000000..d7fa9f08d
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
@@ -0,0 +1,245 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // The runtime's implementation of non-constructor MethodInfo's that represent a method definition.
+ //
+ internal sealed partial class RuntimeNamedMethodInfo : RuntimeMethodInfo
+ {
+ //
+ // methodHandle - the "tkMethodDef" that identifies the method.
+ // definingType - the "tkTypeDef" that defined the method (this is where you get the metadata reader that created methodHandle.)
+ // contextType - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
+ // get your raw information from "definingType", you report "contextType" as your DeclaringType property.
+ //
+ // For example:
+ //
+ // typeof(Foo<>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType and contextType are both Foo<>
+ //
+ // typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType is "Foo<,>"
+ // The contextType is "Foo<int,String>"
+ //
+ // We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
+ //
+ private RuntimeNamedMethodInfo(MethodHandle methodHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ : base()
+ {
+ _common = new RuntimeMethodCommon(methodHandle, definingTypeInfo, contextTypeInfo);
+ }
+
+ public sealed override MethodAttributes Attributes
+ {
+ get
+ {
+ return _common.Attributes;
+ }
+ }
+
+ public sealed override CallingConventions CallingConvention
+ {
+ get
+ {
+ return _common.CallingConvention;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_CustomAttributes(this);
+
+ return _common.CustomAttributes;
+ }
+ }
+
+ public sealed override MethodInfo GetGenericMethodDefinition()
+ {
+ if (IsGenericMethodDefinition)
+ return this;
+ throw new InvalidOperationException();
+ }
+
+ public sealed override bool IsGenericMethod
+ {
+ get
+ {
+ return IsGenericMethodDefinition;
+ }
+ }
+
+ public sealed override bool IsGenericMethodDefinition
+ {
+ get
+ {
+ Method method = _common.MethodHandle.GetMethod(_common.Reader);
+ return method.GenericParameters.GetEnumerator().MoveNext();
+ }
+ }
+
+ public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodInfo_MakeGenericMethod(this, typeArguments);
+
+ if (typeArguments == null)
+ throw new ArgumentNullException("typeArguments");
+ if (GenericTypeParameters.Length == 0)
+ throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericMethodDefinition, this));
+ RuntimeType[] genericTypeArguments = new RuntimeType[typeArguments.Length];
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ if (typeArguments[i] == null)
+ throw new ArgumentNullException();
+
+ genericTypeArguments[i] = typeArguments[i] as RuntimeType;
+ if (genericTypeArguments[i] == null)
+ throw new ArgumentException(SR.Format(SR.Reflection_CustomReflectionObjectsNotSupported, typeArguments[i]), "typeArguments[" + i + "]"); // Not a runtime type.
+ }
+ if (typeArguments.Length != GenericTypeParameters.Length)
+ throw new ArgumentException(SR.Format(SR.Argument_NotEnoughGenArguments, typeArguments.Length, GenericTypeParameters.Length));
+ RuntimeMethodInfo methodInfo = (RuntimeMethodInfo)RuntimeConstructedGenericMethodInfo.GetRuntimeConstructedGenericMethodInfo(this, genericTypeArguments);
+ MethodInvoker methodInvoker = methodInfo.MethodInvoker; // For compatibility with other Make* apis, trigger any MissingMetadataExceptions now rather than later.
+ return methodInfo;
+ }
+
+ public sealed override MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return _common.MethodImplementationFlags;
+ }
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return _common.Module;
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ return ComputeToString(this);
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeNamedMethodInfo other = obj as RuntimeNamedMethodInfo;
+ if (other == null)
+ return false;
+ return this._common.Equals(other._common);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _common.GetHashCode();
+ }
+
+ internal String ComputeToString(RuntimeMethodInfo contextMethod)
+ {
+ return _common.ComputeToString(contextMethod, contextMethod.RuntimeGenericArgumentsOrParameters);
+ }
+
+ internal MethodHandle MethodHandle
+ {
+ get
+ {
+ return _common.MethodHandle;
+ }
+ }
+
+ internal MetadataReader Reader
+ {
+ get
+ {
+ return _common.Reader;
+ }
+ }
+
+ internal sealed override RuntimeType[] RuntimeGenericArgumentsOrParameters
+ {
+ get
+ {
+ return this.GenericTypeParameters;
+ }
+ }
+
+ internal sealed override RuntimeParameterInfo[] GetRuntimeParametersAndReturn(RuntimeMethodInfo contextMethod)
+ {
+ return _common.GetRuntimeParametersAndReturn(contextMethod, contextMethod.RuntimeGenericArgumentsOrParameters);
+ }
+
+ internal sealed override RuntimeType RuntimeDeclaringType
+ {
+ get
+ {
+ return _common.DeclaringType;
+ }
+ }
+
+ internal sealed override String RuntimeName
+ {
+ get
+ {
+ return _common.Name;
+ }
+ }
+
+ private RuntimeType[] GenericTypeParameters
+ {
+ get
+ {
+ LowLevelList<RuntimeType> genericTypeParameters = new LowLevelList<RuntimeType>();
+ Method method = _common.MethodHandle.GetMethod(_common.Reader);
+ foreach (GenericParameterHandle genericParameterHandle in method.GenericParameters)
+ {
+ RuntimeNamedMethodInfo owningMethod = this;
+ if (DeclaringType.IsConstructedGenericType)
+ {
+ // Desktop compat: Constructed generic types and their generic type definitions share the same Type objects for method generic parameters.
+ RuntimeNamedTypeInfo genericTypeDefinition = DeclaringType.GetGenericTypeDefinition().GetRuntimeTypeInfo<RuntimeNamedTypeInfo>();
+ owningMethod = RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(MethodHandle, genericTypeDefinition, genericTypeDefinition);
+ }
+ RuntimeType genericParameterType = RuntimeTypeUnifierEx.GetRuntimeGenericParameterTypeForMethods(owningMethod, owningMethod._common.Reader, genericParameterHandle);
+ genericTypeParameters.Add(genericParameterType);
+ }
+ return genericTypeParameters.ToArray();
+ }
+ }
+
+ protected sealed override MethodInvoker UncachedMethodInvoker
+ {
+ get
+ {
+ return ReflectionCoreExecution.ExecutionEnvironment.GetMethodInvoker(_common.Reader, _common.DeclaringType, _common.MethodHandle, Array.Empty<RuntimeType>(), this);
+ }
+ }
+
+ private readonly RuntimeMethodCommon _common;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs
new file mode 100644
index 000000000..8aa7039e4
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs
@@ -0,0 +1,166 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // The runtime's implementation of ConstructorInfo's represented in the metadata (this is the 99% case.)
+ //
+ internal sealed partial class RuntimePlainConstructorInfo : RuntimeConstructorInfo
+ {
+ //
+ // methodHandle - the "tkMethodDef" that identifies the method.
+ // definingType - the "tkTypeDef" that defined the method (this is where you get the metadata reader that created methodHandle.)
+ // contextType - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
+ // get your raw information from "definingType", you report "contextType" as your DeclaringType property.
+ //
+ // For example:
+ //
+ // typeof(Foo<>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType and contextType are both Foo<>
+ //
+ // typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType is "Foo<,>"
+ // The contextType is "Foo<int,String>"
+ //
+ // We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
+ //
+ private RuntimePlainConstructorInfo(MethodHandle methodHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ _common = new RuntimeMethodCommon(methodHandle, definingTypeInfo, contextTypeInfo);
+ }
+
+ public sealed override MethodAttributes Attributes
+ {
+ get
+ {
+ return _common.Attributes;
+ }
+ }
+
+ public sealed override CallingConventions CallingConvention
+ {
+ get
+ {
+ return _common.CallingConvention;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_CustomAttributes(this);
+
+ return _common.CustomAttributes;
+ }
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_DeclaringType(this);
+
+ return _common.DeclaringType;
+ }
+ }
+
+ public sealed override Object Invoke(Object[] parameters)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.ConstructorInfo_Invoke(this, parameters);
+
+ if (parameters == null)
+ parameters = Array.Empty<Object>();
+
+ // Most objects are allocated by NewObject and their constructors return "void". But in many frameworks,
+ // there are "weird" cases (e.g. String) where the constructor must do both the allocation and initialization.
+ // Reflection.Core does not hardcode these special cases. It's up to the ExecutionEnvironment to steer
+ // us the right way by coordinating the implementation of NewObject and MethodInvoker.
+ Object newObject = ReflectionCoreExecution.ExecutionEnvironment.NewObject(this.DeclaringType.TypeHandle);
+ Object ctorAllocatedObject = this.MethodInvoker.Invoke(newObject, parameters);
+ return newObject != null ? newObject : ctorAllocatedObject;
+ }
+
+ public sealed override MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return _common.MethodImplementationFlags;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.MethodBase_Name(this);
+
+ return _common.Name;
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimePlainConstructorInfo other = obj as RuntimePlainConstructorInfo;
+ if (other == null)
+ return false;
+ return this._common.Equals(other._common);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _common.GetHashCode();
+ }
+
+ public sealed override String ToString()
+ {
+ return _common.ComputeToString(this, Array.Empty<RuntimeType>());
+ }
+
+ protected sealed override RuntimeParameterInfo[] RuntimeParametersAndReturn
+ {
+ get
+ {
+ return _common.GetRuntimeParametersAndReturn(this, Array.Empty<RuntimeType>());
+ }
+ }
+
+ protected sealed override MethodInvoker UncachedMethodInvoker
+ {
+ get
+ {
+ if (this._common.DefiningTypeInfo.IsAbstract)
+ throw new MemberAccessException(SR.Format(SR.Acc_CreateAbstEx, this._common.DefiningTypeInfo.FullName));
+
+ if (this.IsStatic)
+ throw new MemberAccessException(SR.Acc_NotClassInit);
+
+ return ReflectionCoreExecution.ExecutionEnvironment.GetMethodInvoker(_common.Reader, _common.DeclaringType, _common.MethodHandle, Array.Empty<RuntimeType>(), this);
+ }
+ }
+
+ private RuntimeMethodCommon _common;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs
new file mode 100644
index 000000000..854033ef4
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs
@@ -0,0 +1,152 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // The runtime's implementation of constructors exposed on array types.
+ //
+ internal sealed partial class RuntimeSyntheticConstructorInfo : RuntimeConstructorInfo
+ {
+ private RuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeType declaringType, RuntimeType[] runtimeParameterTypesAndReturn, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ {
+ _syntheticMethodId = syntheticMethodId;
+ _declaringType = declaringType;
+ _options = options;
+ _invoker = invoker;
+ _runtimeParameterTypesAndReturn = runtimeParameterTypesAndReturn;
+ }
+
+ public sealed override MethodAttributes Attributes
+ {
+ get
+ {
+ return MethodAttributes.Public | MethodAttributes.PrivateScope | MethodAttributes.RTSpecialName;
+ }
+ }
+
+ public sealed override CallingConventions CallingConvention
+ {
+ get
+ {
+ return CallingConventions.Standard | CallingConventions.HasThis;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ return _declaringType;
+ }
+ }
+
+ public sealed override Object Invoke(Object[] parameters)
+ {
+ if (parameters == null)
+ parameters = Array.Empty<Object>();
+
+ Object ctorAllocatedObject = this.MethodInvoker.Invoke(null, parameters);
+ return ctorAllocatedObject;
+ }
+
+ public sealed override MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return MethodImplAttributes.IL;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ return ConstructorName;
+ }
+ }
+
+ public sealed override bool Equals(object obj)
+ {
+ RuntimeSyntheticConstructorInfo other = obj as RuntimeSyntheticConstructorInfo;
+ if (other == null)
+ return false;
+ if (this._syntheticMethodId != other._syntheticMethodId)
+ return false;
+ if (!(this._declaringType.Equals(other._declaringType)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return this._declaringType.GetHashCode();
+ }
+
+ public sealed override String ToString()
+ {
+ return RuntimeMethodCommon.ComputeToString(this, Array.Empty<RuntimeType>(), RuntimeParametersAndReturn);
+ }
+
+ protected sealed override RuntimeParameterInfo[] RuntimeParametersAndReturn
+ {
+ get
+ {
+ RuntimeParameterInfo[] runtimeParametersAndReturn = _lazyRuntimeParametersAndReturn;
+ if (runtimeParametersAndReturn == null)
+ {
+ runtimeParametersAndReturn = new RuntimeParameterInfo[_runtimeParameterTypesAndReturn.Length];
+ for (int i = 0; i < runtimeParametersAndReturn.Length; i++)
+ {
+ runtimeParametersAndReturn[i] = RuntimeSyntheticParameterInfo.GetRuntimeSyntheticParameterInfo(this, i - 1, _runtimeParameterTypesAndReturn[i]);
+ }
+ _lazyRuntimeParametersAndReturn = runtimeParametersAndReturn;
+ }
+ return runtimeParametersAndReturn;
+ }
+ }
+
+ protected sealed override MethodInvoker UncachedMethodInvoker
+ {
+ get
+ {
+ RuntimeTypeHandle[] runtimeParameterTypeHandles = new RuntimeTypeHandle[_runtimeParameterTypesAndReturn.Length - 1];
+ for (int i = 1; i < _runtimeParameterTypesAndReturn.Length; i++)
+ runtimeParameterTypeHandles[i - 1] = _runtimeParameterTypesAndReturn[i].TypeHandle;
+ return ReflectionCoreExecution.ExecutionEnvironment.GetSyntheticMethodInvoker(
+ _declaringType.TypeHandle,
+ runtimeParameterTypeHandles,
+ _options,
+ _invoker);
+ }
+ }
+
+ private volatile RuntimeParameterInfo[] _lazyRuntimeParametersAndReturn;
+
+ private SyntheticMethodId _syntheticMethodId;
+ private RuntimeType _declaringType;
+ private RuntimeType[] _runtimeParameterTypesAndReturn;
+ private InvokerOptions _options;
+ private Func<Object, Object[], Object> _invoker;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
new file mode 100644
index 000000000..6b0dc7fe9
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
@@ -0,0 +1,185 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ //
+ // These methods implement the Get/Set methods on array types.
+ //
+ internal sealed partial class RuntimeSyntheticMethodInfo : RuntimeMethodInfo
+ {
+ private RuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeType declaringType, RuntimeType[] runtimeParameterTypesAndReturn, InvokerOptions options, Func<Object, Object[], Object> invoker)
+ {
+ _syntheticMethodId = syntheticMethodId;
+ _name = name;
+ _declaringType = declaringType;
+ _options = options;
+ _invoker = invoker;
+ _runtimeParameterTypesAndReturn = runtimeParameterTypesAndReturn;
+ }
+
+ public sealed override MethodAttributes Attributes
+ {
+ get
+ {
+ return MethodAttributes.Public | MethodAttributes.PrivateScope;
+ }
+ }
+
+ public sealed override CallingConventions CallingConvention
+ {
+ get
+ {
+ return CallingConventions.Standard | CallingConventions.HasThis;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeSyntheticMethodInfo other = obj as RuntimeSyntheticMethodInfo;
+ if (other == null)
+ return false;
+ if (this._syntheticMethodId != other._syntheticMethodId)
+ return false;
+ if (!(this._declaringType.Equals(other._declaringType)))
+ return false;
+ return true;
+ }
+
+ public sealed override MethodInfo GetGenericMethodDefinition()
+ {
+ throw new InvalidOperationException();
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return this._declaringType.GetHashCode();
+ }
+
+ public sealed override bool IsGenericMethod
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public sealed override bool IsGenericMethodDefinition
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericMethodDefinition, this));
+ }
+
+ public sealed override MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return MethodImplAttributes.IL;
+ }
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return this.DeclaringType.GetTypeInfo().Assembly.ManifestModule;
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ return RuntimeMethodCommon.ComputeToString(this, Array.Empty<RuntimeType>(), GetRuntimeParametersAndReturn(this));
+ }
+
+ protected sealed override MethodInvoker UncachedMethodInvoker
+ {
+ get
+ {
+ RuntimeTypeHandle[] runtimeParameterTypeHandles = new RuntimeTypeHandle[_runtimeParameterTypesAndReturn.Length - 1];
+ for (int i = 1; i < _runtimeParameterTypesAndReturn.Length; i++)
+ runtimeParameterTypeHandles[i - 1] = _runtimeParameterTypesAndReturn[i].TypeHandle;
+ return ReflectionCoreExecution.ExecutionEnvironment.GetSyntheticMethodInvoker(
+ _declaringType.TypeHandle,
+ runtimeParameterTypeHandles,
+ _options,
+ _invoker);
+ }
+ }
+
+ internal sealed override RuntimeType[] RuntimeGenericArgumentsOrParameters
+ {
+ get
+ {
+ return Array.Empty<RuntimeType>();
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeDeclaringType
+ {
+ get
+ {
+ return _declaringType;
+ }
+ }
+
+ internal sealed override String RuntimeName
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ internal sealed override RuntimeParameterInfo[] GetRuntimeParametersAndReturn(RuntimeMethodInfo contextMethod)
+ {
+ RuntimeParameterInfo[] runtimeParametersAndReturn = _lazyRuntimeParametersAndReturn;
+ if (runtimeParametersAndReturn == null)
+ {
+ runtimeParametersAndReturn = new RuntimeParameterInfo[_runtimeParameterTypesAndReturn.Length];
+ for (int i = 0; i < runtimeParametersAndReturn.Length; i++)
+ {
+ runtimeParametersAndReturn[i] = RuntimeSyntheticParameterInfo.GetRuntimeSyntheticParameterInfo(this, i - 1, _runtimeParameterTypesAndReturn[i]);
+ }
+ _lazyRuntimeParametersAndReturn = runtimeParametersAndReturn;
+ }
+ return runtimeParametersAndReturn;
+ }
+
+ private volatile RuntimeParameterInfo[] _lazyRuntimeParametersAndReturn;
+
+ private String _name;
+ private SyntheticMethodId _syntheticMethodId;
+ private RuntimeType _declaringType;
+ private RuntimeType[] _runtimeParameterTypesAndReturn;
+ private InvokerOptions _options;
+ private Func<Object, Object[], Object> _invoker;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs
new file mode 100644
index 000000000..9fdd73b59
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.MethodInfos
+{
+ internal enum SyntheticMethodId
+ {
+ ArrayCtor = 1,
+ ArrayMultiDimCtor = 2,
+ ArrayGet = 3,
+ ArraySet = 4,
+ ArrayAddress = 5,
+
+ // Ids from 0x80000000..0xffffffff are reserved for the jagged array constructors
+ // (e.g. a type such as T[][][][] has three such constructors so we need three ID's.
+ // We stick the parameter count into the lower bits to generate unique ids.)
+ ArrayCtorJagged = unchecked((int)0x80000000),
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs
new file mode 100644
index 000000000..62030bb23
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Collections.Generic;
+
+using global::Internal.Reflection.Extensibility;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.Modules
+{
+ //
+ // The runtime's implementation of a Module.
+ //
+ // Modules are quite meaningless in ProjectN but we have to keep up the appearances since they still exist in Win8P's surface area.
+ // As far as ProjectN is concerned, each Assembly has one module whose name is "<Unknown>".
+ //
+ internal sealed partial class RuntimeModule : ExtensibleModule
+ {
+ private RuntimeModule(RuntimeAssembly assembly)
+ : base()
+ {
+ _assembly = assembly;
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ return _assembly;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override String FullyQualifiedName
+ {
+ get
+ {
+ return "<Unknown>";
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ return this.Assembly.GetName().Name;
+ }
+ }
+
+ public sealed override bool Equals(Object o)
+ {
+ RuntimeModule other = o as RuntimeModule;
+ if (other == null)
+ return false;
+ return this._assembly.Equals(other._assembly);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _assembly.GetHashCode();
+ }
+
+ public sealed override Type GetType(String name, bool throwOnError, bool ignoreCase)
+ {
+ return _assembly.GetType(name, throwOnError, ignoreCase);
+ }
+
+ public sealed override String ToString()
+ {
+ return "<Unknown>";
+ }
+
+ private Assembly _assembly;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs
new file mode 100644
index 000000000..606a99f92
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ //
+ // This implements ParameterInfo objects owned by MethodBase objects that have an associated Parameter metadata entity.
+ //
+ internal sealed partial class RuntimeFatMethodParameterInfo : RuntimeMethodParameterInfo
+ {
+ private RuntimeFatMethodParameterInfo(MethodBase member, MethodHandle methodHandle, int position, ParameterHandle parameterHandle, ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeHandle, TypeContext typeContext)
+ : base(member, position, reflectionDomain, reader, typeHandle, typeContext)
+ {
+ _methodHandle = methodHandle;
+ _parameterHandle = parameterHandle;
+ _parameter = parameterHandle.GetParameter(reader);
+ }
+
+ public sealed override ParameterAttributes Attributes
+ {
+ get
+ {
+ return _parameter.Flags;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ IEnumerable<CustomAttributeData> customAttributes = RuntimeCustomAttributeData.GetCustomAttributes(reflectionDomain, this.Reader, _parameter.CustomAttributes);
+ foreach (CustomAttributeData cad in customAttributes)
+ yield return cad;
+ ExecutionDomain executionDomain = reflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ MethodHandle declaringMethodHandle = _methodHandle;
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(this.Reader, _parameterHandle, declaringMethodHandle))
+ yield return cad;
+ }
+ }
+ }
+
+ public sealed override Object DefaultValue
+ {
+ get
+ {
+ return DefaultValueInfo.Item2;
+ }
+ }
+
+ public sealed override bool HasDefaultValue
+ {
+ get
+ {
+ return DefaultValueInfo.Item1;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ return _parameter.Name.GetStringOrNull(this.Reader);
+ }
+ }
+
+ private Tuple<bool, Object> DefaultValueInfo
+ {
+ get
+ {
+ Tuple<bool, Object> defaultValueInfo = _lazyDefaultValueInfo;
+ if (defaultValueInfo == null)
+ {
+ if (!(this.ReflectionDomain is ExecutionDomain))
+ throw new NotSupportedException();
+
+ Object defaultValue;
+ bool hasDefaultValue = ReflectionCoreExecution.ExecutionEnvironment.GetDefaultValueIfAny(
+ this.Reader,
+ _parameterHandle,
+ this.ParameterType,
+ this.CustomAttributes,
+ out defaultValue);
+ if (!hasDefaultValue)
+ {
+ defaultValue = IsOptional ? Missing.Value : DBNull.Value;
+ }
+ defaultValueInfo = _lazyDefaultValueInfo = Tuple.Create(hasDefaultValue, defaultValue);
+ }
+ return defaultValueInfo;
+ }
+ }
+
+ private MethodHandle _methodHandle;
+ private ParameterHandle _parameterHandle;
+ private Parameter _parameter;
+ private volatile Tuple<bool, Object> _lazyDefaultValueInfo;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs
new file mode 100644
index 000000000..adaf12843
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ //
+ // Abstract base for all ParameterInfo objects exposed by runtime MethodBase objects
+ // (including the ReturnParameter.)
+ //
+ internal abstract class RuntimeMethodParameterInfo : RuntimeParameterInfo
+ {
+ protected RuntimeMethodParameterInfo(MethodBase member, int position, ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeHandle, TypeContext typeContext)
+ : base(member, position)
+ {
+ _reflectionDomain = reflectionDomain;
+ Reader = reader;
+ _typeHandle = typeHandle;
+ _typeContext = typeContext;
+ }
+
+ public sealed override Type ParameterType
+ {
+ get
+ {
+ return _reflectionDomain.Resolve(this.Reader, _typeHandle, _typeContext);
+ }
+ }
+
+ internal sealed override string ParameterTypeString
+ {
+ get
+ {
+ return _typeHandle.FormatTypeName(this.Reader, _typeContext, _reflectionDomain);
+ }
+ }
+
+ protected MetadataReader Reader { get; private set; }
+
+
+ private ReflectionDomain _reflectionDomain;
+ private Handle _typeHandle;
+ private TypeContext _typeContext;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs
new file mode 100644
index 000000000..2aa89dfec
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs
@@ -0,0 +1,94 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ //
+ // Abstract base for all ParameterInfo objects created by the Runtime.
+ //
+ internal abstract class RuntimeParameterInfo : ExtensibleParameterInfo
+ {
+ protected RuntimeParameterInfo(MemberInfo member, int position)
+ {
+ _member = member;
+ _position = position;
+ }
+
+ public abstract override ParameterAttributes Attributes { get; }
+ public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; }
+ public abstract override Object DefaultValue { get; }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeParameterInfo other = obj as RuntimeParameterInfo;
+ if (other == null)
+ return false;
+ if (this._position != other._position)
+ return false;
+ if (!(this._member.Equals(other._member)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _member.GetHashCode();
+ }
+
+ public abstract override bool HasDefaultValue { get; }
+
+ public sealed override MemberInfo Member
+ {
+ get
+ {
+ return _member;
+ }
+ }
+
+ public abstract override String Name { get; }
+ public abstract override Type ParameterType { get; }
+
+ public sealed override int Position
+ {
+ get
+ {
+ return _position;
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ return this.ParameterTypeString + " " + this.Name;
+ }
+
+ // Gets the ToString() output of ParameterType in a pay-to-play-safe way: Other Reflection ToString() methods should always use this rather than
+ // "ParameterType.ToString()".
+ internal abstract String ParameterTypeString { get; }
+
+ protected ReflectionDomain ReflectionDomain
+ {
+ get
+ {
+ return ReflectionCoreExecution.ExecutionDomain; //@TODO: User Reflection Domains not yet supported.
+ }
+ }
+
+ private MemberInfo _member;
+ private int _position;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs
new file mode 100644
index 000000000..e431daedd
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.PropertyInfos;
+
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ //
+ // This implements ParameterInfo objects returned by PropertyInfo.GetIndexParameters(). Basically, they're identical to the underling accessor method's
+ // ParameterInfo's except that the Member property returns the PropertyInfo rather than a MethodBase.
+ //
+ internal sealed partial class RuntimePropertyIndexParameterInfo : RuntimeParameterInfo
+ {
+ private RuntimePropertyIndexParameterInfo(RuntimePropertyInfo member, RuntimeParameterInfo backingParameter)
+ : base(member, backingParameter.Position)
+ {
+ _backingParameter = backingParameter;
+ }
+
+ public sealed override ParameterAttributes Attributes
+ {
+ get
+ {
+ return _backingParameter.Attributes;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return _backingParameter.CustomAttributes;
+ }
+ }
+
+ public sealed override Object DefaultValue
+ {
+ get
+ {
+ return _backingParameter.DefaultValue;
+ }
+ }
+
+ public sealed override bool HasDefaultValue
+ {
+ get
+ {
+ return _backingParameter.HasDefaultValue;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ return _backingParameter.Name;
+ }
+ }
+
+ public sealed override Type ParameterType
+ {
+ get
+ {
+ return _backingParameter.ParameterType;
+ }
+ }
+
+ internal sealed override String ParameterTypeString
+ {
+ get
+ {
+ return _backingParameter.ParameterTypeString;
+ }
+ }
+
+ private RuntimeParameterInfo _backingParameter;
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs
new file mode 100644
index 000000000..5e6f5d849
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ // This class is used for the "Get/Set" methods on array types.
+ internal sealed partial class RuntimeSyntheticParameterInfo : RuntimeParameterInfo
+ {
+ private RuntimeSyntheticParameterInfo(MemberInfo memberInfo, int position, RuntimeType parameterType)
+ : base(memberInfo, position)
+ {
+ _parameterType = parameterType;
+ }
+
+ public sealed override ParameterAttributes Attributes
+ {
+ get
+ {
+ return ParameterAttributes.None;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override Object DefaultValue
+ {
+ get
+ {
+ return null; // Legacy: This is what the desktop returns.
+ }
+ }
+
+ public sealed override bool HasDefaultValue
+ {
+ get
+ {
+ return false; // Legacy: Desktop strangely returns true but since we fixed this in Project N for other HasDefaultValues, we'll do so here as well.
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ return null; // Legacy: This is what the dekstop returns.
+ }
+ }
+
+ public sealed override Type ParameterType
+ {
+ get
+ {
+ return _parameterType;
+ }
+ }
+
+ internal sealed override String ParameterTypeString
+ {
+ get
+ {
+ return _parameterType.FormatTypeName();
+ }
+ }
+
+ private RuntimeType _parameterType;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs
new file mode 100644
index 000000000..8173715d5
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.ParameterInfos
+{
+ //
+ // This implements ParameterInfo objects owned by MethodBase objects that have no associated Parameter metadata. (In practice,
+ // this means return type "Parameters" that don't have custom attributes.
+ //
+ internal sealed partial class RuntimeThinMethodParameterInfo : RuntimeMethodParameterInfo
+ {
+ private RuntimeThinMethodParameterInfo(MethodBase member, int position, ReflectionDomain reflectionDomain, MetadataReader reader, Handle typeHandle, TypeContext typeContext)
+ : base(member, position, reflectionDomain, reader, typeHandle, typeContext)
+ {
+ }
+
+ public sealed override ParameterAttributes Attributes
+ {
+ get
+ {
+ return ParameterAttributes.None;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override Object DefaultValue
+ {
+ get
+ {
+ // Returning "null" matches the desktop behavior, though this is inconsistent with the DBNull/Missing values
+ // returned by non-return ParameterInfo's without default values.
+ return null;
+ }
+ }
+
+ public sealed override bool HasDefaultValue
+ {
+ get
+ {
+ // COMPAT: Desktop actually returns true here, but that behavior makes no sense.
+ return false;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ return null;
+ }
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs
new file mode 100644
index 000000000..f0b4ed7a6
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs
@@ -0,0 +1,380 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Text;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.ParameterInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.PropertyInfos
+{
+ //
+ // The runtime's implementation of PropertyInfo's
+ //
+ internal sealed partial class RuntimePropertyInfo : ExtensiblePropertyInfo, ITraceableTypeMember
+ {
+ //
+ // propertyHandle - the "tkPropertyDef" that identifies the property.
+ // definingType - the "tkTypeDef" that defined the field (this is where you get the metadata reader that created propertyHandle.)
+ // contextType - the type that supplies the type context (i.e. substitutions for generic parameters.) Though you
+ // get your raw information from "definingType", you report "contextType" as your DeclaringType property.
+ //
+ // For example:
+ //
+ // typeof(Foo<>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType and contextType are both Foo<>
+ //
+ // typeof(Foo<int,String>).GetTypeInfo().DeclaredMembers
+ //
+ // The definingType is "Foo<,>"
+ // The contextType is "Foo<int,String>"
+ //
+ // We don't report any DeclaredMembers for arrays or generic parameters so those don't apply.
+ //
+ private RuntimePropertyInfo(PropertyHandle propertyHandle, RuntimeNamedTypeInfo definingTypeInfo, RuntimeTypeInfo contextTypeInfo)
+ {
+ _propertyHandle = propertyHandle;
+ _definingTypeInfo = definingTypeInfo;
+ _contextTypeInfo = contextTypeInfo;
+ _reader = definingTypeInfo.Reader;
+ _property = propertyHandle.GetProperty(_reader);
+ }
+
+ public sealed override PropertyAttributes Attributes
+ {
+ get
+ {
+ return _property.Flags;
+ }
+ }
+
+ public sealed override bool CanRead
+ {
+ get
+ {
+ MethodHandle ignore;
+ return GetAccessor(MethodSemanticsAttributes.Getter, out ignore);
+ }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get
+ {
+ MethodHandle ignore;
+ return GetAccessor(MethodSemanticsAttributes.Setter, out ignore);
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_CustomAttributes(this);
+
+ foreach (CustomAttributeData cad in RuntimeCustomAttributeData.GetCustomAttributes(_definingTypeInfo.ReflectionDomain, _reader, _property.CustomAttributes))
+ yield return cad;
+ ExecutionDomain executionDomain = _definingTypeInfo.ReflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(_reader, _propertyHandle, _definingTypeInfo.TypeDefinitionHandle))
+ yield return cad;
+ }
+ }
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_DeclaringType(this);
+
+ return _contextTypeInfo.AsType();
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimePropertyInfo other = obj as RuntimePropertyInfo;
+ if (other == null)
+ return false;
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._propertyHandle.Equals(other._propertyHandle)))
+ return false;
+ if (!(this._contextTypeInfo.Equals(other._contextTypeInfo)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _propertyHandle.GetHashCode();
+ }
+
+ public sealed override Object GetConstantValue()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_GetConstantValue(this);
+
+ if (!(_definingTypeInfo.ReflectionDomain is ExecutionDomain))
+ throw new NotSupportedException(); // Cannot instantiate a boxed enum on a non-execution domain.
+
+ Object defaultValue;
+ if (!ReflectionCoreExecution.ExecutionEnvironment.GetDefaultValueIfAny(
+ _reader,
+ _propertyHandle,
+ this.PropertyType,
+ this.CustomAttributes,
+ out defaultValue))
+ {
+ throw new InvalidOperationException();
+ }
+ return defaultValue;
+ }
+
+ public sealed override ParameterInfo[] GetIndexParameters()
+ {
+ bool useGetter = CanRead;
+ RuntimeMethodInfo accessor = (useGetter ? Getter : Setter);
+ RuntimeParameterInfo[] runtimeMethodParameterInfos = accessor.GetRuntimeParametersAndReturn(accessor);
+ int count = runtimeMethodParameterInfos.Length - 1; // Subtract one for the return parameter.
+ if (!useGetter)
+ count--; // If we're taking the parameters off the setter, subtract one for the "value" parameter.
+ if (count == 0)
+ return Array.Empty<ParameterInfo>();
+ ParameterInfo[] result = new ParameterInfo[count];
+ for (int i = 0; i < count; i++)
+ result[i] = RuntimePropertyIndexParameterInfo.GetRuntimePropertyIndexParameterInfo(this, runtimeMethodParameterInfos[i + 1]);
+ return result;
+ }
+
+ public sealed override MethodInfo GetMethod
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_GetMethod(this);
+
+ return Getter;
+ }
+ }
+
+ public sealed override Object GetValue(Object obj, Object[] index)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_GetValue(this, obj, index);
+
+ if (_lazyGetterInvoker == null)
+ {
+ MethodHandle getterMethodHandle;
+ if (!GetAccessor(MethodSemanticsAttributes.Getter, out getterMethodHandle))
+ throw new ArgumentException();
+ MethodAttributes getterMethodAttributes = getterMethodHandle.GetMethod(_reader).Flags;
+ _lazyGetterInvoker = ReflectionCoreExecution.ExecutionEnvironment.GetMethodInvoker(_reader, _contextTypeInfo.RuntimeType, getterMethodHandle, Array.Empty<RuntimeType>(), this);
+ }
+ if (index == null)
+ index = Array.Empty<Object>();
+ return _lazyGetterInvoker.Invoke(obj, index);
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return _definingTypeInfo.Module;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_Name(this);
+
+ return _property.Name.GetString(_reader);
+ }
+ }
+
+ public sealed override Type PropertyType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_PropertyType(this);
+
+ TypeContext typeContext = _contextTypeInfo.TypeContext;
+ Handle typeHandle = _property.Signature.GetPropertySignature(_reader).Type;
+ return _contextTypeInfo.ReflectionDomain.Resolve(_reader, typeHandle, typeContext);
+ }
+ }
+
+ public sealed override MethodInfo SetMethod
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_SetMethod(this);
+
+ return Setter;
+ }
+ }
+
+ public sealed override void SetValue(Object obj, Object value, Object[] index)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.PropertyInfo_SetValue(this, obj, value, index);
+
+ if (_lazySetterInvoker == null)
+ {
+ MethodHandle setterMethodHandle;
+ if (!GetAccessor(MethodSemanticsAttributes.Setter, out setterMethodHandle))
+ throw new ArgumentException();
+ MethodAttributes setterMethodAttributes = setterMethodHandle.GetMethod(_reader).Flags;
+ _lazySetterInvoker = ReflectionCoreExecution.ExecutionEnvironment.GetMethodInvoker(_reader, _contextTypeInfo.RuntimeType, setterMethodHandle, Array.Empty<RuntimeType>(), this);
+ }
+ Object[] arguments;
+ if (index == null)
+ {
+ arguments = new Object[] { value };
+ }
+ else
+ {
+ arguments = new Object[index.Length + 1];
+ for (int i = 0; i < index.Length; i++)
+ {
+ arguments[i] = index[i];
+ }
+ arguments[index.Length] = value;
+ }
+ _lazySetterInvoker.Invoke(obj, arguments);
+ }
+
+ public sealed override String ToString()
+ {
+ StringBuilder sb = new StringBuilder(30);
+
+ ReflectionDomain reflectionDomain = _contextTypeInfo.ReflectionDomain;
+ TypeContext typeContext = _contextTypeInfo.TypeContext;
+ Handle typeHandle = _property.Signature.GetPropertySignature(_reader).Type;
+ sb.Append(typeHandle.FormatTypeName(_reader, typeContext, reflectionDomain));
+ sb.Append(' ');
+ sb.Append(this.Name);
+ ParameterInfo[] indexParameters = this.GetIndexParameters();
+ if (indexParameters.Length != 0)
+ {
+ RuntimeParameterInfo[] indexRuntimeParameters = new RuntimeParameterInfo[indexParameters.Length];
+ for (int i = 0; i < indexParameters.Length; i++)
+ indexRuntimeParameters[i] = (RuntimeParameterInfo)(indexParameters[i]);
+ sb.Append(" [");
+ sb.Append(RuntimeMethodCommon.ComputeParametersString(indexRuntimeParameters, 0));
+ sb.Append(']');
+ }
+
+ return sb.ToString();
+ }
+
+ String ITraceableTypeMember.MemberName
+ {
+ get
+ {
+ return _property.Name.GetString(_reader);
+ }
+ }
+
+ Type ITraceableTypeMember.ContainingType
+ {
+ get
+ {
+ return _contextTypeInfo.AsType();
+ }
+ }
+
+ private RuntimeMethodInfo Getter
+ {
+ get
+ {
+ MethodHandle getterHandle;
+ if (GetAccessor(MethodSemanticsAttributes.Getter, out getterHandle))
+ {
+ return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(getterHandle, _definingTypeInfo, _contextTypeInfo);
+ }
+ return null;
+ }
+ }
+
+ private RuntimeMethodInfo Setter
+ {
+ get
+ {
+ MethodHandle setterHandle;
+ if (GetAccessor(MethodSemanticsAttributes.Setter, out setterHandle))
+ {
+ return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(setterHandle, _definingTypeInfo, _contextTypeInfo);
+ }
+ return null;
+ }
+ }
+
+ private bool GetAccessor(MethodSemanticsAttributes methodSemanticsAttribute, out MethodHandle methodHandle)
+ {
+ foreach (MethodSemanticsHandle methodSemanticsHandle in _property.MethodSemantics)
+ {
+ MethodSemantics methodSemantics = methodSemanticsHandle.GetMethodSemantics(_reader);
+ if (methodSemantics.Attributes == methodSemanticsAttribute)
+ {
+ methodHandle = methodSemantics.Method;
+ return true;
+ }
+ }
+ methodHandle = default(MethodHandle);
+ return false;
+ }
+
+ private RuntimePropertyInfo WithDebugName()
+ {
+#if DEBUG
+ if (_debugName == null)
+ {
+ _debugName = "Constructing..."; // Protect against any inadvertent reentrancy.
+ _debugName = ((ITraceableTypeMember)this).MemberName;
+ }
+#endif
+ return this;
+ }
+
+ private RuntimeNamedTypeInfo _definingTypeInfo;
+ private PropertyHandle _propertyHandle;
+ private RuntimeTypeInfo _contextTypeInfo;
+
+ private MetadataReader _reader;
+ private Property _property;
+
+ private volatile MethodInvoker _lazyGetterInvoker = null;
+ private volatile MethodInvoker _lazySetterInvoker = null;
+
+#if DEBUG
+ private String _debugName;
+#endif
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Tracing/ReflectionEventSource.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Tracing/ReflectionEventSource.cs
new file mode 100644
index 000000000..f9400fde6
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Tracing/ReflectionEventSource.cs
@@ -0,0 +1,376 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Diagnostics.Tracing;
+
+namespace System.Reflection.Runtime.Tracing
+{
+ [EventSource(Guid = "55B578AE-32B0-48F8-822F-B3245E6FA59C", Name = "System.Reflection.Runtime.Tracing")]
+ internal sealed class ReflectionEventSource : EventSource
+ {
+ // Defines the singleton instance for the Resources ETW provider
+ public static readonly ReflectionEventSource Log = new ReflectionEventSource();
+
+ public static bool IsInitialized
+ {
+ get
+ {
+ return Log != null;
+ }
+ }
+
+ private ReflectionEventSource() { }
+
+
+ #region Reflection Event Handlers
+ [Event(1)]
+ public void TypeInfo_CustomAttributes(String typeName)
+ {
+ WriteEvent(1, typeName);
+ }
+
+ [Event(2)]
+ public void TypeInfo_Name(String typeName)
+ {
+ WriteEvent(2, typeName);
+ }
+
+ [Event(3)]
+ public void TypeInfo_BaseType(String typeName)
+ {
+ WriteEvent(3, typeName);
+ }
+
+ [Event(4)]
+ public void TypeInfo_DeclaredConstructors(String typeName)
+ {
+ WriteEvent(4, typeName);
+ }
+
+ [Event(5)]
+ public void TypeInfo_DeclaredEvents(String typeName)
+ {
+ WriteEvent(5, typeName);
+ }
+
+ [Event(6)]
+ public void TypeInfo_DeclaredFields(String typeName)
+ {
+ WriteEvent(6, typeName);
+ }
+
+ [Event(7)]
+ public void TypeInfo_DeclaredMembers(String typeName)
+ {
+ WriteEvent(7, typeName);
+ }
+
+ [Event(8)]
+ public void TypeInfo_DeclaredMethods(String typeName)
+ {
+ WriteEvent(8, typeName);
+ }
+
+ [Event(9)]
+ public void TypeInfo_DeclaredNestedTypes(String typeName)
+ {
+ WriteEvent(9, typeName);
+ }
+
+ [Event(10)]
+ public void TypeInfo_DeclaredProperties(String typeName)
+ {
+ WriteEvent(10, typeName);
+ }
+
+ [Event(11)]
+ public void TypeInfo_DeclaringMethod(String typeName)
+ {
+ WriteEvent(11, typeName);
+ }
+
+ [Event(12)]
+ public void TypeInfo_FullName(String typeName)
+ {
+ WriteEvent(12, typeName);
+ }
+
+ [Event(13)]
+ public void TypeInfo_Namespace(String typeName)
+ {
+ WriteEvent(13, typeName);
+ }
+
+ [Event(14)]
+ public void TypeInfo_GetDeclaredEvent(String typeName, String eventName)
+ {
+ WriteEvent(14, typeName, eventName);
+ }
+
+ [Event(15)]
+ public void TypeInfo_GetDeclaredField(String typeName, String fieldName)
+ {
+ WriteEvent(15, typeName, fieldName);
+ }
+
+ [Event(16)]
+ public void TypeInfo_GetDeclaredMethod(String typeName, String methodName)
+ {
+ WriteEvent(16, typeName, methodName);
+ }
+
+ [Event(17)]
+ public void TypeInfo_GetDeclaredProperty(String typeName, String propertyName)
+ {
+ WriteEvent(17, typeName, propertyName);
+ }
+
+ [Event(18)]
+ public void TypeInfo_MakeArrayType(String typeName)
+ {
+ WriteEvent(18, typeName);
+ }
+
+ [Event(19)]
+ public void TypeInfo_MakeByRefType(String typeName)
+ {
+ WriteEvent(19, typeName);
+ }
+
+ [Event(20)]
+ public void TypeInfo_MakeGenericType(String typeName, String typeArguments)
+ {
+ WriteEvent(20, typeName, typeArguments);
+ }
+
+ [Event(21)]
+ public void TypeInfo_MakePointerType(String typeName)
+ {
+ WriteEvent(21, typeName);
+ }
+
+ [Event(22)]
+ public void Assembly_DefinedTypes(String assemblyName)
+ {
+ WriteEvent(22, assemblyName);
+ }
+
+ [Event(23)]
+ public void Assembly_GetType(String assemblyName, String typeName)
+ {
+ WriteEvent(23, assemblyName, typeName);
+ }
+
+ [Event(24)]
+ public void Assembly_CustomAttributes(String assemblyName)
+ {
+ WriteEvent(24, assemblyName);
+ }
+
+ [Event(25)]
+ public void Assembly_FullName(String assemblyName)
+ {
+ WriteEvent(25, assemblyName);
+ }
+
+ [Event(26)]
+ public void Assembly_GetName(String assemblyName)
+ {
+ WriteEvent(26, assemblyName);
+ }
+
+ [Event(27)]
+ public void CustomAttributeData_ConstructorArguments(String caName)
+ {
+ WriteEvent(27, caName);
+ }
+
+ [Event(28)]
+ public void CustomAttributeData_NamedArguments(String caName)
+ {
+ WriteEvent(28, caName);
+ }
+
+ [Event(29)]
+ public void EventInfo_AddMethod(String typeName, String eventName)
+ {
+ WriteEvent(29, typeName, eventName);
+ }
+
+ [Event(30)]
+ public void EventInfo_RaiseMethod(String typeName, String eventName)
+ {
+ WriteEvent(30, typeName, eventName);
+ }
+
+ [Event(31)]
+ public void EventInfo_RemoveMethod(String typeName, String eventName)
+ {
+ WriteEvent(31, typeName, eventName);
+ }
+
+ [Event(32)]
+ public void EventInfo_CustomAttributes(String typeName, String eventName)
+ {
+ WriteEvent(32, typeName, eventName);
+ }
+
+ [Event(33)]
+ public void EventInfo_Name(String typeName, String eventName)
+ {
+ WriteEvent(33, typeName, eventName);
+ }
+
+ [Event(34)]
+ public void EventInfo_DeclaringType(String typeName, String eventName)
+ {
+ WriteEvent(34, typeName, eventName);
+ }
+
+ [Event(35)]
+ public void FieldInfo_SetValue(String typeName, String fieldName)
+ {
+ WriteEvent(35, typeName, fieldName);
+ }
+
+ [Event(36)]
+ public void FieldInfo_GetValue(String typeName, String fieldName)
+ {
+ WriteEvent(36, typeName, fieldName);
+ }
+
+ [Event(37)]
+ public void FieldInfo_CustomAttributes(String typeName, String fieldName)
+ {
+ WriteEvent(37, typeName, fieldName);
+ }
+
+ [Event(38)]
+ public void FieldInfo_Name(String typeName, String fieldName)
+ {
+ WriteEvent(38, typeName, fieldName);
+ }
+
+ [Event(39)]
+ public void FieldInfo_DeclaringType(String typeName, String fieldName)
+ {
+ WriteEvent(39, typeName, fieldName);
+ }
+
+ [Event(40)]
+ public void MethodBase_CustomAttributes(String typeName, String methodName)
+ {
+ WriteEvent(40, typeName, methodName);
+ }
+
+ [Event(41)]
+ public void MethodBase_Name(String typeName, String methodName)
+ {
+ WriteEvent(41, typeName, methodName);
+ }
+
+ [Event(42)]
+ public void MethodBase_DeclaringType(String typeName, String methodName)
+ {
+ WriteEvent(42, typeName, methodName);
+ }
+
+ [Event(43)]
+ public void MethodBase_GetParameters(String typeName, String methodName)
+ {
+ WriteEvent(43, typeName, methodName);
+ }
+
+ [Event(44)]
+ public void MethodBase_Invoke(String typeName, String methodName)
+ {
+ WriteEvent(44, typeName, methodName);
+ }
+
+ [Event(45)]
+ public void MethodInfo_ReturnParameter(String typeName, String methodName)
+ {
+ WriteEvent(45, typeName, methodName);
+ }
+
+ [Event(46)]
+ public void MethodInfo_ReturnType(String typeName, String methodName)
+ {
+ WriteEvent(46, typeName, methodName);
+ }
+
+ [Event(47)]
+ public void MethodInfo_MakeGenericMethod(String typeName, String methodName, String typeArguments)
+ {
+ WriteEvent(47, typeName, methodName, typeArguments);
+ }
+
+ [Event(48)]
+ public void MethodInfo_CreateDelegate(String typeName, String methodName, String delegateTypeName)
+ {
+ WriteEvent(48, typeName, methodName, delegateTypeName);
+ }
+
+ [Event(49)]
+ public void PropertyInfo_GetValue(String typeName, String propertyName)
+ {
+ WriteEvent(49, typeName, propertyName);
+ }
+
+ [Event(50)]
+ public void PropertyInfo_SetValue(String typeName, String propertyName)
+ {
+ WriteEvent(50, typeName, propertyName);
+ }
+
+ [Event(51)]
+ public void PropertyInfo_GetMethod(String typeName, String propertyName)
+ {
+ WriteEvent(51, typeName, propertyName);
+ }
+
+ [Event(52)]
+ public void PropertyInfo_SetMethod(String typeName, String propertyName)
+ {
+ WriteEvent(52, typeName, propertyName);
+ }
+
+ [Event(53)]
+ public void PropertyInfo_GetConstantValue(String typeName, String propertyName)
+ {
+ WriteEvent(53, typeName, propertyName);
+ }
+
+ [Event(54)]
+ public void PropertyInfo_PropertyType(String typeName, String propertyName)
+ {
+ WriteEvent(54, typeName, propertyName);
+ }
+
+ [Event(55)]
+ public void PropertyInfo_CustomAttributes(String typeName, String propertyName)
+ {
+ WriteEvent(55, typeName, propertyName);
+ }
+
+ [Event(56)]
+ public void PropertyInfo_Name(String typeName, String propertyName)
+ {
+ WriteEvent(56, typeName, propertyName);
+ }
+
+ [Event(57)]
+ public void PropertyInfo_DeclaringType(String typeName, String propertyName)
+ {
+ WriteEvent(57, typeName, propertyName);
+ }
+
+ [Event(58)]
+ public void TypeInfo_AssemblyQualifiedName(String typeName)
+ {
+ WriteEvent(58, typeName);
+ }
+ #endregion
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs
new file mode 100644
index 000000000..f132021d7
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs
@@ -0,0 +1,317 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.MethodInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+using TargetException = System.ArgumentException;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // The runtime's implementation of TypeInfo's for array types.
+ //
+
+ internal sealed partial class RuntimeArrayTypeInfo : RuntimeHasElementTypeInfo
+ {
+ private RuntimeArrayTypeInfo(RuntimeType hasElementType)
+ : base(hasElementType)
+ {
+ Debug.Assert(hasElementType.IsArray);
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get
+ {
+ return TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable;
+ }
+ }
+
+ internal sealed override IEnumerable<RuntimeConstructorInfo> SyntheticConstructors
+ {
+ get
+ {
+ bool multiDim = this.RuntimeType.InternalIsMultiDimArray;
+ int rank = this.RuntimeType.GetArrayRank();
+
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ FoundationTypes foundationTypes = reflectionDomain.FoundationTypes;
+ RuntimeType arrayType = this.RuntimeType;
+ RuntimeType countType = foundationTypes.SystemInt32.AsConfirmedRuntimeType();
+ RuntimeType voidType = foundationTypes.SystemVoid.AsConfirmedRuntimeType();
+
+ {
+ RuntimeType[] ctorParametersAndReturn = new RuntimeType[rank + 1];
+ ctorParametersAndReturn[0] = voidType;
+ for (int i = 0; i < rank; i++)
+ ctorParametersAndReturn[i + 1] = countType;
+ yield return RuntimeSyntheticConstructorInfo.GetRuntimeSyntheticConstructorInfo(
+ SyntheticMethodId.ArrayCtor,
+ arrayType,
+ ctorParametersAndReturn,
+ InvokerOptions.AllowNullThis | InvokerOptions.DontWrapException,
+ delegate (Object _this, Object[] args)
+ {
+ if (rank == 1)
+ {
+ // Legacy: This seems really wrong in the rank1-multidim case (as it's a case of a synthetic constructor that's declared on T[*] returning an instance of T[])
+ // This is how the desktop behaves, however.
+
+ int count = (int)(args[0]);
+
+ RuntimeType vectorType;
+ if (multiDim)
+ {
+ vectorType = ReflectionCoreNonPortable.GetArrayType(arrayType.InternalRuntimeElementType);
+ }
+ else
+ {
+ vectorType = arrayType;
+ }
+
+ return ReflectionCoreExecution.ExecutionEnvironment.NewArray(vectorType.TypeHandle, count);
+ }
+ else
+ {
+ int[] lengths = new int[rank];
+ for (int i = 0; i < rank; i++)
+ {
+ lengths[i] = (int)(args[i]);
+ }
+ return ReflectionCoreExecution.ExecutionEnvironment.NewMultiDimArray(arrayType.TypeHandle, lengths, null);
+ }
+ }
+ );
+ }
+
+ if (!multiDim)
+ {
+ //
+ // Jagged arrays also expose constructors that take multiple indices and construct a jagged matrix. For example,
+ //
+ // String[][][][]
+ //
+ // also exposes:
+ //
+ // .ctor(int32, int32)
+ // .ctor(int32, int32, int32)
+ // .ctor(int32, int32, int32, int32)
+ //
+
+ int parameterCount = 2;
+ RuntimeType elementType = this.RuntimeType.InternalRuntimeElementType;
+ while (elementType.IsArray && elementType.GetArrayRank() == 1)
+ {
+ RuntimeType[] ctorParametersAndReturn = new RuntimeType[parameterCount + 1];
+ ctorParametersAndReturn[0] = voidType;
+ for (int i = 0; i < parameterCount; i++)
+ ctorParametersAndReturn[i + 1] = countType;
+ yield return RuntimeSyntheticConstructorInfo.GetRuntimeSyntheticConstructorInfo(
+ SyntheticMethodId.ArrayCtorJagged + parameterCount,
+ arrayType,
+ ctorParametersAndReturn,
+ InvokerOptions.AllowNullThis | InvokerOptions.DontWrapException,
+ delegate (Object _this, Object[] args)
+ {
+ int[] lengths = new int[args.Length];
+ for (int i = 0; i < args.Length; i++)
+ {
+ lengths[i] = (int)(args[i]);
+ }
+ Array jaggedArray = CreateJaggedArray(arrayType, lengths, 0);
+ return jaggedArray;
+ }
+ );
+ parameterCount++;
+ elementType = elementType.InternalRuntimeElementType;
+ }
+ }
+
+ if (multiDim)
+ {
+ RuntimeType[] ctorParametersAndReturn = new RuntimeType[rank * 2 + 1];
+ ctorParametersAndReturn[0] = voidType;
+ for (int i = 0; i < rank * 2; i++)
+ ctorParametersAndReturn[i + 1] = countType;
+ yield return RuntimeSyntheticConstructorInfo.GetRuntimeSyntheticConstructorInfo(
+ SyntheticMethodId.ArrayMultiDimCtor,
+ arrayType,
+ ctorParametersAndReturn,
+ InvokerOptions.AllowNullThis | InvokerOptions.DontWrapException,
+ delegate (Object _this, Object[] args)
+ {
+ int[] lengths = new int[rank];
+ int[] lowerBounds = new int[rank];
+ for (int i = 0; i < rank; i++)
+ {
+ lowerBounds[i] = (int)(args[i * 2]);
+ lengths[i] = (int)(args[i * 2 + 1]);
+ }
+ return ReflectionCoreExecution.ExecutionEnvironment.NewMultiDimArray(arrayType.TypeHandle, lengths, lowerBounds);
+ }
+ );
+ }
+ }
+ }
+
+ internal sealed override IEnumerable<RuntimeMethodInfo> SyntheticMethods
+ {
+ get
+ {
+ int rank = this.RuntimeType.GetArrayRank();
+
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ FoundationTypes foundationTypes = reflectionDomain.FoundationTypes;
+ RuntimeType indexType = foundationTypes.SystemInt32.AsConfirmedRuntimeType();
+ RuntimeType arrayType = this.RuntimeType;
+ RuntimeType elementType = arrayType.InternalRuntimeElementType;
+ RuntimeType voidType = foundationTypes.SystemVoid.AsConfirmedRuntimeType();
+
+ {
+ RuntimeType[] getParametersAndReturn = new RuntimeType[rank + 1];
+ getParametersAndReturn[0] = elementType;
+ for (int i = 0; i < rank; i++)
+ getParametersAndReturn[i + 1] = indexType;
+ yield return RuntimeSyntheticMethodInfo.GetRuntimeSyntheticMethodInfo(
+ SyntheticMethodId.ArrayGet,
+ "Get",
+ arrayType,
+ getParametersAndReturn,
+ InvokerOptions.None,
+ delegate (Object _this, Object[] args)
+ {
+ Array array = (Array)_this;
+ int[] indices = new int[rank];
+ for (int i = 0; i < rank; i++)
+ indices[i] = (int)(args[i]);
+ return array.GetValue(indices);
+ }
+ );
+ }
+
+ {
+ RuntimeType[] setParametersAndReturn = new RuntimeType[rank + 2];
+ setParametersAndReturn[0] = voidType;
+ for (int i = 0; i < rank; i++)
+ setParametersAndReturn[i + 1] = indexType;
+ setParametersAndReturn[rank + 1] = elementType;
+ yield return RuntimeSyntheticMethodInfo.GetRuntimeSyntheticMethodInfo(
+ SyntheticMethodId.ArraySet,
+ "Set",
+ arrayType,
+ setParametersAndReturn,
+ InvokerOptions.None,
+ delegate (Object _this, Object[] args)
+ {
+ Array array = (Array)_this;
+ int[] indices = new int[rank];
+ for (int i = 0; i < rank; i++)
+ indices[i] = (int)(args[i]);
+ Object value = args[rank];
+ array.SetValue(value, indices);
+ return null;
+ }
+ );
+ }
+
+ {
+ RuntimeType[] addressParametersAndReturn = new RuntimeType[rank + 1];
+ addressParametersAndReturn[0] = ReflectionCoreNonPortable.GetByRefType(elementType);
+ for (int i = 0; i < rank; i++)
+ addressParametersAndReturn[i + 1] = indexType;
+ yield return RuntimeSyntheticMethodInfo.GetRuntimeSyntheticMethodInfo(
+ SyntheticMethodId.ArrayAddress,
+ "Address",
+ arrayType,
+ addressParametersAndReturn,
+ InvokerOptions.None,
+ delegate (Object _this, Object[] args)
+ {
+ throw new NotSupportedException();
+ }
+ );
+ }
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ return TypeDefInfoProjectionForArrays.TypeRefDefOrSpecForBaseType;
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ if (this.RuntimeType.InternalIsMultiDimArray)
+ return Array.Empty<QTypeDefRefOrSpec>();
+ else
+ return TypeDefInfoProjectionForArrays.TypeRefDefOrSpecsForDirectlyImplementedInterfaces;
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ return new TypeContext(new RuntimeType[] { this.RuntimeType.InternalRuntimeElementType }, null);
+ }
+ }
+
+ //
+ // Arrays don't have a true typedef behind them but for the purpose of reporting base classes and interfaces, we can create a pretender.
+ //
+ private RuntimeNamedTypeInfo TypeDefInfoProjectionForArrays
+ {
+ get
+ {
+ Debug.Assert(this.ReflectionDomain == ReflectionCoreExecution.ExecutionDomain, "User Reflectable Domains not yet implemented.");
+ RuntimeTypeHandle projectionTypeHandleForArrays = ReflectionCoreExecution.ExecutionEnvironment.ProjectionTypeForArrays;
+ RuntimeType projectionRuntimeTypeForArrays = ReflectionCoreNonPortable.GetTypeForRuntimeTypeHandle(projectionTypeHandleForArrays);
+ return projectionRuntimeTypeForArrays.GetRuntimeTypeInfo<RuntimeNamedTypeInfo>();
+ }
+ }
+
+ //
+ // Helper for jagged array constructors.
+ //
+ private Array CreateJaggedArray(RuntimeType arrayType, int[] lengths, int index)
+ {
+ int length = lengths[index];
+ Array jaggedArray = ReflectionCoreExecution.ExecutionEnvironment.NewArray(arrayType.TypeHandle, length);
+ if (index != lengths.Length - 1)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ Array subArray = CreateJaggedArray(arrayType.InternalRuntimeElementType, lengths, index + 1);
+ jaggedArray.SetValue(subArray, i);
+ }
+ }
+ return jaggedArray;
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs
new file mode 100644
index 000000000..169a88e8d
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs
@@ -0,0 +1,187 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // TypeInfos that represent type definitions (i.e. Foo or Foo<>) or constructed generic types (Foo<int>)
+ // that can never be reflection-enabled due to the framework Reflection block.
+ //
+ // These types differ from NoMetadata TypeInfos in that properties that inquire about members,
+ // custom attributes or interfaces return an empty list rather than throwing a MissingMetadataException.
+ //
+ // Since these represent "internal framework types", the app cannot prove we are lying.
+ //
+ internal sealed partial class RuntimeBlockedTypeInfo : RuntimeTypeInfo
+ {
+ private RuntimeBlockedTypeInfo(RuntimeType runtimeType)
+ {
+ _asType = runtimeType;
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ return typeof(Object).GetTypeInfo().Assembly;
+ }
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get
+ {
+ return TypeAttributes.Class | TypeAttributes.NotPublic;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override IEnumerable<TypeInfo> DeclaredNestedTypes
+ {
+ get
+ {
+ return Empty<TypeInfo>.Enumerable;
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ if (Object.ReferenceEquals(this, obj))
+ return true;
+
+ RuntimeBlockedTypeInfo other = obj as RuntimeBlockedTypeInfo;
+ if (other == null)
+ return false;
+ if (!(this._asType.Equals(other._asType)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _asType.GetHashCode();
+ }
+
+ public sealed override Guid GUID
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ public sealed override bool IsGenericType
+ {
+ get
+ {
+ return _asType.IsConstructedGenericType || this.IsGenericTypeDefinition;
+ }
+ }
+
+ public sealed override bool IsGenericTypeDefinition
+ {
+ get
+ {
+ return _asType.InternalIsGenericTypeDefinition;
+ }
+ }
+
+ //
+ // Returns the anchoring typedef that declares the members that this type wants returned by the Declared*** properties.
+ // The Declared*** properties will project the anchoring typedef's members by overriding their DeclaringType property with "this"
+ // and substituting the value of this.TypeContext into any generic parameters.
+ //
+ // Default implementation returns null which causes the Declared*** properties to return no members.
+ //
+ // Note that this does not apply to DeclaredNestedTypes. Nested types and their containers have completely separate generic instantiation environments
+ // (despite what C# might lead you to think.) Constructed generic types return the exact same same nested types that its generic type definition does
+ // - i.e. their DeclaringTypes refer back to the generic type definition, not the constructed generic type.)
+ //
+ // Note also that we cannot use this anchoring concept for base types because of generic parameters. Generic parameters return
+ // baseclass and interfaces based on its constraints.
+ //
+ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers
+ {
+ get
+ {
+ return null; // this causes the type to report having no members.
+ }
+ }
+
+ internal sealed override RuntimeType[] RuntimeGenericTypeParameters
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeType
+ {
+ get
+ {
+ return _asType;
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ private RuntimeType _asType;
+ }
+}
+
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs
new file mode 100644
index 000000000..a0df40576
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs
@@ -0,0 +1,172 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core.NonPortable;
+using Internal.Reflection.Tracing;
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // TypeInfos that represent constructed generic types.
+ //
+ //
+ internal sealed partial class RuntimeConstructedGenericTypeInfo : RuntimeTypeInfo
+ {
+ private RuntimeConstructedGenericTypeInfo(RuntimeType genericConstructedGenericType)
+ : base()
+ {
+ Debug.Assert(genericConstructedGenericType.IsConstructedGenericType);
+ _asType = genericConstructedGenericType;
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_CustomAttributes(this);
+
+ return GenericTypeDefinitionTypeInfo.CustomAttributes;
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeConstructedGenericTypeInfo other = obj as RuntimeConstructedGenericTypeInfo;
+ if (other == null)
+ return false;
+ return _asType.Equals(other._asType);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _asType.GetHashCode();
+ }
+
+ public sealed override Guid GUID
+ {
+ get
+ {
+ return GenericTypeDefinitionTypeInfo.GUID;
+ }
+ }
+
+ public sealed override bool IsGenericType
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ return GenericTypeDefinitionTypeInfo.Assembly;
+ }
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get
+ {
+ return GenericTypeDefinitionTypeInfo.Attributes;
+ }
+ }
+
+ public sealed override IEnumerable<TypeInfo> DeclaredNestedTypes
+ {
+ get
+ {
+ return GenericTypeDefinitionTypeInfo.DeclaredNestedTypes;
+ }
+ }
+
+ //
+ // Returns the anchoring typedef that declares the members that this type wants returned by the Declared*** properties.
+ // The Declared*** properties will project the anchoring typedef's members by overriding their DeclaringType property with "this"
+ // and substituting the value of this.TypeContext into any generic parameters.
+ //
+ // Default implementation returns null which causes the Declared*** properties to return no members.
+ //
+ // Note that this does not apply to DeclaredNestedTypes. Nested types and their containers have completely separate generic instantiation environments
+ // (despite what C# might lead you to think.) Constructed generic types return the exact same same nested types that its generic type definition does
+ // - i.e. their DeclaringTypes refer back to the generic type definition, not the constructed generic type.)
+ //
+ // Note also that we cannot use this anchoring concept for base types because of generic parameters. Generic parameters return
+ // baseclass and interfaces based on its constraints.
+ //
+ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers
+ {
+ get
+ {
+ RuntimeTypeInfo genericTypeDefinition = this.GenericTypeDefinitionTypeInfo;
+ RuntimeNamedTypeInfo genericTypeDefinitionNamedTypeInfo = genericTypeDefinition as RuntimeNamedTypeInfo;
+ if (genericTypeDefinitionNamedTypeInfo == null)
+ throw this.ReflectionDomain.CreateMissingMetadataException(genericTypeDefinition);
+ return genericTypeDefinitionNamedTypeInfo;
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeType
+ {
+ get
+ {
+ return _asType;
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ return this.GenericTypeDefinitionTypeInfo.TypeRefDefOrSpecForBaseType;
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ return this.GenericTypeDefinitionTypeInfo.TypeRefDefOrSpecsForDirectlyImplementedInterfaces;
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ return new TypeContext(this.RuntimeType.InternalRuntimeGenericTypeArguments, null);
+ }
+ }
+
+ private RuntimeTypeInfo GenericTypeDefinitionTypeInfo
+ {
+ get
+ {
+ return GetGenericTypeDefinition().GetRuntimeTypeInfo<RuntimeTypeInfo>();
+ }
+ }
+
+ private RuntimeType _asType;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs
new file mode 100644
index 000000000..37d14337c
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs
@@ -0,0 +1,193 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.MethodInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ internal sealed partial class RuntimeGenericParameterTypeInfo : RuntimeTypeInfo
+ {
+ private RuntimeGenericParameterTypeInfo(RuntimeGenericParameterType asType)
+ {
+ _asType = asType;
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ return DeclaringType.GetTypeInfo().Assembly;
+ }
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get
+ {
+ return TypeAttributes.Public;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_CustomAttributes(this);
+
+ return _asType.CustomAttributes;
+ }
+ }
+
+ public sealed override MethodBase DeclaringMethod
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaringMethod(this);
+
+ return _asType.DeclaringMethod;
+ }
+ }
+
+ public sealed override GenericParameterAttributes GenericParameterAttributes
+ {
+ get
+ {
+ return _asType.GenericParameterAttributes;
+ }
+ }
+
+ public sealed override Type[] GetGenericParameterConstraints()
+ {
+ TypeInfo[] constraintInfos = ConstraintInfos;
+ if (constraintInfos.Length == 0)
+ return Array.Empty<Type>();
+ Type[] result = new Type[constraintInfos.Length];
+ for (int i = 0; i < constraintInfos.Length; i++)
+ result[i] = constraintInfos[i].AsType();
+ return result;
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeGenericParameterTypeInfo other = obj as RuntimeGenericParameterTypeInfo;
+ if (other == null)
+ return false;
+ return this._asType.Equals(other._asType);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _asType.GetHashCode();
+ }
+
+ internal sealed override RuntimeType RuntimeType
+ {
+ get
+ {
+ return _asType;
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ QTypeDefRefOrSpec[] constraints = Constraints;
+ TypeInfo[] constraintInfos = ConstraintInfos;
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ TypeInfo constraintInfo = constraintInfos[i];
+ if (constraintInfo.IsInterface)
+ continue;
+ return constraints[i];
+ }
+
+ RuntimeNamedTypeInfo objectTypeInfo = this.ReflectionDomain.FoundationTypes.SystemObject.GetRuntimeTypeInfo<RuntimeNamedTypeInfo>();
+ return new QTypeDefRefOrSpec(objectTypeInfo.Reader, objectTypeInfo.TypeDefinitionHandle);
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ LowLevelList<QTypeDefRefOrSpec> result = new LowLevelList<QTypeDefRefOrSpec>();
+ QTypeDefRefOrSpec[] constraints = Constraints;
+ TypeInfo[] constraintInfos = ConstraintInfos;
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ if (constraintInfos[i].IsInterface)
+ result.Add(constraints[i]);
+ }
+ return result.ToArray();
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ return _asType.TypeContext;
+ }
+ }
+
+ private QTypeDefRefOrSpec[] Constraints
+ {
+ get
+ {
+ MetadataReader reader = _asType.Reader;
+ LowLevelList<QTypeDefRefOrSpec> constraints = new LowLevelList<QTypeDefRefOrSpec>();
+ foreach (Handle constraintHandle in _asType.GenericParameterHandle.GetGenericParameter(_asType.Reader).Constraints)
+ {
+ constraints.Add(new QTypeDefRefOrSpec(reader, constraintHandle));
+ }
+ return constraints.ToArray();
+ }
+ }
+
+ private TypeInfo[] ConstraintInfos
+ {
+ get
+ {
+ QTypeDefRefOrSpec[] constraints = Constraints;
+ if (constraints.Length == 0)
+ return Array.Empty<TypeInfo>();
+ TypeInfo[] constraintInfos = new TypeInfo[constraints.Length];
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ constraintInfos[i] = reflectionDomain.Resolve(constraints[i].Reader, constraints[i].Handle, TypeContext).GetTypeInfo();
+ }
+ return constraintInfos;
+ }
+ }
+
+ private RuntimeGenericParameterType _asType;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs
new file mode 100644
index 000000000..102d49008
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // The runtime's implementation of TypeInfo's for the "HasElement" subclass of types.
+ //
+ // For now, only Array has its own base class below this - that's the only with that implements anything differently.
+ //
+ internal partial class RuntimeHasElementTypeInfo : RuntimeTypeInfo
+ {
+ protected RuntimeHasElementTypeInfo(RuntimeType hasElementType)
+ : base()
+ {
+ Debug.Assert(hasElementType.HasElementType);
+ _asType = hasElementType;
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ RuntimeHasElementTypeInfo other = obj as RuntimeHasElementTypeInfo;
+ if (other == null)
+ return false;
+ return _asType.Equals(other._asType);
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _asType.GetHashCode();
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ return ElementTypeInfo.Assembly;
+ }
+ }
+
+ //
+ // Left unsealed because this implemention is correct for ByRefs and Pointers but not Arrays.
+ //
+ public override TypeAttributes Attributes
+ {
+ get
+ {
+ Debug.Assert(IsByRef || IsPointer);
+ return TypeAttributes.AnsiClass;
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeType
+ {
+ get
+ {
+ return _asType;
+ }
+ }
+
+ private RuntimeType _asType;
+
+ private RuntimeTypeInfo ElementTypeInfo
+ {
+ get
+ {
+ if (_elementTypeInfo == null)
+ {
+ _elementTypeInfo = _asType.InternalRuntimeElementType.GetRuntimeTypeInfo();
+ }
+ return _elementTypeInfo;
+ }
+ }
+
+ private volatile RuntimeTypeInfo _elementTypeInfo;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs
new file mode 100644
index 000000000..db5caad62
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs
@@ -0,0 +1,364 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Collections.Concurrent;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // TypeInfos that represent type definitions (i.e. Foo or Foo<>, but not Foo<int> or arrays/pointers/byrefs.)
+ //
+ //
+ internal sealed partial class RuntimeNamedTypeInfo : RuntimeTypeInfo, IEquatable<RuntimeNamedTypeInfo>
+ {
+ private RuntimeNamedTypeInfo(MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle)
+ {
+ _reader = reader;
+ _typeDefinitionHandle = typeDefinitionHandle;
+ _typeDefinition = _typeDefinitionHandle.GetTypeDefinition(reader);
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ // If an assembly is split across multiple metadata blobs then the defining scope may
+ // not be the canonical scope representing the assembly. We need to look up the assembly
+ // by name to ensure we get the right one.
+
+ ScopeDefinitionHandle scopeDefinitionHandle = NamespaceChain.DefiningScope;
+ RuntimeAssemblyName runtimeAssemblyName = scopeDefinitionHandle.ToRuntimeAssemblyName(_reader);
+
+ return RuntimeAssembly.GetRuntimeAssembly(this.ReflectionDomain, runtimeAssemblyName);
+ }
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get
+ {
+ TypeAttributes attr = _typeDefinition.Flags;
+ return attr;
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_CustomAttributes(this);
+
+ IEnumerable<CustomAttributeData> customAttributes = RuntimeCustomAttributeData.GetCustomAttributes(this.ReflectionDomain, _reader, _typeDefinition.CustomAttributes);
+ foreach (CustomAttributeData cad in customAttributes)
+ yield return cad;
+ ExecutionDomain executionDomain = this.ReflectionDomain as ExecutionDomain;
+ if (executionDomain != null)
+ {
+ foreach (CustomAttributeData cad in executionDomain.ExecutionEnvironment.GetPsuedoCustomAttributes(_reader, _typeDefinitionHandle))
+ {
+ yield return cad;
+ }
+ }
+ }
+ }
+
+ public sealed override IEnumerable<TypeInfo> DeclaredNestedTypes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredNestedTypes(this);
+
+ foreach (TypeDefinitionHandle nestedTypeHandle in _typeDefinition.NestedTypes)
+ {
+ yield return RuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(_reader, nestedTypeHandle);
+ }
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ if (Object.ReferenceEquals(this, obj))
+ return true;
+
+ RuntimeNamedTypeInfo other = obj as RuntimeNamedTypeInfo;
+ if (!Equals(other))
+ return false;
+ return true;
+ }
+
+ public bool Equals(RuntimeNamedTypeInfo other)
+ {
+ if (other == null)
+ return false;
+ if (this._reader != other._reader)
+ return false;
+ if (!(this._typeDefinitionHandle.Equals(other._typeDefinitionHandle)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _typeDefinitionHandle.GetHashCode();
+ }
+
+ public sealed override Guid GUID
+ {
+ get
+ {
+ //
+ // Look for a [Guid] attribute. If found, return that.
+ //
+ foreach (CustomAttributeHandle cah in _typeDefinition.CustomAttributes)
+ {
+ // We can't reference the GuidAttribute class directly as we don't have an official dependency on System.Runtime.InteropServices.
+ // Following age-old CLR tradition, we search for the custom attribute using a name-based search. Since this makes it harder
+ // to be sure we won't run into custom attribute constructors that comply with the GuidAttribute(String) signature,
+ // we'll check that it does and silently skip the CA if it doesn't match the expected pattern.
+ if (cah.IsCustomAttributeOfType(_reader, "System.Runtime.InteropServices", "GuidAttribute"))
+ {
+ CustomAttribute ca = cah.GetCustomAttribute(_reader);
+ IEnumerator<FixedArgumentHandle> fahEnumerator = ca.FixedArguments.GetEnumerator();
+ if (!fahEnumerator.MoveNext())
+ continue;
+ FixedArgumentHandle guidStringArgumentHandle = fahEnumerator.Current;
+ if (fahEnumerator.MoveNext())
+ continue;
+ FixedArgument guidStringArgument = guidStringArgumentHandle.GetFixedArgument(_reader);
+ String guidString = guidStringArgument.Value.ParseConstantValue(this.ReflectionDomain, _reader) as String;
+ if (guidString == null)
+ continue;
+ return new Guid(guidString);
+ }
+ }
+
+ //
+ // If we got here, there was no [Guid] attribute.
+ //
+ // Ideally, we'd now compute the same GUID the desktop returns - however, that algorithm is complex and has questionable dependencies
+ // (in particular, the GUID changes if the language compilers ever change the way it emits metadata tokens into certain unordered lists.
+ // We don't even retain that order across the Project N toolchain.)
+ //
+ // For now, this is a compromise that satisfies our app-compat goals. We ensure that each unique Type receives a different GUID (at least one app
+ // uses the GUID as a dictionary key to look up types.) It will not be the same GUID on multiple runs of the app but so far, there's
+ // no evidence that's needed.
+ //
+ return _namedTypeToGuidTable.GetOrAdd(this).Item1;
+ }
+ }
+
+ public sealed override bool IsGenericTypeDefinition
+ {
+ get
+ {
+ return _typeDefinition.GenericParameters.GetEnumerator().MoveNext();
+ }
+ }
+
+ public sealed override bool IsGenericType
+ {
+ get
+ {
+ return _typeDefinition.GenericParameters.GetEnumerator().MoveNext();
+ }
+ }
+
+ //
+ // Returns the anchoring typedef that declares the members that this type wants returned by the Declared*** properties.
+ // The Declared*** properties will project the anchoring typedef's members by overriding their DeclaringType property with "this"
+ // and substituting the value of this.TypeContext into any generic parameters.
+ //
+ // Default implementation returns null which causes the Declared*** properties to return no members.
+ //
+ // Note that this does not apply to DeclaredNestedTypes. Nested types and their containers have completely separate generic instantiation environments
+ // (despite what C# might lead you to think.) Constructed generic types return the exact same same nested types that its generic type definition does
+ // - i.e. their DeclaringTypes refer back to the generic type definition, not the constructed generic type.)
+ //
+ // Note also that we cannot use this anchoring concept for base types because of generic parameters. Generic parameters return
+ // baseclass and interfaces based on its constraints.
+ //
+ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers
+ {
+ get
+ {
+ return this;
+ }
+ }
+
+ internal sealed override RuntimeType[] RuntimeGenericTypeParameters
+ {
+ get
+ {
+ LowLevelList<RuntimeType> genericTypeParameters = new LowLevelList<RuntimeType>();
+
+ foreach (GenericParameterHandle genericParameterHandle in _typeDefinition.GenericParameters)
+ {
+ RuntimeType genericParameterType = RuntimeTypeUnifierEx.GetRuntimeGenericParameterTypeForTypes(this, genericParameterHandle);
+ genericTypeParameters.Add(genericParameterType);
+ }
+
+ return genericTypeParameters.ToArray();
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeType
+ {
+ get
+ {
+ if (_lazyType == null)
+ {
+ _lazyType = this.ReflectionDomain.ResolveTypeDefinition(_reader, _typeDefinitionHandle);
+ }
+ return _lazyType;
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ Handle baseType = _typeDefinition.BaseType;
+ if (baseType.IsNull(_reader))
+ return QTypeDefRefOrSpec.Null;
+ return new QTypeDefRefOrSpec(_reader, baseType);
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ LowLevelList<QTypeDefRefOrSpec> directlyImplementedInterfaces = new LowLevelList<QTypeDefRefOrSpec>();
+ foreach (Handle ifcHandle in _typeDefinition.Interfaces)
+ directlyImplementedInterfaces.Add(new QTypeDefRefOrSpec(_reader, ifcHandle));
+ return directlyImplementedInterfaces.ToArray();
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ return new TypeContext(this.RuntimeGenericTypeParameters, null);
+ }
+ }
+
+ internal MetadataReader Reader
+ {
+ get
+ {
+ return _reader;
+ }
+ }
+
+ internal TypeDefinitionHandle TypeDefinitionHandle
+ {
+ get
+ {
+ return _typeDefinitionHandle;
+ }
+ }
+
+ internal IEnumerable<MethodHandle> DeclaredConstructorHandles
+ {
+ get
+ {
+ foreach (MethodHandle methodHandle in _typeDefinition.Methods)
+ {
+ if (methodHandle.IsConstructor(_reader))
+ yield return methodHandle;
+ }
+ }
+ }
+
+ internal IEnumerable<EventHandle> DeclaredEventHandles
+ {
+ get
+ {
+ return _typeDefinition.Events;
+ }
+ }
+
+ internal IEnumerable<FieldHandle> DeclaredFieldHandles
+ {
+ get
+ {
+ return _typeDefinition.Fields;
+ }
+ }
+
+ internal IEnumerable<MethodHandle> DeclaredMethodAndConstructorHandles
+ {
+ get
+ {
+ return _typeDefinition.Methods;
+ }
+ }
+
+ internal IEnumerable<PropertyHandle> DeclaredPropertyHandles
+ {
+ get
+ {
+ return _typeDefinition.Properties;
+ }
+ }
+
+ private MetadataReader _reader;
+ private TypeDefinitionHandle _typeDefinitionHandle;
+ private TypeDefinition _typeDefinition;
+
+ private NamespaceChain NamespaceChain
+ {
+ get
+ {
+ if (_lazyNamespaceChain == null)
+ _lazyNamespaceChain = new NamespaceChain(_reader, _typeDefinition.NamespaceDefinition);
+ return _lazyNamespaceChain;
+ }
+ }
+
+ private volatile NamespaceChain _lazyNamespaceChain;
+
+ private volatile RuntimeType _lazyType;
+
+ private static NamedTypeToGuidTable _namedTypeToGuidTable = new NamedTypeToGuidTable();
+ private sealed class NamedTypeToGuidTable : ConcurrentUnifier<RuntimeNamedTypeInfo, Tuple<Guid>>
+ {
+ protected sealed override Tuple<Guid> Factory(RuntimeNamedTypeInfo key)
+ {
+ return new Tuple<Guid>(Guid.NewGuid());
+ }
+ }
+ }
+}
+
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs
new file mode 100644
index 000000000..09258efd3
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs
@@ -0,0 +1,182 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Assemblies;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // TypeInfos that represent type definitions (i.e. Foo or Foo<>, but not Foo<int> or arrays/pointers/byrefs.)
+ // that not opted into pay-for-play metadata.
+ //
+ internal sealed partial class RuntimeNoMetadataNamedTypeInfo : RuntimeTypeInfo
+ {
+ private RuntimeNoMetadataNamedTypeInfo(RuntimeType runtimeType)
+ {
+ _asType = runtimeType;
+ }
+
+ public sealed override Assembly Assembly
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ public sealed override TypeAttributes Attributes
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ public sealed override IEnumerable<TypeInfo> DeclaredNestedTypes
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ if (Object.ReferenceEquals(this, obj))
+ return true;
+
+ RuntimeNoMetadataNamedTypeInfo other = obj as RuntimeNoMetadataNamedTypeInfo;
+ if (other == null)
+ return false;
+ if (!(this._asType.Equals(other._asType)))
+ return false;
+ return true;
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _asType.GetHashCode();
+ }
+
+ public sealed override Guid GUID
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ public sealed override bool IsGenericType
+ {
+ get
+ {
+ return _asType.IsConstructedGenericType || this.IsGenericTypeDefinition;
+ }
+ }
+
+ public sealed override bool IsGenericTypeDefinition
+ {
+ get
+ {
+ return _asType.InternalIsGenericTypeDefinition;
+ }
+ }
+
+ //
+ // Returns the anchoring typedef that declares the members that this type wants returned by the Declared*** properties.
+ // The Declared*** properties will project the anchoring typedef's members by overriding their DeclaringType property with "this"
+ // and substituting the value of this.TypeContext into any generic parameters.
+ //
+ // Default implementation returns null which causes the Declared*** properties to return no members.
+ //
+ // Note that this does not apply to DeclaredNestedTypes. Nested types and their containers have completely separate generic instantiation environments
+ // (despite what C# might lead you to think.) Constructed generic types return the exact same same nested types that its generic type definition does
+ // - i.e. their DeclaringTypes refer back to the generic type definition, not the constructed generic type.)
+ //
+ // Note also that we cannot use this anchoring concept for base types because of generic parameters. Generic parameters return
+ // baseclass and interfaces based on its constraints.
+ //
+ internal sealed override RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ internal sealed override RuntimeType[] RuntimeGenericTypeParameters
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ internal sealed override RuntimeType RuntimeType
+ {
+ get
+ {
+ return _asType;
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal sealed override QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ throw this.ReflectionDomain.CreateMissingMetadataException(this);
+ }
+ }
+
+ private RuntimeType _asType;
+ }
+}
+
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs
new file mode 100644
index 000000000..777987640
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs
@@ -0,0 +1,1003 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.FieldInfos;
+using global::System.Reflection.Runtime.PropertyInfos;
+using global::System.Reflection.Runtime.EventInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using global::Internal.Reflection.Extensibility;
+using global::Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //
+ // Abstract base class for all TypeInfo's implemented by the runtime.
+ //
+ // This base class performs several services:
+ //
+ // - Provides default implementations that delegate to AsType() when possible and
+ // returns the "common" error result for narrowly applicable properties (such as those
+ // that apply only to generic parameters.)
+ //
+ // - Inverts the DeclaredMembers/DeclaredX relationship (DeclaredMembers is auto-implemented, others
+ // are overriden as abstract. This ordering makes more sense when reading from metadata.)
+ //
+ // - Overrides many "NotImplemented" members in TypeInfo with abstracts so failure to implement
+ // shows up as build error.
+ //
+ internal abstract partial class RuntimeTypeInfo : ExtensibleTypeInfo, ITraceableTypeMember
+ {
+ protected RuntimeTypeInfo()
+ {
+ }
+
+ public sealed override String AssemblyQualifiedName
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_AssemblyQualifiedName(this);
+
+ return AsType().AssemblyQualifiedName;
+ }
+ }
+
+ public sealed override Type AsType()
+ {
+ return this.RuntimeType;
+ }
+
+ public sealed override bool IsCOMObject
+ {
+ get
+ {
+ return ReflectionCoreExecution.ExecutionEnvironment.IsCOMObject(this.RuntimeType);
+ }
+ }
+
+ public sealed override Type BaseType
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_BaseType(this);
+
+ // If this has a RuntimeTypeHandle, let the underlying runtime engine have the first crack. If it refuses, fall back to metadata.
+ RuntimeTypeHandle typeHandle;
+ if (this.RuntimeType.InternalTryGetTypeHandle(out typeHandle))
+ {
+ RuntimeTypeHandle baseTypeHandle;
+ if (ReflectionCoreExecution.ExecutionEnvironment.TryGetBaseType(typeHandle, out baseTypeHandle))
+ return Type.GetTypeFromHandle(baseTypeHandle);
+ }
+
+ Type baseType = BaseTypeWithoutTheGenericParameterQuirk;
+ if (baseType != null && baseType.IsGenericParameter)
+ {
+ // Desktop quirk: a generic parameter whose constraint is another generic parameter reports its BaseType as System.Object
+ // unless that other generic parameter has a "class" constraint.
+ GenericParameterAttributes genericParameterAttributes = baseType.GetTypeInfo().GenericParameterAttributes;
+ if (0 == (genericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint))
+ baseType = this.ReflectionDomain.FoundationTypes.SystemObject;
+ }
+ return baseType;
+ }
+ }
+
+ public sealed override bool ContainsGenericParameters
+ {
+ get
+ {
+ return this.RuntimeType.InternalIsOpen;
+ }
+ }
+
+ //
+ // Left unsealed so that RuntimeNamedTypeInfo and RuntimeConstructedGenericTypeInfo and RuntimeGenericParameterTypeInfo can override.
+ //
+ public override IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_CustomAttributes(this);
+
+ Debug.Assert(IsArray || IsByRef || IsPointer);
+ return Empty<CustomAttributeData>.Enumerable;
+ }
+ }
+
+ public sealed override IEnumerable<ConstructorInfo> DeclaredConstructors
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredConstructors(this);
+
+ return GetDeclaredConstructorsInternal(this.AnchoringTypeDefinitionForDeclaredMembers);
+ }
+ }
+
+ public sealed override IEnumerable<EventInfo> DeclaredEvents
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredEvents(this);
+
+ return GetDeclaredEventsInternal(this.AnchoringTypeDefinitionForDeclaredMembers, null);
+ }
+ }
+
+ public sealed override IEnumerable<FieldInfo> DeclaredFields
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredFields(this);
+
+ return GetDeclaredFieldsInternal(this.AnchoringTypeDefinitionForDeclaredMembers, null);
+ }
+ }
+
+ public sealed override IEnumerable<MemberInfo> DeclaredMembers
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredMembers(this);
+
+ return GetDeclaredMembersInternal(
+ this.DeclaredMethods,
+ this.DeclaredConstructors,
+ this.DeclaredProperties,
+ this.DeclaredEvents,
+ this.DeclaredFields,
+ this.DeclaredNestedTypes);
+ }
+ }
+
+ public sealed override IEnumerable<MethodInfo> DeclaredMethods
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredMethods(this);
+
+ return GetDeclaredMethodsInternal(this.AnchoringTypeDefinitionForDeclaredMembers, null);
+ }
+ }
+
+ //
+ // Left unsealed as named types must override.
+ //
+ public override IEnumerable<TypeInfo> DeclaredNestedTypes
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredNestedTypes(this);
+
+ Debug.Assert(!(this is RuntimeNamedTypeInfo));
+ return Empty<TypeInfo>.Enumerable;
+ }
+ }
+
+ public sealed override IEnumerable<PropertyInfo> DeclaredProperties
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_DeclaredProperties(this);
+
+ return GetDeclaredPropertiesInternal(this.AnchoringTypeDefinitionForDeclaredMembers, null);
+ }
+ }
+
+ //
+ // Left unsealed as generic parameter types must override.
+ //
+ public override MethodBase DeclaringMethod
+ {
+ get
+ {
+ Debug.Assert(!IsGenericParameter);
+ throw new InvalidOperationException(SR.Arg_NotGenericParameter);
+ }
+ }
+
+ public abstract override bool Equals(Object obj);
+ public abstract override int GetHashCode();
+
+ public sealed override String FullName
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_FullName(this);
+
+ return AsType().FullName;
+ }
+ }
+
+ //
+ // Left unsealed as generic parameter types must override.
+ //
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ get
+ {
+ Debug.Assert(!IsGenericParameter);
+ throw new InvalidOperationException(SR.Arg_NotGenericParameter);
+ }
+ }
+
+ public sealed override int GenericParameterPosition
+ {
+ get
+ {
+ return AsType().GenericParameterPosition;
+ }
+ }
+
+ public sealed override Type[] GenericTypeArguments
+ {
+ get
+ {
+ return AsType().GenericTypeArguments;
+ }
+ }
+
+ public sealed override EventInfo GetDeclaredEvent(String name)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_GetDeclaredEvent(this, name);
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ TypeInfoCachedData cachedData = this.TypeInfoCachedData;
+ return cachedData.GetDeclaredEvent(name);
+ }
+
+ public sealed override FieldInfo GetDeclaredField(String name)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_GetDeclaredField(this, name);
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ TypeInfoCachedData cachedData = this.TypeInfoCachedData;
+ return cachedData.GetDeclaredField(name);
+ }
+
+ public sealed override MethodInfo GetDeclaredMethod(String name)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_GetDeclaredMethod(this, name);
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ TypeInfoCachedData cachedData = this.TypeInfoCachedData;
+ return cachedData.GetDeclaredMethod(name);
+ }
+
+ public sealed override PropertyInfo GetDeclaredProperty(String name)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_GetDeclaredProperty(this, name);
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ TypeInfoCachedData cachedData = this.TypeInfoCachedData;
+ return cachedData.GetDeclaredProperty(name);
+ }
+
+ //
+ // Implements the correct GUID behavior for all "constructed" types (i.e. returning an all-zero GUID.) Left unsealed
+ // so that RuntimeNamedTypeInfo can override.
+ //
+ public override Guid GUID
+ {
+ get
+ {
+ return Guid.Empty;
+ }
+ }
+
+ public sealed override IEnumerable<Type> ImplementedInterfaces
+ {
+ get
+ {
+ LowLevelListWithIList<Type> result = new LowLevelListWithIList<Type>();
+
+ bool done = false;
+
+ // If this has a RuntimeTypeHandle, let the underlying runtime engine have the first crack. If it refuses, fall back to metadata.
+ RuntimeTypeHandle typeHandle;
+
+ if (this.RuntimeType.InternalTryGetTypeHandle(out typeHandle))
+ {
+ IEnumerable<RuntimeTypeHandle> implementedInterfaces = ReflectionCoreExecution.ExecutionEnvironment.TryGetImplementedInterfaces(typeHandle);
+ if (implementedInterfaces != null)
+ {
+ done = true;
+
+ foreach (RuntimeTypeHandle th in implementedInterfaces)
+ {
+ result.Add(Type.GetTypeFromHandle(th));
+ }
+ }
+ }
+
+ if (!done)
+ {
+ TypeContext typeContext = this.TypeContext;
+ Type baseType = this.BaseTypeWithoutTheGenericParameterQuirk;
+ if (baseType != null)
+ result.AddRange(baseType.GetTypeInfo().ImplementedInterfaces);
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ foreach (QTypeDefRefOrSpec directlyImplementedInterface in this.TypeRefDefOrSpecsForDirectlyImplementedInterfaces)
+ {
+ Type ifc = reflectionDomain.Resolve(directlyImplementedInterface.Reader, directlyImplementedInterface.Handle, typeContext);
+ if (result.Contains(ifc))
+ continue;
+ result.Add(ifc);
+ foreach (Type indirectIfc in ifc.GetTypeInfo().ImplementedInterfaces)
+ {
+ if (result.Contains(indirectIfc))
+ continue;
+ result.Add(indirectIfc);
+ }
+ }
+ }
+
+ return result.AsNothingButIEnumerable();
+ }
+ }
+
+ public sealed override bool IsAssignableFrom(TypeInfo typeInfo)
+ {
+ RuntimeTypeInfo toTypeInfo = this;
+ RuntimeTypeInfo fromTypeInfo = typeInfo as RuntimeTypeInfo;
+
+ if (fromTypeInfo == null)
+ return false; // Desktop compat: If typeInfo is null, or implemented by a different Reflection implementation, return "false."
+
+ if (toTypeInfo.ReflectionDomain != fromTypeInfo.ReflectionDomain)
+ return false;
+
+ if (toTypeInfo.Equals(fromTypeInfo))
+ return true;
+
+ RuntimeTypeHandle toTypeHandle = default(RuntimeTypeHandle);
+ RuntimeTypeHandle fromTypeHandle = default(RuntimeTypeHandle);
+ bool haveTypeHandles = toTypeInfo.RuntimeType.InternalTryGetTypeHandle(out toTypeHandle) && fromTypeInfo.RuntimeType.InternalTryGetTypeHandle(out fromTypeHandle);
+ if (haveTypeHandles)
+ {
+ // If both types have type handles, let MRT handle this. It's not dependent on metadata.
+ if (ReflectionCoreExecution.ExecutionEnvironment.IsAssignableFrom(toTypeHandle, fromTypeHandle))
+ return true;
+
+ // Runtime IsAssignableFrom does not handle casts from generic type definitions: always returns false. For those, we fall through to the
+ // managed implementation. For everyone else, return "false".
+ //
+ // Runtime IsAssignableFrom does not handle pointer -> UIntPtr cast.
+ if (!(fromTypeInfo.IsGenericTypeDefinition || fromTypeInfo.IsPointer))
+ return false;
+ }
+
+ // If we got here, the types are open, or reduced away, or otherwise lacking in type handles. Perform the IsAssignability check in managed code.
+ return Assignability.IsAssignableFrom(this, typeInfo, fromTypeInfo.ReflectionDomain.FoundationTypes);
+ }
+
+ public sealed override bool IsEnum
+ {
+ get
+ {
+ return 0 != (Classification & TypeClassification.IsEnum);
+ }
+ }
+
+ public sealed override bool IsGenericParameter
+ {
+ get
+ {
+ return AsType().IsGenericParameter;
+ }
+ }
+
+ //
+ // Left unsealed as generic type definitions and constructed generic types must override.
+ //
+ public override bool IsGenericType
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ //
+ // Left unsealed as generic type definitions must override.
+ //
+ public override bool IsGenericTypeDefinition
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public sealed override bool IsPrimitive
+ {
+ get
+ {
+ return 0 != (Classification & TypeClassification.IsPrimitive);
+ }
+ }
+
+ public sealed override bool IsSerializable
+ {
+ get
+ {
+ return 0 != (this.Attributes & TypeAttributes.Serializable);
+ }
+ }
+
+ public sealed override bool IsValueType
+ {
+ get
+ {
+ return 0 != (Classification & TypeClassification.IsValueType);
+ }
+ }
+
+ public sealed override Module Module
+ {
+ get
+ {
+ return Assembly.ManifestModule;
+ }
+ }
+
+ public sealed override String Namespace
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_Namespace(this);
+
+ return AsType().Namespace;
+ }
+ }
+
+ public sealed override Type[] GenericTypeParameters
+ {
+ get
+ {
+ RuntimeType[] genericTypeParameters = RuntimeGenericTypeParameters;
+ if (genericTypeParameters.Length == 0)
+ return Array.Empty<Type>();
+ Type[] result = new Type[genericTypeParameters.Length];
+ for (int i = 0; i < genericTypeParameters.Length; i++)
+ result[i] = genericTypeParameters[i];
+ return result;
+ }
+ }
+
+ public sealed override int GetArrayRank()
+ {
+ return AsType().GetArrayRank();
+ }
+
+ public sealed override Type GetElementType()
+ {
+ return AsType().GetElementType();
+ }
+
+ //
+ // Left unsealed as generic parameter types must override.
+ //
+ public override Type[] GetGenericParameterConstraints()
+ {
+ Debug.Assert(!IsGenericParameter);
+ throw new InvalidOperationException(SR.Arg_NotGenericParameter);
+ }
+
+ public sealed override Type GetGenericTypeDefinition()
+ {
+ return AsType().GetGenericTypeDefinition();
+ }
+
+ public sealed override Type MakeArrayType()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_MakeArrayType(this);
+
+ return AsType().MakeArrayType();
+ }
+
+ public sealed override Type MakeArrayType(int rank)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_MakeArrayType(this, rank);
+
+ return AsType().MakeArrayType(rank);
+ }
+
+ public sealed override Type MakeByRefType()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_MakeByRefType(this);
+
+ return AsType().MakeByRefType();
+ }
+
+ public sealed override Type MakeGenericType(params Type[] typeArguments)
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_MakeGenericType(this, typeArguments);
+
+ return AsType().MakeGenericType(typeArguments);
+ }
+
+ public sealed override Type MakePointerType()
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_MakePointerType(this);
+
+ return AsType().MakePointerType();
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ return this.InternalDeclaringType;
+ }
+ }
+
+ public sealed override String Name
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.TypeInfo_Name(this);
+
+ return this.InternalName;
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ return AsType().ToString();
+ }
+
+
+ String ITraceableTypeMember.MemberName
+ {
+ get
+ {
+ return this.InternalName;
+ }
+ }
+
+ Type ITraceableTypeMember.ContainingType
+ {
+ get
+ {
+ return this.InternalDeclaringType;
+ }
+ }
+
+ //
+ // The non-public version of AsType().
+ //
+ internal abstract RuntimeType RuntimeType { get; }
+
+ internal ReflectionDomain ReflectionDomain
+ {
+ get
+ {
+ return ReflectionCoreExecution.ExecutionDomain; //@todo: User Reflection Domains not yet supported.
+ }
+ }
+
+ //
+ // Returns the anchoring typedef that declares the members that this type wants returned by the Declared*** properties.
+ // The Declared*** properties will project the anchoring typedef's members by overriding their DeclaringType property with "this"
+ // and substituting the value of this.TypeContext into any generic parameters.
+ //
+ // Default implementation returns null which causes the Declared*** properties to return no members.
+ //
+ // Note that this does not apply to DeclaredNestedTypes. Nested types and their containers have completely separate generic instantiation environments
+ // (despite what C# might lead you to think.) Constructed generic types return the exact same same nested types that its generic type definition does
+ // - i.e. their DeclaringTypes refer back to the generic type definition, not the constructed generic type.)
+ //
+ // Note also that we cannot use this anchoring concept for base types because of generic parameters. Generic parameters return
+ // a base class and interface list based on its constraints.
+ //
+ internal virtual RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ //
+ // Return all declared events whose name matches "optionalNameFilter". If optionalNameFilter is null, return them all.
+ //
+ internal IEnumerable<RuntimeEventInfo> GetDeclaredEventsInternal(RuntimeNamedTypeInfo definingType, String optionalNameFilter)
+ {
+ if (definingType != null)
+ {
+ // We require the caller to pass a value that we could calculate ourselves because we're an iterator and we
+ // don't want any MissingMetadataException that AnchoringType throws to be deferred.
+ Debug.Assert(definingType.Equals(this.AnchoringTypeDefinitionForDeclaredMembers));
+
+ MetadataReader reader = definingType.Reader;
+ foreach (EventHandle eventHandle in definingType.DeclaredEventHandles)
+ {
+ if (optionalNameFilter == null || eventHandle.GetEvent(reader).Name.StringEquals(optionalNameFilter, reader))
+ yield return RuntimeEventInfo.GetRuntimeEventInfo(eventHandle, definingType, this);
+ }
+ }
+ }
+
+ //
+ // Return all declared fields whose name matches "optionalNameFilter". If optionalNameFilter is null, return them all.
+ //
+ internal IEnumerable<RuntimeFieldInfo> GetDeclaredFieldsInternal(RuntimeNamedTypeInfo definingType, String optionalNameFilter)
+ {
+ if (definingType != null)
+ {
+ // We require the caller to pass a value that we could calculate ourselves because we're an iterator and we
+ // don't want any MissingMetadataException that AnchoringType throws to be deferred.
+ Debug.Assert(definingType.Equals(this.AnchoringTypeDefinitionForDeclaredMembers));
+
+ MetadataReader reader = definingType.Reader;
+ foreach (FieldHandle fieldHandle in definingType.DeclaredFieldHandles)
+ {
+ if (optionalNameFilter == null || fieldHandle.GetField(reader).Name.StringEquals(optionalNameFilter, reader))
+ yield return RuntimeFieldInfo.GetRuntimeFieldInfo(fieldHandle, definingType, this);
+ }
+ }
+ }
+
+ //
+ // Return all declared methods whose name matches "optionalNameFilter". If optionalNameFilter is null, return them all.
+ //
+ internal IEnumerable<RuntimeMethodInfo> GetDeclaredMethodsInternal(RuntimeNamedTypeInfo definingType, String optionalNameFilter)
+ {
+ if (definingType != null)
+ {
+ // We require the caller to pass a value that we could calculate ourselves because we're an iterator and we
+ // don't want any MissingMetadataException that AnchoringType throws to be deferred.
+ Debug.Assert(definingType.Equals(this.AnchoringTypeDefinitionForDeclaredMembers));
+
+ MetadataReader reader = definingType.Reader;
+ foreach (MethodHandle methodHandle in definingType.DeclaredMethodAndConstructorHandles)
+ {
+ Method method = methodHandle.GetMethod(reader);
+
+ if ((optionalNameFilter != null) && !method.Name.StringEquals(optionalNameFilter, reader))
+ continue;
+
+ if (MetadataReaderExtensions.IsConstructor(ref method, reader))
+ continue;
+ yield return RuntimeNamedMethodInfo.GetRuntimeNamedMethodInfo(methodHandle, definingType, this);
+ }
+ }
+
+ foreach (RuntimeMethodInfo syntheticMethod in SyntheticMethods)
+ {
+ if (optionalNameFilter == null || optionalNameFilter == syntheticMethod.Name)
+ {
+ yield return syntheticMethod;
+ }
+ }
+ }
+
+ //
+ // Return all declared properties whose name matches "optionalNameFilter". If optionalNameFilter is null, return them all.
+ //
+ internal IEnumerable<RuntimePropertyInfo> GetDeclaredPropertiesInternal(RuntimeNamedTypeInfo definingType, String optionalNameFilter)
+ {
+ if (definingType != null)
+ {
+ // We require the caller to pass a value that we could calculate ourselves because we're an iterator and we
+ // don't want any MissingMetadataException that AnchoringType throws to be deferred.
+ Debug.Assert(definingType.Equals(this.AnchoringTypeDefinitionForDeclaredMembers));
+
+ MetadataReader reader = definingType.Reader;
+ foreach (PropertyHandle propertyHandle in definingType.DeclaredPropertyHandles)
+ {
+ if (optionalNameFilter == null || propertyHandle.GetProperty(reader).Name.StringEquals(optionalNameFilter, reader))
+ yield return RuntimePropertyInfo.GetRuntimePropertyInfo(propertyHandle, definingType, this);
+ }
+ }
+ }
+
+
+ //
+ // The non-public version of TypeInfo.GenericTypeParameters (does not array-copy.)
+ //
+ internal virtual RuntimeType[] RuntimeGenericTypeParameters
+ {
+ get
+ {
+ Debug.Assert(!(this is RuntimeNamedTypeInfo));
+ return Array.Empty<RuntimeType>();
+ }
+ }
+
+ //
+ // Normally returns empty: Overridden by array types to return constructors.
+ //
+ internal virtual IEnumerable<RuntimeConstructorInfo> SyntheticConstructors
+ {
+ get
+ {
+ return Empty<RuntimeConstructorInfo>.Enumerable;
+ }
+ }
+
+ //
+ // Normally returns empty: Overridden by array types to return the "Get" and "Set" methods.
+ //
+ internal virtual IEnumerable<RuntimeMethodInfo> SyntheticMethods
+ {
+ get
+ {
+ return Empty<RuntimeMethodInfo>.Enumerable;
+ }
+ }
+
+ //
+ // Returns the base type as a typeDef, Ref, or Spec. Default behavior is to QTypeDefRefOrSpec.Null, which causes BaseType to return null.
+ //
+ internal virtual QTypeDefRefOrSpec TypeRefDefOrSpecForBaseType
+ {
+ get
+ {
+ return QTypeDefRefOrSpec.Null;
+ }
+ }
+
+ //
+ // Returns the *directly implemented* interfaces as typedefs, specs or refs. ImplementedInterfaces will take care of the transitive closure and
+ // insertion of the TypeContext.
+ //
+ internal virtual QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImplementedInterfaces
+ {
+ get
+ {
+ return Array.Empty<QTypeDefRefOrSpec>();
+ }
+ }
+
+ //
+ // Returns the generic parameter substitutions to use when enumerating declared members, base class and implemented interfaces.
+ //
+ internal virtual TypeContext TypeContext
+ {
+ get
+ {
+ return new TypeContext(null, null);
+ }
+ }
+
+ //
+ // Note: This can be (and is) called multiple times. We do not do this work in the constructor as calling ToString()
+ // in the constructor causes some serious recursion issues.
+ //
+ internal void EstablishDebugName()
+ {
+#if DEBUG
+ if (_debugName == null)
+ {
+ _debugName = "Constructing..."; // Protect against any inadvertent reentrancy.
+ String debugName;
+ if (ReflectionTrace.Enabled)
+ debugName = this.GetTraceString(); // If tracing on, call this.GetTraceString() which only gives you useful strings when metadata is available but doesn't pollute the ETW trace.
+ else
+ debugName = this.ToString();
+ if (debugName == null)
+ debugName = "";
+ _debugName = debugName;
+ }
+#endif
+ return;
+ }
+
+
+ private String InternalName
+ {
+ get
+ {
+ return this.RuntimeType.Name;
+ }
+ }
+
+ private Type InternalDeclaringType
+ {
+ get
+ {
+ return this.RuntimeType.DeclaringType;
+ }
+ }
+
+ //
+ // This internal method implements BaseType without the following desktop quirk:
+ //
+ // class Foo<X,Y>
+ // where X:Y
+ // where Y:MyReferenceClass
+ //
+ // The desktop reports "X"'s base type as "System.Object" rather than "Y", even though it does
+ // report any interfaces that are in MyReferenceClass's interface list.
+ //
+ // This seriously messes up the implementation of RuntimeTypeInfo.ImplementedInterfaces which assumes
+ // that it can recover the transitive interface closure by combining the directly mentioned interfaces and
+ // the BaseType's own interface closure.
+ //
+ // To implement this with the least amount of code smell, we'll implement the idealized version of BaseType here
+ // and make the special-case adjustment in the public version of BaseType.
+ //
+ private RuntimeType BaseTypeWithoutTheGenericParameterQuirk
+ {
+ get
+ {
+ QTypeDefRefOrSpec baseTypeDefRefOrSpec = TypeRefDefOrSpecForBaseType;
+ MetadataReader reader = baseTypeDefRefOrSpec.Reader;
+ RuntimeType baseType = null;
+ ReflectionDomain reflectionDomain = this.ReflectionDomain;
+ if (reader != null)
+ {
+ Handle typeDefRefOrSpec = baseTypeDefRefOrSpec.Handle;
+ baseType = reflectionDomain.Resolve(reader, typeDefRefOrSpec, this.TypeContext);
+ }
+ return baseType;
+ }
+ }
+
+ //
+ // Returns a latched set of flags indicating the value of IsValueType, IsEnum, etc.
+ //
+ private TypeClassification Classification
+ {
+ get
+ {
+ if (_lazyClassification == 0)
+ {
+ TypeClassification classification = TypeClassification.Computed;
+ Type baseType = this.BaseType;
+ if (baseType != null)
+ {
+ FoundationTypes foundationTypes = this.ReflectionDomain.FoundationTypes;
+ Type enumType = foundationTypes.SystemEnum;
+ Type valueType = foundationTypes.SystemValueType;
+
+ if (baseType.Equals(enumType))
+ classification |= TypeClassification.IsEnum | TypeClassification.IsValueType;
+ if (baseType.Equals(valueType) && !(this.AsType().Equals(enumType)))
+ {
+ classification |= TypeClassification.IsValueType;
+ Type thisType = this.AsType();
+ foreach (Type primitiveType in this.ReflectionDomain.PrimitiveTypes)
+ {
+ if (thisType.Equals(primitiveType))
+ {
+ classification |= TypeClassification.IsPrimitive;
+ break;
+ }
+ }
+ }
+ }
+ _lazyClassification = classification;
+ }
+ return _lazyClassification;
+ }
+ }
+
+ [Flags]
+ private enum TypeClassification
+ {
+ Computed = 0x00000001, // Always set (to indicate that the lazy evaluation has occurred)
+ IsValueType = 0x00000002,
+ IsEnum = 0x00000004,
+ IsPrimitive = 0x00000008,
+ }
+
+ //
+ // Return all declared members. This may look like a silly code sequence to wrap inside a helper but we want to separate the iterator from
+ // the actual calls to get the sub-enumerations as we want any MissingMetadataException thrown by those
+ // calls to happen at the time DeclaredMembers is called.
+ //
+ private IEnumerable<MemberInfo> GetDeclaredMembersInternal(
+ IEnumerable<MethodInfo> methods,
+ IEnumerable<ConstructorInfo> constructors,
+ IEnumerable<PropertyInfo> properties,
+ IEnumerable<EventInfo> events,
+ IEnumerable<FieldInfo> fields,
+ IEnumerable<TypeInfo> nestedTypes
+ )
+ {
+ foreach (MemberInfo member in methods)
+ yield return member;
+ foreach (MemberInfo member in constructors)
+ yield return member;
+ foreach (MemberInfo member in properties)
+ yield return member;
+ foreach (MemberInfo member in events)
+ yield return member;
+ foreach (MemberInfo member in fields)
+ yield return member;
+ foreach (MemberInfo member in nestedTypes)
+ yield return member;
+ }
+
+ //
+ // Return all declared constructors.
+ //
+ private IEnumerable<RuntimeConstructorInfo> GetDeclaredConstructorsInternal(RuntimeNamedTypeInfo definingType)
+ {
+ if (definingType != null)
+ {
+ // We require the caller to pass a value that we could calculate ourselves because we're an iterator and we
+ // don't want any MissingMetadataException that AnchoringType throws to be deferred.
+ Debug.Assert(definingType.Equals(this.AnchoringTypeDefinitionForDeclaredMembers));
+
+ RuntimeTypeInfo contextType = this;
+ foreach (MethodHandle methodHandle in definingType.DeclaredConstructorHandles)
+ {
+ yield return RuntimePlainConstructorInfo.GetRuntimePlainConstructorInfo(methodHandle, definingType, contextType);
+ }
+ }
+
+ foreach (RuntimeConstructorInfo syntheticConstructor in SyntheticConstructors)
+ {
+ yield return syntheticConstructor;
+ }
+ }
+
+ private volatile TypeClassification _lazyClassification;
+
+ private TypeInfoCachedData TypeInfoCachedData
+ {
+ get
+ {
+ TypeInfoCachedData cachedData = _lazyTypeInfoCachedData;
+ if (cachedData != null)
+ return cachedData;
+ _lazyTypeInfoCachedData = cachedData = new TypeInfoCachedData(this);
+ return cachedData;
+ }
+ }
+
+ private volatile TypeInfoCachedData _lazyTypeInfoCachedData;
+
+#if DEBUG
+ private String _debugName;
+#endif // DEBUG
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/TypeInfoCachedData.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/TypeInfoCachedData.cs
new file mode 100644
index 000000000..0ac493414
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/TypeInfoCachedData.cs
@@ -0,0 +1,121 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Types;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.Dispensers;
+using global::System.Reflection.Runtime.FieldInfos;
+using global::System.Reflection.Runtime.EventInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.PropertyInfos;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.TypeInfos
+{
+ //================================================================================================================
+ // TypeInfoCachedData objects are allocated on-demand on a per-TypeInfo basis to cache hot data for key scenarios.
+ // To maximize throughput once the cache is created, the object creates all of its internal caches up front
+ // and holds entries strongly (and relying on the fact that TypeInfos themselves are held weakly to avoid immortality.)
+ //
+ // Note that it is possible that two threads racing to query the same TypeInfo may allocate and query two different
+ // CachedData objecs. Thus, this object must not be relied upon to preserve object identity.
+ //================================================================================================================
+ internal sealed class TypeInfoCachedData
+ {
+ public TypeInfoCachedData(RuntimeTypeInfo runtimeTypeInfo)
+ {
+ _runtimeTypeInfo = runtimeTypeInfo;
+ _methodLookupDispenser = new DispenserThatAlwaysReuses<String, RuntimeMethodInfo>(LookupDeclaredMethodByName);
+ _fieldLookupDispenser = new DispenserThatAlwaysReuses<String, RuntimeFieldInfo>(LookupDeclaredFieldByName);
+ _propertyLookupDispenser = new DispenserThatAlwaysReuses<String, RuntimePropertyInfo>(LookupDeclaredPropertyByName);
+ _eventLookupDispenser = new DispenserThatAlwaysReuses<String, RuntimeEventInfo>(LookupDeclaredEventByName);
+ }
+
+ public RuntimeMethodInfo GetDeclaredMethod(String name)
+ {
+ return _methodLookupDispenser.GetOrAdd(name);
+ }
+
+ public RuntimeFieldInfo GetDeclaredField(String name)
+ {
+ return _fieldLookupDispenser.GetOrAdd(name);
+ }
+
+ public RuntimePropertyInfo GetDeclaredProperty(String name)
+ {
+ return _propertyLookupDispenser.GetOrAdd(name);
+ }
+
+ public RuntimeEventInfo GetDeclaredEvent(String name)
+ {
+ return _eventLookupDispenser.GetOrAdd(name);
+ }
+
+
+ private Dispenser<String, RuntimeMethodInfo> _methodLookupDispenser;
+
+ private RuntimeMethodInfo LookupDeclaredMethodByName(String name)
+ {
+ RuntimeNamedTypeInfo definingType = _runtimeTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
+ IEnumerator<RuntimeMethodInfo> matches = _runtimeTypeInfo.GetDeclaredMethodsInternal(definingType, name).GetEnumerator();
+ if (!matches.MoveNext())
+ return null;
+ RuntimeMethodInfo result = matches.Current;
+ if (matches.MoveNext())
+ throw new AmbiguousMatchException();
+ return result;
+ }
+
+ private Dispenser<String, RuntimeFieldInfo> _fieldLookupDispenser;
+
+ private RuntimeFieldInfo LookupDeclaredFieldByName(String name)
+ {
+ RuntimeNamedTypeInfo definingType = _runtimeTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
+ IEnumerator<RuntimeFieldInfo> matches = _runtimeTypeInfo.GetDeclaredFieldsInternal(definingType, name).GetEnumerator();
+ if (!matches.MoveNext())
+ return null;
+ RuntimeFieldInfo result = matches.Current;
+ if (matches.MoveNext())
+ throw new AmbiguousMatchException();
+ return result;
+ }
+
+ private Dispenser<String, RuntimePropertyInfo> _propertyLookupDispenser;
+
+ private RuntimePropertyInfo LookupDeclaredPropertyByName(String name)
+ {
+ RuntimeNamedTypeInfo definingType = _runtimeTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
+ IEnumerator<RuntimePropertyInfo> matches = _runtimeTypeInfo.GetDeclaredPropertiesInternal(definingType, name).GetEnumerator();
+ if (!matches.MoveNext())
+ return null;
+ RuntimePropertyInfo result = matches.Current;
+ if (matches.MoveNext())
+ throw new AmbiguousMatchException();
+ return result;
+ }
+
+
+ private Dispenser<String, RuntimeEventInfo> _eventLookupDispenser;
+
+ private RuntimeEventInfo LookupDeclaredEventByName(String name)
+ {
+ RuntimeNamedTypeInfo definingType = _runtimeTypeInfo.AnchoringTypeDefinitionForDeclaredMembers;
+ IEnumerator<RuntimeEventInfo> matches = _runtimeTypeInfo.GetDeclaredEventsInternal(definingType, name).GetEnumerator();
+ if (!matches.MoveNext())
+ return null;
+ RuntimeEventInfo result = matches.Current;
+ if (matches.MoveNext())
+ throw new AmbiguousMatchException();
+ return result;
+ }
+
+ private RuntimeTypeInfo _runtimeTypeInfo;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs
new file mode 100644
index 000000000..610c4f5b9
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs
@@ -0,0 +1,242 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Collections;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Assemblies;
+
+namespace System.Reflection.Runtime.TypeParsing
+{
+ //
+ // String tokenizer for typenames passed to the GetType() api's.
+ //
+ internal sealed class TypeLexer
+ {
+ public TypeLexer(String s)
+ {
+ // Turn the string into a char array with a NUL terminator.
+ char[] chars = new char[s.Length + 1];
+ s.CopyTo(0, chars, 0, s.Length);
+ _chars = chars;
+ _index = 0;
+ }
+
+ public TokenType Peek
+ {
+ get
+ {
+ SkipWhiteSpace();
+ char c = _chars[_index];
+ return CharToToken(c);
+ }
+ }
+
+ public TokenType PeekSecond
+ {
+ get
+ {
+ SkipWhiteSpace();
+ int index = _index + 1;
+ while (Char.IsWhiteSpace(_chars[index]))
+ index++;
+ char c = _chars[index];
+ return CharToToken(c);
+ }
+ }
+
+
+ public void Skip()
+ {
+ Debug.Assert(_index != _chars.Length);
+ SkipWhiteSpace();
+ _index++;
+ }
+
+ // Return the next token and skip index past it unless already at end of string
+ // or the token is not a reserved token.
+ public TokenType GetNextToken()
+ {
+ TokenType tokenType = Peek;
+ if (tokenType == TokenType.End || tokenType == TokenType.Other)
+ return tokenType;
+ Skip();
+ return tokenType;
+ }
+
+ //
+ // Lex the next segment as part of a type name. (Do not use for assembly names.)
+ //
+ // Note that unescaped "."'s do NOT terminate the identifier, but unescaped "+"'s do.
+ //
+ // Terminated by the first non-escaped reserved character ('[', ']', '+', '&', '*' or ',')
+ //
+ public String GetNextIdentifier()
+ {
+ SkipWhiteSpace();
+
+ int src = _index;
+ char[] buffer = new char[_chars.Length];
+ int dst = 0;
+ for (; ;)
+ {
+ char c = _chars[src];
+ TokenType token = CharToToken(c);
+ if (token != TokenType.Other)
+ break;
+ src++;
+ if (c == '\\')
+ {
+ c = _chars[src];
+ if (c != NUL)
+ src++;
+ if (c == NUL || CharToToken(c) == TokenType.Other)
+ {
+ // If we got here, a backslash was used to escape a character that is not legal to escape inside a type name.
+ //
+ // Common sense would dictate throwing an ArgumentException but that's not what the desktop CLR does.
+ // The desktop CLR treats this case by returning FALSE from TypeName::TypeNameParser::GetIdentifier().
+ // Unfortunately, no one checks this return result. Instead, the CLR keeps parsing (unfortunately, the lexer
+ // was left in some strange state by the previous failure but typically, this goes unnoticed) and eventually, tries to resolve
+ // a Type whose name is the empty string. When it can't resolve that type, the CLR throws a TypeLoadException()
+ // complaining about be unable to find a type with the empty name.
+ //
+ // To emulate this accidental behavior, we'll throw a special exception that's caught by the TypeParser.
+ //
+ throw new IllegalEscapeSequenceException();
+ }
+ }
+ buffer[dst++] = c;
+ }
+
+ _index = src;
+ return new String(buffer, 0, dst);
+ }
+
+ //
+ // Lex the next segment as the assembly name at the end of an assembly-qualified type name. (Do not use for
+ // assembly names embedded inside generic type arguments.)
+ //
+ // Terminated by NUL. There are no escape characters defined by the typename lexer (however, AssemblyName
+ // does have its own escape rules.)
+ //
+ public RuntimeAssemblyName GetNextAssemblyName()
+ {
+ SkipWhiteSpace();
+
+ int src = _index;
+ char[] buffer = new char[_chars.Length];
+ int dst = 0;
+ for (; ;)
+ {
+ char c = _chars[src];
+ if (c == NUL)
+ break;
+ src++;
+ buffer[dst++] = c;
+ }
+ _index = src;
+ String fullName = new String(buffer, 0, dst);
+ return AssemblyNameParser.Parse(fullName);
+ }
+
+ //
+ // Lex the next segment as an assembly name embedded inside a generic argument type.
+ //
+ // Terminated by an unescaped ']'.
+ //
+ public RuntimeAssemblyName GetNextEmbeddedAssemblyName()
+ {
+ SkipWhiteSpace();
+
+ int src = _index;
+ char[] buffer = new char[_chars.Length];
+ int dst = 0;
+ for (; ;)
+ {
+ char c = _chars[src];
+ if (c == NUL)
+ throw new ArgumentException();
+ if (c == ']')
+ break;
+ src++;
+
+ // Backslash can be used to escape a ']' - any other backslash character is left alone (along with the backslash)
+ // for the AssemblyName parser to handle.
+ if (c == '\\' && _chars[src] == ']')
+ {
+ c = _chars[src++];
+ }
+ buffer[dst++] = c;
+ }
+ _index = src;
+ String fullName = new String(buffer, 0, dst);
+ return AssemblyNameParser.Parse(fullName);
+ }
+
+ //
+ // Classify a character as a TokenType. (Fortunately, all tokens in typename strings other than identifiers are single-character tokens.)
+ //
+ private static TokenType CharToToken(char c)
+ {
+ switch (c)
+ {
+ case NUL:
+ return TokenType.End;
+ case '[':
+ return TokenType.OpenSqBracket;
+ case ']':
+ return TokenType.CloseSqBracket;
+ case ',':
+ return TokenType.Comma;
+ case '+':
+ return TokenType.Plus;
+ case '*':
+ return TokenType.Asterisk;
+ case '&':
+ return TokenType.Ampersand;
+ default:
+ return TokenType.Other;
+ }
+ }
+
+ //
+ // The desktop typename parser has a strange attitude towards whitespace. It throws away whitespace between punctuation tokens and whitespace
+ // preceeding identifiers or assembly names (and this cannot be escaped away). But whitespace between the end of an identifier
+ // and the punctuation that ends it is *not* ignored.
+ //
+ // In other words, GetType(" Foo") searches for "Foo" but GetType("Foo ") searches for "Foo ".
+ //
+ // Whitespace between the end of an assembly name and the punction mark that ends it is also not ignored by this parser,
+ // but this is irrelevant since the assembly name is then turned over to AssemblyName for parsing, which *does* ignore trailing whitespace.
+ //
+ private void SkipWhiteSpace()
+ {
+ while (Char.IsWhiteSpace(_chars[_index]))
+ _index++;
+ }
+
+
+ private int _index;
+ private char[] _chars;
+ private const char NUL = (char)0;
+
+
+ public sealed class IllegalEscapeSequenceException : Exception
+ {
+ }
+ }
+
+ internal enum TokenType
+ {
+ End = 0, //At end of string
+ OpenSqBracket = 1, //'['
+ CloseSqBracket = 2, //']'
+ Comma = 3, //','
+ Plus = 4, //'+'
+ Asterisk = 5, //'*'
+ Ampersand = 6, //'&'
+ Other = 7, //Type identifier, AssemblyName or embedded AssemblyName.
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs
new file mode 100644
index 000000000..72918dc47
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs
@@ -0,0 +1,535 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Collections;
+using global::System.Reflection;
+using global::System.Collections.Generic;
+
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.Assemblies;
+
+using global::Internal.Metadata.NativeFormat;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.NonPortable;
+
+namespace System.Reflection.Runtime.TypeParsing
+{
+ //
+ // The TypeName class is the base class for a family of types that represent the nodes in a parse tree for
+ // assembly-qualified type names.
+ //
+ internal abstract class TypeName
+ {
+ public abstract Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result);
+ public abstract override String ToString();
+ }
+
+
+ //
+ // Represents a parse of a type name OPTIONALLY qualified by an assembly name. If present, the assembly name follows
+ // a comma following the type name.
+ //
+ // Note that unlike the reflection model, the assembly qualification is a property of a typename string as a whole
+ // rather than the property of the single namespace type that "represents" the type. This model is simply a better match to
+ // how type names passed to GetType() are constructed and parsed.
+ //
+ internal sealed class AssemblyQualifiedTypeName : TypeName
+ {
+ public AssemblyQualifiedTypeName(NonQualifiedTypeName typeName, RuntimeAssemblyName assemblyName)
+ {
+ Debug.Assert(typeName != null);
+ TypeName = typeName;
+ AssemblyName = assemblyName;
+ }
+
+ public NonQualifiedTypeName TypeName { get; private set; }
+ public RuntimeAssemblyName AssemblyName { get; private set; } // This can return null if the type name was not actually qualified.
+
+ public sealed override String ToString()
+ {
+ return TypeName.ToString() + ((AssemblyName == null) ? "" : ", " + AssemblyName.FullName);
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ if (AssemblyName == null)
+ {
+ return TypeName.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out result);
+ }
+ else
+ {
+ RuntimeAssembly newAssembly;
+ Exception assemblyLoadException = RuntimeAssembly.TryGetRuntimeAssembly(reflectionDomain, AssemblyName, out newAssembly);
+ if (assemblyLoadException != null)
+ return assemblyLoadException;
+ return TypeName.TryResolve(reflectionDomain, newAssembly, ignoreCase, out result);
+ }
+ }
+ }
+
+ //
+ // Base class for all non-assembly-qualified type names.
+ //
+ internal abstract class NonQualifiedTypeName : TypeName
+ {
+ }
+
+ //
+ // Base class for namespace or nested type.
+ //
+ internal abstract class NamedTypeName : NonQualifiedTypeName
+ {
+ }
+
+ //
+ // Non-nested named type. The full name is the namespace-qualified name. For example, the FullName for
+ // System.Collections.Generic.IList<> is "System.Collections.Generic.IList`1".
+ //
+ internal sealed partial class NamespaceTypeName : NamedTypeName
+ {
+ public NamespaceTypeName(String[] namespaceParts, String name)
+ {
+ Debug.Assert(namespaceParts != null);
+ Debug.Assert(name != null);
+
+ _name = name;
+ _namespaceParts = namespaceParts;
+ }
+
+ public sealed override String ToString()
+ {
+ String fullName = "";
+ for (int i = 0; i < _namespaceParts.Length; i++)
+ {
+ fullName += _namespaceParts[_namespaceParts.Length - i - 1];
+ fullName += ".";
+ }
+ fullName += _name;
+ return fullName;
+ }
+
+ private bool TryResolveNamespaceDefinitionCaseSensitive(MetadataReader reader, ScopeDefinitionHandle scopeDefinitionHandle, out NamespaceDefinition namespaceDefinition)
+ {
+ namespaceDefinition = scopeDefinitionHandle.GetScopeDefinition(reader).RootNamespaceDefinition.GetNamespaceDefinition(reader);
+ IEnumerable<NamespaceDefinitionHandle> candidates = namespaceDefinition.NamespaceDefinitions;
+ int idx = _namespaceParts.Length;
+ while (idx-- != 0)
+ {
+ // Each iteration finds a match for one segment of the namespace chain.
+ String expected = _namespaceParts[idx];
+ bool foundMatch = false;
+ foreach (NamespaceDefinitionHandle candidate in candidates)
+ {
+ namespaceDefinition = candidate.GetNamespaceDefinition(reader);
+ if (namespaceDefinition.Name.StringOrNullEquals(expected, reader))
+ {
+ // Found a match for this segment of the namespace chain. Move on to the next level.
+ foundMatch = true;
+ candidates = namespaceDefinition.NamespaceDefinitions;
+ break;
+ }
+ }
+
+ if (!foundMatch)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private Exception UncachedTryResolveCaseSensitive(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, out RuntimeType result)
+ {
+ result = null;
+
+ foreach (QScopeDefinition scopeDefinition in currentAssembly.AllScopes)
+ {
+ MetadataReader reader = scopeDefinition.Reader;
+ ScopeDefinitionHandle scopeDefinitionHandle = scopeDefinition.Handle;
+
+ NamespaceDefinition namespaceDefinition;
+ if (!TryResolveNamespaceDefinitionCaseSensitive(reader, scopeDefinitionHandle, out namespaceDefinition))
+ {
+ continue;
+ }
+
+ // We've successfully drilled down the namespace chain. Now look for a top-level type matching the type name.
+ IEnumerable<TypeDefinitionHandle> candidateTypes = namespaceDefinition.TypeDefinitions;
+ foreach (TypeDefinitionHandle candidateType in candidateTypes)
+ {
+ TypeDefinition typeDefinition = candidateType.GetTypeDefinition(reader);
+ if (typeDefinition.Name.StringEquals(_name, reader))
+ {
+ result = reflectionDomain.ResolveTypeDefinition(reader, candidateType);
+ return null;
+ }
+ }
+
+ // No match found in this assembly - see if there's a matching type forwarder.
+ IEnumerable<TypeForwarderHandle> candidateTypeForwarders = namespaceDefinition.TypeForwarders;
+ foreach (TypeForwarderHandle typeForwarderHandle in candidateTypeForwarders)
+ {
+ TypeForwarder typeForwarder = typeForwarderHandle.GetTypeForwarder(reader);
+ if (typeForwarder.Name.StringEquals(_name, reader))
+ {
+ RuntimeAssemblyName redirectedAssemblyName = typeForwarder.Scope.ToRuntimeAssemblyName(reader);
+ AssemblyQualifiedTypeName redirectedTypeName = new AssemblyQualifiedTypeName(this, redirectedAssemblyName);
+ return redirectedTypeName.TryResolve(reflectionDomain, null, /*ignoreCase: */false, out result);
+ }
+ }
+ }
+
+ {
+ String typeName = this.ToString();
+ String message = SR.Format(SR.TypeLoad_TypeNotFound, typeName, currentAssembly.FullName);
+ return ReflectionCoreNonPortable.CreateTypeLoadException(message, typeName);
+ }
+ }
+
+ private Exception TryResolveCaseInsensitive(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, out RuntimeType result)
+ {
+ String fullName = this.ToString().ToLower();
+
+ LowLevelDictionary<String, QHandle> dict = GetCaseInsensitiveTypeDictionary(currentAssembly);
+ QHandle qualifiedHandle;
+ if (!dict.TryGetValue(fullName, out qualifiedHandle))
+ {
+ result = null;
+ return new TypeLoadException(SR.Format(SR.TypeLoad_TypeNotFound, this.ToString(), currentAssembly.FullName));
+ }
+
+ MetadataReader reader = qualifiedHandle.Reader;
+ Handle typeDefOrForwarderHandle = qualifiedHandle.Handle;
+
+ HandleType handleType = typeDefOrForwarderHandle.HandleType;
+ switch (handleType)
+ {
+ case HandleType.TypeDefinition:
+ {
+ TypeDefinitionHandle typeDefinitionHandle = typeDefOrForwarderHandle.ToTypeDefinitionHandle(reader);
+ result = reflectionDomain.ResolveTypeDefinition(reader, typeDefinitionHandle);
+ return null;
+ }
+ case HandleType.TypeForwarder:
+ {
+ TypeForwarder typeForwarder = typeDefOrForwarderHandle.ToTypeForwarderHandle(reader).GetTypeForwarder(reader);
+ ScopeReferenceHandle destinationScope = typeForwarder.Scope;
+ RuntimeAssemblyName destinationAssemblyName = destinationScope.ToRuntimeAssemblyName(reader);
+ RuntimeAssembly destinationAssembly;
+ Exception exception = RuntimeAssembly.TryGetRuntimeAssembly(reflectionDomain, destinationAssemblyName, out destinationAssembly);
+ if (exception != null)
+ {
+ result = null;
+ return exception;
+ }
+ return TryResolveCaseInsensitive(reflectionDomain, destinationAssembly, out result);
+ }
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+
+ private static LowLevelDictionary<String, QHandle> CreateCaseInsensitiveTypeDictionary(RuntimeAssembly assembly)
+ {
+ //
+ // Collect all of the *non-nested* types and type-forwards.
+ //
+ // The keys are full typenames in lower-cased form.
+ // The value is a tuple containing either a TypeDefinitionHandle or TypeForwarderHandle and the associated Reader
+ // for that handle.
+ //
+ // We do not store nested types here. The container type is resolved and chosen first, then the nested type chosen from
+ // that. If we chose the wrong container type and fail the match as a result, that's too bad. (The desktop CLR has the
+ // same issue.)
+ //
+ ReflectionDomain reflectionDomain = assembly.ReflectionDomain;
+ LowLevelDictionary<String, QHandle> dict = new LowLevelDictionary<string, QHandle>();
+
+ foreach (QScopeDefinition scope in assembly.AllScopes)
+ {
+ MetadataReader reader = scope.Reader;
+ ScopeDefinition scopeDefinition = scope.ScopeDefinition;
+ IEnumerable<NamespaceDefinitionHandle> topLevelNamespaceHandles = new NamespaceDefinitionHandle[] { scopeDefinition.RootNamespaceDefinition };
+ IEnumerable<NamespaceDefinitionHandle> allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles);
+ foreach (NamespaceDefinitionHandle namespaceHandle in allNamespaceHandles)
+ {
+ String ns = namespaceHandle.ToNamespaceName(reader);
+ if (ns.Length != 0)
+ ns = ns + ".";
+ ns = ns.ToLower();
+
+ NamespaceDefinition namespaceDefinition = namespaceHandle.GetNamespaceDefinition(reader);
+ foreach (TypeDefinitionHandle typeDefinitionHandle in namespaceDefinition.TypeDefinitions)
+ {
+ String fullName = ns + typeDefinitionHandle.GetTypeDefinition(reader).Name.GetString(reader).ToLower();
+ QHandle existingValue;
+ if (!dict.TryGetValue(fullName, out existingValue))
+ {
+ dict.Add(fullName, new QHandle(reader, typeDefinitionHandle));
+ }
+ }
+
+ foreach (TypeForwarderHandle typeForwarderHandle in namespaceDefinition.TypeForwarders)
+ {
+ String fullName = ns + typeForwarderHandle.GetTypeForwarder(reader).Name.GetString(reader).ToLower();
+ QHandle existingValue;
+ if (!dict.TryGetValue(fullName, out existingValue))
+ {
+ dict.Add(fullName, new QHandle(reader, typeForwarderHandle));
+ }
+ }
+ }
+ }
+
+ return dict;
+ }
+
+ private String _name;
+ private String[] _namespaceParts;
+ }
+
+ //
+ // A nested type. The Name is the simple name of the type (not including any portion of its declaring type name.
+ //
+ internal sealed class NestedTypeName : NamedTypeName
+ {
+ public NestedTypeName(String name, NamedTypeName declaringType)
+ {
+ Name = name;
+ DeclaringType = declaringType;
+ }
+
+ public String Name { get; private set; }
+ public NamedTypeName DeclaringType { get; private set; }
+
+ public sealed override String ToString()
+ {
+ return DeclaringType + "+" + Name;
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ RuntimeType declaringType;
+ Exception typeLoadException = DeclaringType.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out declaringType);
+ if (typeLoadException != null)
+ return typeLoadException;
+ TypeInfo nestedTypeInfo = FindDeclaredNestedType(declaringType.GetTypeInfo(), Name, ignoreCase);
+ if (nestedTypeInfo == null)
+ return new TypeLoadException(SR.Format(SR.TypeLoad_TypeNotFound, declaringType.FullName + "+" + Name, currentAssembly.FullName));
+ result = (RuntimeType)(nestedTypeInfo.AsType());
+ return null;
+ }
+
+ private TypeInfo FindDeclaredNestedType(TypeInfo declaringTypeInfo, String name, bool ignoreCase)
+ {
+ TypeInfo nestedType = declaringTypeInfo.GetDeclaredNestedType(name);
+ if (nestedType != null)
+ return nestedType;
+ if (!ignoreCase)
+ return null;
+
+ //
+ // Desktop compat note: If there is more than one nested type that matches the name in a case-blind match,
+ // we might not return the same one that the desktop returns. The actual selection method is influenced both by the type's
+ // placement in the IL and the implementation details of the CLR's internal hashtables so it would be very
+ // hard to replicate here.
+ //
+ // Desktop compat note #2: Case-insensitive lookups: If we don't find a match, we do *not* go back and search
+ // other declaring types that might match the case-insensitive search and contain the nested type being sought.
+ // Though this is somewhat unsatisfactory, the desktop CLR has the same limitation.
+ //
+ foreach (TypeInfo candidate in declaringTypeInfo.DeclaredNestedTypes)
+ {
+ String candidateName = candidate.Name;
+ if (name.Equals(candidateName, StringComparison.OrdinalIgnoreCase))
+ return candidate;
+ }
+ return null;
+ }
+ }
+
+ //
+ // Abstract base for array, byref and pointer type names.
+ //
+ internal abstract class HasElementTypeName : NonQualifiedTypeName
+ {
+ public HasElementTypeName(TypeName elementTypeName)
+ {
+ ElementTypeName = elementTypeName;
+ }
+
+ public TypeName ElementTypeName { get; private set; }
+ }
+
+ //
+ // A single-dimensional zero-lower-bound array type name.
+ //
+ internal sealed class ArrayTypeName : HasElementTypeName
+ {
+ public ArrayTypeName(TypeName elementTypeName)
+ : base(elementTypeName)
+ {
+ }
+
+ public sealed override String ToString()
+ {
+ return ElementTypeName + "[]";
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ RuntimeType elementType;
+ Exception typeLoadException = ElementTypeName.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out elementType);
+ if (typeLoadException != null)
+ return typeLoadException;
+ result = ReflectionCoreNonPortable.GetArrayType(elementType);
+ return null;
+ }
+ }
+
+ //
+ // A multidim array type name.
+ //
+ internal sealed class MultiDimArrayTypeName : HasElementTypeName
+ {
+ public MultiDimArrayTypeName(TypeName elementTypeName, int rank)
+ : base(elementTypeName)
+ {
+ _rank = rank;
+ }
+
+ public sealed override String ToString()
+ {
+ return ElementTypeName + "[" + (_rank == 1 ? "*" : new String(',', _rank - 1)) + "]";
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ RuntimeType elementType;
+ Exception typeLoadException = ElementTypeName.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out elementType);
+ if (typeLoadException != null)
+ return typeLoadException;
+ result = ReflectionCoreNonPortable.GetMultiDimArrayType(elementType, _rank);
+ return null;
+ }
+
+ private int _rank;
+ }
+
+ //
+ // A byref type.
+ //
+ internal sealed class ByRefTypeName : HasElementTypeName
+ {
+ public ByRefTypeName(TypeName elementTypeName)
+ : base(elementTypeName)
+ {
+ }
+
+ public sealed override String ToString()
+ {
+ return ElementTypeName + "&";
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ RuntimeType elementType;
+ Exception typeLoadException = ElementTypeName.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out elementType);
+ if (typeLoadException != null)
+ return typeLoadException;
+ result = ReflectionCoreNonPortable.GetByRefType(elementType);
+ return null;
+ }
+ }
+
+ //
+ // A pointer type.
+ //
+ internal sealed class PointerTypeName : HasElementTypeName
+ {
+ public PointerTypeName(TypeName elementTypeName)
+ : base(elementTypeName)
+ {
+ }
+
+ public sealed override String ToString()
+ {
+ return ElementTypeName + "*";
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ RuntimeType elementType;
+ Exception typeLoadException = ElementTypeName.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out elementType);
+ if (typeLoadException != null)
+ return typeLoadException;
+ result = ReflectionCoreNonPortable.GetPointerType(elementType);
+ return null;
+ }
+ }
+
+ //
+ // A constructed generic type.
+ //
+ internal sealed class ConstructedGenericTypeName : NonQualifiedTypeName
+ {
+ public ConstructedGenericTypeName(NamedTypeName genericType, IEnumerable<TypeName> genericArguments)
+ {
+ GenericType = genericType;
+ GenericArguments = genericArguments;
+ }
+
+ public NamedTypeName GenericType { get; private set; }
+ public IEnumerable<TypeName> GenericArguments { get; private set; }
+
+ public sealed override String ToString()
+ {
+ String s = GenericType.ToString();
+ s += "[";
+ String sep = "";
+ foreach (TypeName genericTypeArgument in GenericArguments)
+ {
+ s += sep;
+ sep = ",";
+ AssemblyQualifiedTypeName assemblyQualifiedTypeArgument = genericTypeArgument as AssemblyQualifiedTypeName;
+ if (assemblyQualifiedTypeArgument == null || assemblyQualifiedTypeArgument.AssemblyName == null)
+ s += genericTypeArgument.ToString();
+ else
+ s += "[" + genericTypeArgument.ToString() + "]";
+ }
+ s += "]";
+ return s;
+ }
+
+ public sealed override Exception TryResolve(ReflectionDomain reflectionDomain, RuntimeAssembly currentAssembly, bool ignoreCase, out RuntimeType result)
+ {
+ result = null;
+ RuntimeType genericType;
+ Exception typeLoadException = GenericType.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out genericType);
+ if (typeLoadException != null)
+ return typeLoadException;
+ LowLevelList<RuntimeType> genericTypeArguments = new LowLevelList<RuntimeType>();
+ foreach (TypeName genericTypeArgumentName in GenericArguments)
+ {
+ RuntimeType genericTypeArgument;
+ typeLoadException = genericTypeArgumentName.TryResolve(reflectionDomain, currentAssembly, ignoreCase, out genericTypeArgument);
+ if (typeLoadException != null)
+ return typeLoadException;
+ genericTypeArguments.Add(genericTypeArgument);
+ }
+ result = ReflectionCoreNonPortable.GetConstructedGenericType(genericType, genericTypeArguments.ToArray());
+ return null;
+ }
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs
new file mode 100644
index 000000000..e1ab5e4af
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs
@@ -0,0 +1,210 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Diagnostics;
+using global::System.Collections;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.Assemblies;
+
+namespace System.Reflection.Runtime.TypeParsing
+{
+ //
+ // Parser for type names passed to GetType() apis.
+ //
+ internal sealed class TypeParser
+ {
+ //
+ // Parses a typename. The typename may be optionally postpended with a "," followed by a legal assembly name.
+ //
+ public static AssemblyQualifiedTypeName ParseAssemblyQualifiedTypeName(String s)
+ {
+ // Desktop compat: a whitespace-only "typename" qualified by an assembly name throws an ArgumentException rather than
+ // a TypeLoadException.
+ int idx = 0;
+ while (idx < s.Length && Char.IsWhiteSpace(s[idx]))
+ {
+ idx++;
+ }
+ if (idx < s.Length && s[idx] == ',')
+ throw new ArgumentException(SR.Arg_TypeLoadNullStr);
+
+ try
+ {
+ TypeParser parser = new TypeParser(s);
+ NonQualifiedTypeName typeName = parser.ParseNonQualifiedTypeName();
+ TokenType token = parser._lexer.GetNextToken();
+ if (token == TokenType.End)
+ return new AssemblyQualifiedTypeName(typeName, null);
+ if (token == TokenType.Comma)
+ {
+ RuntimeAssemblyName assemblyName = parser._lexer.GetNextAssemblyName();
+ token = parser._lexer.Peek;
+ if (token != TokenType.End)
+ throw new ArgumentException();
+ return new AssemblyQualifiedTypeName(typeName, assemblyName);
+ }
+ throw new ArgumentException();
+ }
+ catch (TypeLexer.IllegalEscapeSequenceException)
+ {
+ // Emulates a CLR4.5 bug that causes any string that contains an illegal escape sequence to be parsed as the empty string.
+ return ParseAssemblyQualifiedTypeName(String.Empty);
+ }
+ }
+
+ private TypeParser(String s)
+ {
+ _lexer = new TypeLexer(s);
+ }
+
+
+ //
+ // Parses a type name without any assembly name qualification.
+ //
+ private NonQualifiedTypeName ParseNonQualifiedTypeName()
+ {
+ // Parse the named type or constructed generic type part first.
+ NonQualifiedTypeName typeName = ParseNamedOrConstructedGenericTypeName();
+
+ // Iterate through any "has-element" qualifiers ([], &, *).
+ for (; ;)
+ {
+ TokenType token = _lexer.Peek;
+ if (token == TokenType.End)
+ break;
+ if (token == TokenType.Asterisk)
+ {
+ _lexer.Skip();
+ typeName = new PointerTypeName(typeName);
+ }
+ else if (token == TokenType.Ampersand)
+ {
+ _lexer.Skip();
+ typeName = new ByRefTypeName(typeName);
+ }
+ else if (token == TokenType.OpenSqBracket)
+ {
+ _lexer.Skip();
+ token = _lexer.GetNextToken();
+ if (token == TokenType.Asterisk)
+ {
+ typeName = new MultiDimArrayTypeName(typeName, 1);
+ token = _lexer.GetNextToken();
+ }
+ else
+ {
+ int rank = 1;
+ while (token == TokenType.Comma)
+ {
+ token = _lexer.GetNextToken();
+ rank++;
+ }
+ if (rank == 1)
+ typeName = new ArrayTypeName(typeName);
+ else
+ typeName = new MultiDimArrayTypeName(typeName, rank);
+ }
+ if (token != TokenType.CloseSqBracket)
+ throw new ArgumentException();
+ }
+ else
+ {
+ break;
+ }
+ }
+ return typeName;
+ }
+
+ //
+ // Foo or Foo+Inner or Foo[String] or Foo+Inner[String]
+ //
+ private NonQualifiedTypeName ParseNamedOrConstructedGenericTypeName()
+ {
+ NamedTypeName namedType = ParseNamedTypeName();
+ // Because "[" is used both for generic arguments and array indexes, we must peek two characters deep.
+ if (!(_lexer.Peek == TokenType.OpenSqBracket && (_lexer.PeekSecond == TokenType.Other || _lexer.PeekSecond == TokenType.OpenSqBracket)))
+ return namedType;
+ else
+ {
+ _lexer.Skip();
+ LowLevelListWithIList<TypeName> genericTypeArguments = new LowLevelListWithIList<TypeName>();
+ for (; ;)
+ {
+ TypeName genericTypeArgument = ParseGenericTypeArgument();
+ genericTypeArguments.Add(genericTypeArgument);
+ TokenType token = _lexer.GetNextToken();
+ if (token == TokenType.CloseSqBracket)
+ break;
+ if (token != TokenType.Comma)
+ throw new ArgumentException();
+ }
+
+ return new ConstructedGenericTypeName(namedType, genericTypeArguments);
+ }
+ }
+
+ //
+ // Foo or Foo+Inner
+ //
+ private NamedTypeName ParseNamedTypeName()
+ {
+ NamedTypeName namedType = ParseNamespaceTypeName();
+ while (_lexer.Peek == TokenType.Plus)
+ {
+ _lexer.Skip();
+ String nestedTypeName = _lexer.GetNextIdentifier();
+ namedType = new NestedTypeName(nestedTypeName, namedType);
+ }
+ return namedType;
+ }
+
+ //
+ // Non-nested named type.
+ //
+ private NamespaceTypeName ParseNamespaceTypeName()
+ {
+ String fullName = _lexer.GetNextIdentifier();
+ String[] parts = fullName.Split('.');
+ int numNamespaceParts = parts.Length - 1;
+ String[] namespaceParts = new String[numNamespaceParts];
+ for (int i = 0; i < numNamespaceParts; i++)
+ namespaceParts[numNamespaceParts - i - 1] = parts[i];
+ String name = parts[numNamespaceParts];
+ return new NamespaceTypeName(namespaceParts, name);
+ }
+
+ //
+ // Parse a generic argument. In particular, generic arguments can take the special form [<typename>,<assemblyname>].
+ //
+ private TypeName ParseGenericTypeArgument()
+ {
+ TokenType token = _lexer.GetNextToken();
+ if (token == TokenType.Other)
+ {
+ NonQualifiedTypeName nonQualifiedTypeName = ParseNonQualifiedTypeName();
+ return new AssemblyQualifiedTypeName(nonQualifiedTypeName, null);
+ }
+ else if (token == TokenType.OpenSqBracket)
+ {
+ RuntimeAssemblyName assemblyName = null;
+ NonQualifiedTypeName typeName = ParseNonQualifiedTypeName();
+ token = _lexer.GetNextToken();
+ if (token == TokenType.Comma)
+ {
+ assemblyName = _lexer.GetNextEmbeddedAssemblyName();
+ token = _lexer.GetNextToken();
+ }
+ if (token != TokenType.CloseSqBracket)
+ throw new ArgumentException();
+ return new AssemblyQualifiedTypeName(typeName, assemblyName);
+ }
+ else
+ throw new ArgumentException();
+ }
+
+
+ private TypeLexer _lexer;
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterType.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterType.cs
new file mode 100644
index 000000000..3693ceec3
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterType.cs
@@ -0,0 +1,152 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.Types
+{
+ //
+ // Abstract base class for the runtime's implementation of System.Type for generic parameters (both type variables and method variables.)
+ //
+ // - Generic parameters never have EETypes so this is the only class that implements them.
+ //
+ internal abstract class RuntimeGenericParameterType : RuntimeType
+ {
+ internal RuntimeGenericParameterType(MetadataReader reader, GenericParameterHandle genericParameterHandle)
+ {
+ _reader = reader;
+ _genericParameterHandle = genericParameterHandle;
+ _genericParameter = _genericParameterHandle.GetGenericParameter(_reader);
+ _position = _genericParameter.Number;
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ return InternalIsEqual(obj); // Do not change this - see comments in RuntimeType.cs regarding Equals()
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _genericParameterHandle.GetHashCode();
+ }
+
+ public abstract override Type DeclaringType { get; }
+
+ public sealed override String FullName
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public sealed override int GenericParameterPosition
+ {
+ get
+ {
+ return _position;
+ }
+ }
+
+ public sealed override bool IsGenericParameter
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public sealed override String Namespace
+ {
+ get
+ {
+ return DeclaringType.Namespace;
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ return Name;
+ }
+
+ public sealed override String InternalGetNameIfAvailable(ref RuntimeType rootCauseForFailure)
+ {
+ if (_genericParameter.Name.IsNull(_reader))
+ return String.Empty;
+ return _genericParameter.Name.GetString(_reader);
+ }
+
+ public sealed override String InternalFullNameOfAssembly
+ {
+ get
+ {
+ Debug.Assert(false, "Why are you bothering to call me when my FullName is null?");
+ return null;
+ }
+ }
+
+ //
+ // Pay-for-play safe implementation of TypeInfo.ContainsGenericParameters()
+ //
+ public sealed override bool InternalIsOpen
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ internal GenericParameterAttributes GenericParameterAttributes
+ {
+ get
+ {
+ return _genericParameter.Flags;
+ }
+ }
+
+ internal MetadataReader Reader
+ {
+ get
+ {
+ return _reader;
+ }
+ }
+
+ internal GenericParameterHandle GenericParameterHandle
+ {
+ get
+ {
+ return _genericParameterHandle;
+ }
+ }
+
+ internal abstract RuntimeMethodInfo DeclaringMethod { get; }
+
+ internal abstract TypeContext TypeContext { get; }
+
+ internal IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return RuntimeCustomAttributeData.GetCustomAttributes(this.GetReflectionDomain(), _reader, _genericParameter.CustomAttributes);
+ }
+ }
+
+ private MetadataReader _reader;
+ private GenericParameterHandle _genericParameterHandle;
+ private GenericParameter _genericParameter;
+
+ private int _position;
+ }
+}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForMethods.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForMethods.cs
new file mode 100644
index 000000000..337481217
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForMethods.cs
@@ -0,0 +1,156 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Collections.Concurrent;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.Types
+{
+ //
+ // The runtime's implementation of System.Type for generic parameters for methods.
+ //
+
+ internal sealed class RuntimeGenericParameterTypeForMethods : RuntimeGenericParameterType, IKeyedItem<RuntimeGenericParameterTypeForMethods.UnificationKey>
+ {
+ internal RuntimeGenericParameterTypeForMethods(MetadataReader reader, GenericParameterHandle genericParameterHandle, RuntimeNamedMethodInfo declaringRuntimeNamedMethodInfo)
+ : base(reader, genericParameterHandle)
+ {
+ _declaringRuntimeNamedMethodInfo = declaringRuntimeNamedMethodInfo;
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ return _declaringRuntimeNamedMethodInfo.DeclaringType;
+ }
+ }
+
+
+
+ //
+ // Implements IKeyedItem.PrepareKey.
+ //
+ // This method is the keyed item's chance to do any lazy evaluation needed to produce the key quickly.
+ // Concurrent unifiers are guaranteed to invoke this method at least once and wait for it
+ // to complete before invoking the Key property. The unifier lock is NOT held across the call.
+ //
+ // PrepareKey() must be idempodent and thread-safe. It may be invoked multiple times and concurrently.
+ //
+ public void PrepareKey()
+ {
+ }
+
+ //
+ // Implements IKeyedItem.Key.
+ //
+ // Produce the key. This is a high-traffic property and is called while the hash table's lock is held. Thus, it should
+ // return a precomputed stored value and refrain from invoking other methods. If the keyed item wishes to
+ // do lazy evaluation of the key, it should do so in the PrepareKey() method.
+ //
+ public RuntimeGenericParameterTypeForMethods.UnificationKey Key
+ {
+ get
+ {
+ return new UnificationKey(_declaringRuntimeNamedMethodInfo, this.Reader, this.GenericParameterHandle);
+ }
+ }
+
+ internal sealed override RuntimeMethodInfo DeclaringMethod
+ {
+ get
+ {
+ return _declaringRuntimeNamedMethodInfo;
+ }
+ }
+
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ TypeContext typeContext = this.DeclaringType.GetRuntimeTypeInfo<RuntimeTypeInfo>().TypeContext;
+ return new TypeContext(typeContext.GenericTypeArguments, _declaringRuntimeNamedMethodInfo.RuntimeGenericArgumentsOrParameters);
+ }
+ }
+
+ private RuntimeNamedMethodInfo _declaringRuntimeNamedMethodInfo;
+
+
+ //
+ // Key for unification.
+ //
+ internal struct UnificationKey : IEquatable<UnificationKey>
+ {
+ public UnificationKey(RuntimeNamedMethodInfo methodOwner, MetadataReader reader, GenericParameterHandle genericParameterHandle)
+ {
+ _methodOwner = methodOwner;
+ _genericParameterHandle = genericParameterHandle;
+ _reader = reader;
+ }
+
+ public RuntimeNamedMethodInfo MethodOwner
+ {
+ get
+ {
+ return _methodOwner;
+ }
+ }
+
+ public MetadataReader Reader
+ {
+ get
+ {
+ return _reader;
+ }
+ }
+
+ public GenericParameterHandle GenericParameterHandle
+ {
+ get
+ {
+ return _genericParameterHandle;
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is UnificationKey))
+ return false;
+ return Equals((UnificationKey)obj);
+ }
+
+ public bool Equals(UnificationKey other)
+ {
+ if (!(this._genericParameterHandle.Equals(other._genericParameterHandle)))
+ return false;
+ if (!(this._reader == other._reader))
+ return false;
+ if (!this._methodOwner.Equals(other._methodOwner))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return this._genericParameterHandle.GetHashCode();
+ }
+
+ private RuntimeNamedMethodInfo _methodOwner;
+ private MetadataReader _reader;
+ private GenericParameterHandle _genericParameterHandle;
+ }
+ }
+}
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForTypes.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForTypes.cs
new file mode 100644
index 000000000..8cf63cb14
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeGenericParameterTypeForTypes.cs
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+using global::System.Reflection.Runtime.MethodInfos;
+using global::System.Reflection.Runtime.CustomAttributes;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.Types
+{
+ //
+ // The runtime's implementation of System.Type for generic parameters for types (not methods.)
+ //
+
+ internal sealed class RuntimeGenericParameterTypeForTypes : RuntimeGenericParameterType
+ {
+ internal RuntimeGenericParameterTypeForTypes(MetadataReader reader, GenericParameterHandle genericParameterHandle, RuntimeNamedTypeInfo declaringRuntimeNamedTypeInfo)
+ : base(reader, genericParameterHandle)
+ {
+ _declaringRuntimeNamedTypeInfo = declaringRuntimeNamedTypeInfo;
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ return _declaringRuntimeNamedTypeInfo.AsType();
+ }
+ }
+
+ internal sealed override RuntimeMethodInfo DeclaringMethod
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ internal sealed override TypeContext TypeContext
+ {
+ get
+ {
+ return new TypeContext(_declaringRuntimeNamedTypeInfo.RuntimeGenericTypeParameters, null);
+ }
+ }
+
+ private RuntimeNamedTypeInfo _declaringRuntimeNamedTypeInfo;
+
+
+ //
+ // Key for unification.
+ //
+ internal struct UnificationKey : IEquatable<UnificationKey>
+ {
+ public UnificationKey(MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle, GenericParameterHandle genericParameterHandle)
+ {
+ _reader = reader;
+ _typeDefinitionHandle = typeDefinitionHandle;
+ _genericParameterHandle = genericParameterHandle;
+ }
+
+ public MetadataReader Reader
+ {
+ get
+ {
+ return _reader;
+ }
+ }
+
+ public TypeDefinitionHandle TypeDefinitionHandle
+ {
+ get
+ {
+ return _typeDefinitionHandle;
+ }
+ }
+
+ public GenericParameterHandle GenericParameterHandle
+ {
+ get
+ {
+ return _genericParameterHandle;
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is UnificationKey))
+ return false;
+ return Equals((UnificationKey)obj);
+ }
+
+ public bool Equals(UnificationKey other)
+ {
+ if (!this._typeDefinitionHandle.Equals(other._typeDefinitionHandle))
+ return false;
+ if (!(this._reader == other._reader))
+ return false;
+ if (!(this._genericParameterHandle.Equals(other._genericParameterHandle)))
+ return false;
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return this._typeDefinitionHandle.GetHashCode();
+ }
+
+ private MetadataReader _reader;
+ private TypeDefinitionHandle _typeDefinitionHandle;
+ private GenericParameterHandle _genericParameterHandle;
+ }
+ }
+}
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeInspectionOnlyNamedType.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeInspectionOnlyNamedType.cs
new file mode 100644
index 000000000..b6b8a8293
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/RuntimeInspectionOnlyNamedType.cs
@@ -0,0 +1,197 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Linq;
+using global::System.Text;
+using global::System.Threading;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+using global::System.Reflection.Runtime.TypeInfos;
+
+using global::Internal.Reflection.Core;
+using global::Internal.Reflection.Core.Execution;
+using global::Internal.Reflection.Core.NonPortable;
+using Internal.Reflection.Tracing;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.Types
+{
+ //
+ // The runtime's implementation of Types for named types (i.e. types with a TypeDefinitionHandle.)
+ //
+ internal partial class RuntimeInspectionOnlyNamedType : RuntimeType
+ {
+ protected RuntimeInspectionOnlyNamedType(MetadataReader reader, TypeDefinitionHandle typeDefinitionHandle)
+ : base()
+ {
+#if DEBUG
+ if (!(this.InternalViolatesTypeIdentityRules))
+ {
+ RuntimeTypeHandle runtimeTypeHandle;
+ if (ReflectionCoreExecution.ExecutionEnvironment.TryGetNamedTypeForMetadata(reader, typeDefinitionHandle, out runtimeTypeHandle))
+ Debug.Assert(false, "Type identity violation: You must use a RuntimeEENamedType to represent this type as RH has generated an EEType for it.");
+ }
+#endif
+ _reader = reader;
+ _typeDefinitionHandle = typeDefinitionHandle;
+ _typeDefinition = _typeDefinitionHandle.GetTypeDefinition(_reader);
+ }
+
+ public sealed override bool Equals(Object obj)
+ {
+ return InternalIsEqual(obj); // Do not change this - see comments in RuntimeType.cs regarding Equals()
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return _typeDefinitionHandle.GetHashCode();
+ }
+
+ public sealed override Type DeclaringType
+ {
+ get
+ {
+ RuntimeType declaringType = null;
+ TypeDefinitionHandle enclosingTypeDefHandle = _typeDefinition.EnclosingType;
+ if (!enclosingTypeDefHandle.IsNull(_reader))
+ {
+ declaringType = this.GetReflectionDomain().ResolveTypeDefinition(_reader, enclosingTypeDefHandle);
+ }
+ return declaringType;
+ }
+ }
+
+ public sealed override Type GetGenericTypeDefinition()
+ {
+ if (_typeDefinition.GenericParameters.GetEnumerator().MoveNext())
+ return this;
+ return base.GetGenericTypeDefinition();
+ }
+
+ public sealed override String Namespace
+ {
+ get
+ {
+ if (ReflectionTrace.Enabled)
+ ReflectionTrace.Type_Namespace(this);
+
+ return EscapeIdentifier(NamespaceChain.NameSpace);
+ }
+ }
+
+ public sealed override String ToString()
+ {
+ StringBuilder sb = null;
+
+ foreach (GenericParameterHandle genericParameterHandle in _typeDefinition.GenericParameters)
+ {
+ if (sb == null)
+ {
+ sb = new StringBuilder(this.FullName);
+ sb.Append('[');
+ }
+ else
+ {
+ sb.Append(',');
+ }
+
+ sb.Append(genericParameterHandle.GetGenericParameter(_reader).Name.GetString(_reader));
+ }
+
+ if (sb == null)
+ {
+ return this.FullName;
+ }
+ else
+ {
+ return sb.Append(']').ToString();
+ }
+ }
+
+ public sealed override String InternalGetNameIfAvailable(ref RuntimeType rootCauseForFailure)
+ {
+ ConstantStringValueHandle nameHandle = _typeDefinition.Name;
+ String name = nameHandle.GetString(_reader);
+
+ return EscapeIdentifier(name);
+ }
+
+ public sealed override String InternalFullNameOfAssembly
+ {
+ get
+ {
+ NamespaceChain namespaceChain = this.NamespaceChain;
+ ScopeDefinitionHandle scopeDefinitionHandle = namespaceChain.DefiningScope;
+ return scopeDefinitionHandle.ToRuntimeAssemblyName(_reader).FullName;
+ }
+ }
+
+ public sealed override bool InternalIsGenericTypeDefinition
+ {
+ get
+ {
+ return _typeDefinition.GenericParameters.GetEnumerator().MoveNext();
+ }
+ }
+
+ //
+ // Pay-for-play safe implementation of TypeInfo.ContainsGenericParameters()
+ //
+ public sealed override bool InternalIsOpen
+ {
+ get
+ {
+ return this.InternalIsGenericTypeDefinition;
+ }
+ }
+
+ internal RuntimeTypeInfo GetInspectionOnlyNamedRuntimeTypeInfo()
+ {
+ return RuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(_reader, _typeDefinitionHandle);
+ }
+
+ private MetadataReader _reader;
+ private TypeDefinitionHandle _typeDefinitionHandle;
+ private TypeDefinition _typeDefinition;
+
+ private NamespaceChain NamespaceChain
+ {
+ get
+ {
+ if (_lazyNamespaceChain == null)
+ _lazyNamespaceChain = new NamespaceChain(_reader, _typeDefinition.NamespaceDefinition);
+ return _lazyNamespaceChain;
+ }
+ }
+
+ private volatile NamespaceChain _lazyNamespaceChain;
+
+ private static char[] charsToEscape = new char[] { '\\', '[', ']', '+', '*', '&', ',' };
+ // Escape identifiers as described in "Specifying Fully Qualified Type Names" on msdn.
+ // Current link is http://msdn.microsoft.com/en-us/library/yfsftwz6(v=vs.110).aspx
+ private static string EscapeIdentifier(string identifier)
+ {
+ // Some characters in a type name need to be escaped
+ if (identifier != null && identifier.IndexOfAny(charsToEscape) != -1)
+ {
+ StringBuilder sbEscapedName = new StringBuilder(identifier);
+ sbEscapedName.Replace("\\", "\\\\");
+ sbEscapedName.Replace("+", "\\+");
+ sbEscapedName.Replace("[", "\\[");
+ sbEscapedName.Replace("]", "\\]");
+ sbEscapedName.Replace("*", "\\*");
+ sbEscapedName.Replace("&", "\\&");
+ sbEscapedName.Replace(",", "\\,");
+ identifier = sbEscapedName.ToString();
+ }
+ return identifier;
+ }
+ }
+}
+
+
+
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/ShadowRuntimeInspectionOnlyNamedType.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/ShadowRuntimeInspectionOnlyNamedType.cs
new file mode 100644
index 000000000..125152b26
--- /dev/null
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/Types/ShadowRuntimeInspectionOnlyNamedType.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using global::System;
+using global::System.Reflection;
+using global::System.Diagnostics;
+using global::System.Collections.Generic;
+using global::System.Reflection.Runtime.General;
+
+using global::Internal.Reflection.Core.NonPortable;
+
+using global::Internal.Metadata.NativeFormat;
+
+namespace System.Reflection.Runtime.Types
+{
+ //
+ // This is a RuntimeInspectionOnlyNamedType type that's created "behind the scenes" for types that also have EETypes.
+ // The type unification rules dictate that types that have both metadata and EEType be created as RuntimeEENamedTypes
+ // as the public-facing "identity." However, if S.R.R. is loaded and metadata is present, the developer naturally expects the
+ // Type object to be "fully functional." We accomplish this by creating this shadow type on-demand when
+ // a RuntimeEENamedType cannot get what it needs from the raw EEType. In such cases, RuntimeEENamedType delegates
+ // calls to this object.
+ //
+ // ! By necessity, shadow types break the type identity rules - thus, they must NEVER escape out into the wild.
+ //
+ internal sealed class ShadowRuntimeInspectionOnlyNamedType : RuntimeInspectionOnlyNamedType
+ {
+ internal ShadowRuntimeInspectionOnlyNamedType(MetadataReader metadataReader, TypeDefinitionHandle typeDefinitionHandle)
+ : base(metadataReader, typeDefinitionHandle)
+ {
+ }
+
+
+ public sealed override bool InternalViolatesTypeIdentityRules
+ {
+ get
+ {
+ return true;
+ }
+ }
+ }
+}
+