1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Reflection; 7 using System.Collections.Generic; 8 using System.Reflection.Runtime.General; 9 using System.Reflection.Runtime.TypeInfos; 10 using System.Reflection.Runtime.TypeInfos.NativeFormat; 11 using System.Reflection.Runtime.Assemblies; 12 using System.Reflection.Runtime.MethodInfos; 13 using System.Reflection.Runtime.MethodInfos.NativeFormat; 14 #if ECMA_METADATA_SUPPORT 15 using System.Reflection.Runtime.TypeInfos.EcmaFormat; 16 using System.Reflection.Runtime.MethodInfos.EcmaFormat; 17 #endif 18 using System.Reflection.Runtime.TypeParsing; 19 using System.Reflection.Runtime.CustomAttributes; 20 using Internal.Metadata.NativeFormat; 21 using Internal.Runtime.Augments; 22 23 namespace Internal.Reflection.Core.Execution 24 { 25 // 26 // This singleton class acts as an entrypoint from System.Private.Reflection.Execution to System.Private.Reflection.Core. 27 // 28 public sealed class ExecutionDomain 29 { ExecutionDomain(ReflectionDomainSetup executionDomainSetup, ExecutionEnvironment executionEnvironment)30 internal ExecutionDomain(ReflectionDomainSetup executionDomainSetup, ExecutionEnvironment executionEnvironment) 31 { 32 ExecutionEnvironment = executionEnvironment; 33 ReflectionDomainSetup = executionDomainSetup; 34 } 35 36 // 37 // Retrieves a type by name. Helper to implement Type.GetType(); 38 // GetType(String typeName, Func<AssemblyName, Assembly> assemblyResolver, Func<Assembly, string, bool, Type> typeResolver, bool throwOnError, bool ignoreCase, IList<string> defaultAssemblyNames)39 public Type GetType(String typeName, Func<AssemblyName, Assembly> assemblyResolver, Func<Assembly, string, bool, Type> typeResolver, bool throwOnError, bool ignoreCase, IList<string> defaultAssemblyNames) 40 { 41 if (typeName == null) 42 throw new ArgumentNullException(); 43 44 if (typeName.Length == 0) 45 { 46 if (throwOnError) 47 throw new TypeLoadException(SR.Arg_TypeLoadNullStr); 48 else 49 return null; 50 } 51 52 TypeName parsedName = TypeParser.ParseAssemblyQualifiedTypeName(typeName, throwOnError: throwOnError); 53 if (parsedName == null) 54 return null; 55 CoreAssemblyResolver coreAssemblyResolver = CreateCoreAssemblyResolver(assemblyResolver); 56 CoreTypeResolver coreTypeResolver = CreateCoreTypeResolver(typeResolver, defaultAssemblyNames, throwOnError: throwOnError, ignoreCase: ignoreCase); 57 GetTypeOptions getTypeOptions = new GetTypeOptions(coreAssemblyResolver, coreTypeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase); 58 59 return parsedName.ResolveType(null, getTypeOptions); 60 } 61 CreateCoreAssemblyResolver(Func<AssemblyName, Assembly> assemblyResolver)62 private static CoreAssemblyResolver CreateCoreAssemblyResolver(Func<AssemblyName, Assembly> assemblyResolver) 63 { 64 if (assemblyResolver == null) 65 { 66 return RuntimeAssembly.GetRuntimeAssemblyIfExists; 67 } 68 else 69 { 70 return delegate (RuntimeAssemblyName runtimeAssemblyName) 71 { 72 AssemblyName assemblyName = runtimeAssemblyName.ToAssemblyName(); 73 Assembly assembly = assemblyResolver(assemblyName); 74 return assembly; 75 }; 76 } 77 } 78 CreateCoreTypeResolver(Func<Assembly, string, bool, Type> typeResolver, IList<string> defaultAssemblyNames, bool throwOnError, bool ignoreCase)79 private static CoreTypeResolver CreateCoreTypeResolver(Func<Assembly, string, bool, Type> typeResolver, IList<string> defaultAssemblyNames, bool throwOnError, bool ignoreCase) 80 { 81 if (typeResolver == null) 82 { 83 return delegate (Assembly containingAssemblyIfAny, string coreTypeName) 84 { 85 if (containingAssemblyIfAny != null) 86 { 87 return containingAssemblyIfAny.GetTypeCore(coreTypeName, ignoreCase: ignoreCase); 88 } 89 else 90 { 91 foreach (string defaultAssemblyName in defaultAssemblyNames) 92 { 93 RuntimeAssemblyName runtimeAssemblyName = AssemblyNameParser.Parse(defaultAssemblyName); 94 RuntimeAssembly defaultAssembly = RuntimeAssembly.GetRuntimeAssemblyIfExists(runtimeAssemblyName); 95 if (defaultAssembly == null) 96 continue; 97 Type resolvedType = defaultAssembly.GetTypeCore(coreTypeName, ignoreCase: ignoreCase); 98 if (resolvedType != null) 99 return resolvedType; 100 } 101 102 if (throwOnError && defaultAssemblyNames.Count > 0) 103 { 104 // Though we don't have to throw a TypeLoadException exception (that's our caller's job), we can throw a more specific exception than he would so just do it. 105 throw Helpers.CreateTypeLoadException(coreTypeName, defaultAssemblyNames[0]); 106 } 107 return null; 108 } 109 }; 110 } 111 else 112 { 113 return delegate (Assembly containingAssemblyIfAny, string coreTypeName) 114 { 115 string escapedName = coreTypeName.EscapeTypeNameIdentifier(); 116 Type type = typeResolver(containingAssemblyIfAny, escapedName, ignoreCase); 117 return type; 118 }; 119 } 120 } 121 122 // 123 // Retrieves the MethodBase for a given method handle. Helper to implement Delegate.GetMethodInfo() 124 // GetMethod(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles)125 public MethodBase GetMethod(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles) 126 { 127 RuntimeTypeInfo contextTypeInfo = declaringTypeHandle.GetTypeForRuntimeTypeHandle(); 128 RuntimeNamedMethodInfo runtimeNamedMethodInfo = null; 129 130 if (methodHandle.IsNativeFormatMetadataBased) 131 { 132 MethodHandle nativeFormatMethodHandle = methodHandle.NativeFormatHandle; 133 NativeFormatRuntimeNamedTypeInfo definingTypeInfo = contextTypeInfo.AnchoringTypeDefinitionForDeclaredMembers.CastToNativeFormatRuntimeNamedTypeInfo(); 134 MetadataReader reader = definingTypeInfo.Reader; 135 if (nativeFormatMethodHandle.IsConstructor(reader)) 136 { 137 return RuntimePlainConstructorInfo<NativeFormatMethodCommon>.GetRuntimePlainConstructorInfo(new NativeFormatMethodCommon(nativeFormatMethodHandle, definingTypeInfo, contextTypeInfo)); 138 } 139 else 140 { 141 // RuntimeMethodHandles always yield methods whose ReflectedType is the DeclaringType. 142 RuntimeTypeInfo reflectedType = contextTypeInfo; 143 runtimeNamedMethodInfo = RuntimeNamedMethodInfo<NativeFormatMethodCommon>.GetRuntimeNamedMethodInfo(new NativeFormatMethodCommon(nativeFormatMethodHandle, definingTypeInfo, contextTypeInfo), reflectedType); 144 } 145 } 146 #if ECMA_METADATA_SUPPORT 147 else 148 { 149 System.Reflection.Metadata.MethodDefinitionHandle ecmaFormatMethodHandle = methodHandle.EcmaFormatHandle; 150 EcmaFormatRuntimeNamedTypeInfo definingEcmaTypeInfo = contextTypeInfo.AnchoringTypeDefinitionForDeclaredMembers.CastToEcmaFormatRuntimeNamedTypeInfo(); 151 System.Reflection.Metadata.MetadataReader reader = definingEcmaTypeInfo.Reader; 152 if (ecmaFormatMethodHandle.IsConstructor(reader)) 153 { 154 return RuntimePlainConstructorInfo<EcmaFormatMethodCommon>.GetRuntimePlainConstructorInfo(new EcmaFormatMethodCommon(ecmaFormatMethodHandle, definingEcmaTypeInfo, contextTypeInfo)); 155 } 156 else 157 { 158 // RuntimeMethodHandles always yield methods whose ReflectedType is the DeclaringType. 159 RuntimeTypeInfo reflectedType = contextTypeInfo; 160 runtimeNamedMethodInfo = RuntimeNamedMethodInfo<EcmaFormatMethodCommon>.GetRuntimeNamedMethodInfo(new EcmaFormatMethodCommon(ecmaFormatMethodHandle, definingEcmaTypeInfo, contextTypeInfo), reflectedType); 161 } 162 } 163 #endif 164 165 if (!runtimeNamedMethodInfo.IsGenericMethod || genericMethodTypeArgumentHandles == null) 166 { 167 return runtimeNamedMethodInfo; 168 } 169 else 170 { 171 RuntimeTypeInfo[] genericTypeArguments = new RuntimeTypeInfo[genericMethodTypeArgumentHandles.Length]; 172 for (int i = 0; i < genericMethodTypeArgumentHandles.Length; i++) 173 { 174 genericTypeArguments[i] = genericMethodTypeArgumentHandles[i].GetTypeForRuntimeTypeHandle(); 175 } 176 return RuntimeConstructedGenericMethodInfo.GetRuntimeConstructedGenericMethodInfo(runtimeNamedMethodInfo, genericTypeArguments); 177 } 178 } 179 180 //======================================================================================= 181 // This group of methods jointly service the Type.GetTypeFromHandle() path. The caller 182 // is responsible for analyzing the RuntimeTypeHandle to figure out which flavor to call. 183 //======================================================================================= GetNamedTypeForHandle(RuntimeTypeHandle typeHandle, bool isGenericTypeDefinition)184 public Type GetNamedTypeForHandle(RuntimeTypeHandle typeHandle, bool isGenericTypeDefinition) 185 { 186 QTypeDefinition qTypeDefinition; 187 188 if (ExecutionEnvironment.TryGetMetadataForNamedType(typeHandle, out qTypeDefinition)) 189 { 190 #if ECMA_METADATA_SUPPORT 191 if (qTypeDefinition.IsNativeFormatMetadataBased) 192 #endif 193 { 194 return qTypeDefinition.NativeFormatHandle.GetNamedType(qTypeDefinition.NativeFormatReader, typeHandle); 195 } 196 #if ECMA_METADATA_SUPPORT 197 else 198 { 199 return System.Reflection.Runtime.TypeInfos.EcmaFormat.EcmaFormatRuntimeNamedTypeInfo.GetRuntimeNamedTypeInfo(qTypeDefinition.EcmaFormatReader, 200 qTypeDefinition.EcmaFormatHandle, 201 typeHandle); 202 } 203 #endif 204 } 205 else 206 { 207 if (ExecutionEnvironment.IsReflectionBlocked(typeHandle)) 208 { 209 return RuntimeBlockedTypeInfo.GetRuntimeBlockedTypeInfo(typeHandle, isGenericTypeDefinition); 210 } 211 else 212 { 213 return RuntimeNoMetadataNamedTypeInfo.GetRuntimeNoMetadataNamedTypeInfo(typeHandle, isGenericTypeDefinition); 214 } 215 } 216 } 217 GetArrayTypeForHandle(RuntimeTypeHandle typeHandle)218 public Type GetArrayTypeForHandle(RuntimeTypeHandle typeHandle) 219 { 220 RuntimeTypeHandle elementTypeHandle; 221 if (!ExecutionEnvironment.TryGetArrayTypeElementType(typeHandle, out elementTypeHandle)) 222 throw CreateMissingMetadataException((Type)null); 223 224 return elementTypeHandle.GetTypeForRuntimeTypeHandle().GetArrayType(typeHandle); 225 } 226 GetMdArrayTypeForHandle(RuntimeTypeHandle typeHandle, int rank)227 public Type GetMdArrayTypeForHandle(RuntimeTypeHandle typeHandle, int rank) 228 { 229 RuntimeTypeHandle elementTypeHandle; 230 if (!ExecutionEnvironment.TryGetArrayTypeElementType(typeHandle, out elementTypeHandle)) 231 throw CreateMissingMetadataException((Type)null); 232 233 return elementTypeHandle.GetTypeForRuntimeTypeHandle().GetMultiDimArrayType(rank, typeHandle); 234 } 235 GetPointerTypeForHandle(RuntimeTypeHandle typeHandle)236 public Type GetPointerTypeForHandle(RuntimeTypeHandle typeHandle) 237 { 238 RuntimeTypeHandle targetTypeHandle; 239 if (!ExecutionEnvironment.TryGetPointerTypeTargetType(typeHandle, out targetTypeHandle)) 240 throw CreateMissingMetadataException((Type)null); 241 242 return targetTypeHandle.GetTypeForRuntimeTypeHandle().GetPointerType(typeHandle); 243 } 244 GetByRefTypeForHandle(RuntimeTypeHandle typeHandle)245 public Type GetByRefTypeForHandle(RuntimeTypeHandle typeHandle) 246 { 247 RuntimeTypeHandle targetTypeHandle; 248 if (!ExecutionEnvironment.TryGetByRefTypeTargetType(typeHandle, out targetTypeHandle)) 249 throw CreateMissingMetadataException((Type)null); 250 251 return targetTypeHandle.GetTypeForRuntimeTypeHandle().GetByRefType(typeHandle); 252 } 253 GetConstructedGenericTypeForHandle(RuntimeTypeHandle typeHandle)254 public Type GetConstructedGenericTypeForHandle(RuntimeTypeHandle typeHandle) 255 { 256 RuntimeTypeHandle genericTypeDefinitionHandle; 257 RuntimeTypeHandle[] genericTypeArgumentHandles; 258 genericTypeDefinitionHandle = RuntimeAugments.GetGenericInstantiation(typeHandle, out genericTypeArgumentHandles); 259 260 // Reflection blocked constructed generic types simply pretend to not be generic 261 // This is reasonable, as the behavior of reflection blocked types is supposed 262 // to be that they expose the minimal information about a type that is necessary 263 // for users of Object.GetType to move from that type to a type that isn't 264 // reflection blocked. By not revealing that reflection blocked types are generic 265 // we are making it appear as if implementation detail types exposed to user code 266 // are all non-generic, which is theoretically possible, and by doing so 267 // we avoid (in all known circumstances) the very complicated case of representing 268 // the interfaces, base types, and generic parameter types of reflection blocked 269 // generic type definitions. 270 if (ExecutionEnvironment.IsReflectionBlocked(genericTypeDefinitionHandle)) 271 { 272 return RuntimeBlockedTypeInfo.GetRuntimeBlockedTypeInfo(typeHandle, isGenericTypeDefinition: false); 273 } 274 275 RuntimeTypeInfo genericTypeDefinition = genericTypeDefinitionHandle.GetTypeForRuntimeTypeHandle(); 276 int count = genericTypeArgumentHandles.Length; 277 RuntimeTypeInfo[] genericTypeArguments = new RuntimeTypeInfo[count]; 278 for (int i = 0; i < count; i++) 279 { 280 genericTypeArguments[i] = genericTypeArgumentHandles[i].GetTypeForRuntimeTypeHandle(); 281 } 282 return genericTypeDefinition.GetConstructedGenericType(genericTypeArguments, typeHandle); 283 } 284 285 //======================================================================================= 286 // MissingMetadataExceptions. 287 //======================================================================================= CreateMissingMetadataException(Type pertainant)288 public Exception CreateMissingMetadataException(Type pertainant) 289 { 290 return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant); 291 } 292 CreateMissingMetadataException(TypeInfo pertainant)293 public Exception CreateMissingMetadataException(TypeInfo pertainant) 294 { 295 return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant); 296 } 297 CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName)298 public Exception CreateMissingMetadataException(TypeInfo pertainant, string nestedTypeName) 299 { 300 return this.ReflectionDomainSetup.CreateMissingMetadataException(pertainant, nestedTypeName); 301 } 302 CreateNonInvokabilityException(MemberInfo pertainant)303 public Exception CreateNonInvokabilityException(MemberInfo pertainant) 304 { 305 return this.ReflectionDomainSetup.CreateNonInvokabilityException(pertainant); 306 } 307 CreateMissingArrayTypeException(Type elementType, bool isMultiDim, int rank)308 public Exception CreateMissingArrayTypeException(Type elementType, bool isMultiDim, int rank) 309 { 310 return ReflectionDomainSetup.CreateMissingArrayTypeException(elementType, isMultiDim, rank); 311 } 312 CreateMissingConstructedGenericTypeException(Type genericTypeDefinition, Type[] genericTypeArguments)313 public Exception CreateMissingConstructedGenericTypeException(Type genericTypeDefinition, Type[] genericTypeArguments) 314 { 315 return ReflectionDomainSetup.CreateMissingConstructedGenericTypeException(genericTypeDefinition, genericTypeArguments); 316 } 317 318 //======================================================================================= 319 // Miscellaneous. 320 //======================================================================================= GetTypeHandleIfAvailable(Type type)321 public RuntimeTypeHandle GetTypeHandleIfAvailable(Type type) 322 { 323 if (!type.IsRuntimeImplemented()) 324 return default(RuntimeTypeHandle); 325 326 RuntimeTypeInfo runtimeType = type.CastToRuntimeTypeInfo(); 327 if (runtimeType == null) 328 return default(RuntimeTypeHandle); 329 return runtimeType.InternalTypeHandleIfAvailable; 330 } 331 SupportsReflection(Type type)332 public bool SupportsReflection(Type type) 333 { 334 if (!type.IsRuntimeImplemented()) 335 return false; 336 337 RuntimeTypeInfo runtimeType = type.CastToRuntimeTypeInfo(); 338 if (null == runtimeType.InternalNameIfAvailable) 339 return false; 340 341 if (ExecutionEnvironment.IsReflectionBlocked(type.TypeHandle)) 342 { 343 // The type is an internal framework type and is blocked from reflection 344 return false; 345 } 346 347 if (runtimeType.InternalFullNameOfAssembly == Internal.Runtime.Augments.RuntimeAugments.HiddenScopeAssemblyName) 348 { 349 // The type is an internal framework type but is reflectable for internal class library use 350 // where we make the type appear in a hidden assembly 351 return false; 352 } 353 354 return true; 355 } 356 357 internal ExecutionEnvironment ExecutionEnvironment { get; } 358 359 internal ReflectionDomainSetup ReflectionDomainSetup { get; } 360 361 internal IEnumerable<Type> PrimitiveTypes => s_primitiveTypes; 362 363 private static readonly Type[] s_primitiveTypes = 364 { 365 CommonRuntimeTypes.Boolean, 366 CommonRuntimeTypes.Char, 367 CommonRuntimeTypes.SByte, 368 CommonRuntimeTypes.Byte, 369 CommonRuntimeTypes.Int16, 370 CommonRuntimeTypes.UInt16, 371 CommonRuntimeTypes.Int32, 372 CommonRuntimeTypes.UInt32, 373 CommonRuntimeTypes.Int64, 374 CommonRuntimeTypes.UInt64, 375 CommonRuntimeTypes.Single, 376 CommonRuntimeTypes.Double, 377 CommonRuntimeTypes.IntPtr, 378 CommonRuntimeTypes.UIntPtr, 379 }; 380 } 381 } 382