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