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.IO;
6 using System.Collections.Generic;
7 
8 using System.Reflection.Runtime.General;
9 using System.Reflection.Runtime.TypeInfos;
10 using System.Reflection.Runtime.Assemblies;
11 using System.Reflection.Runtime.Dispensers;
12 using System.Reflection.Runtime.PropertyInfos;
13 
14 using Internal.Reflection.Core;
15 using Internal.Reflection.Core.Execution;
16 
17 
18 //=================================================================================================================
19 // This file collects the various chokepoints that create the various Runtime*Info objects. This allows
20 // easy reviewing of the overall caching and unification policy.
21 //
22 // The dispenser functions are defined as static members of the associated Info class. This permits us
23 // to keep the constructors private to ensure that these really are the only ways to obtain these objects.
24 //=================================================================================================================
25 
26 namespace System.Reflection.Runtime.Assemblies
27 {
28     //-----------------------------------------------------------------------------------------------------------
29     // Assemblies (maps 1-1 with a MetadataReader/ScopeDefinitionHandle.
30     //-----------------------------------------------------------------------------------------------------------
31     internal partial class RuntimeAssembly
32     {
33         /// <summary>
34         /// Returns non-null or throws.
35         /// </summary>
GetRuntimeAssembly(RuntimeAssemblyName assemblyRefName)36         internal static RuntimeAssembly GetRuntimeAssembly(RuntimeAssemblyName assemblyRefName)
37         {
38             RuntimeAssembly result;
39             Exception assemblyLoadException = TryGetRuntimeAssembly(assemblyRefName, out result);
40             if (assemblyLoadException != null)
41                 throw assemblyLoadException;
42             return result;
43         }
44 
45         /// <summary>
46         /// Returns non-null or throws.
47         /// </summary>
GetRuntimeAssemblyFromByteArray(byte[] rawAssembly, byte[] pdbSymbolStore)48         internal static RuntimeAssembly GetRuntimeAssemblyFromByteArray(byte[] rawAssembly, byte[] pdbSymbolStore)
49         {
50             AssemblyBinder binder = ReflectionCoreExecution.ExecutionDomain.ReflectionDomainSetup.AssemblyBinder;
51             AssemblyBindResult bindResult;
52             Exception exception;
53             if (!binder.Bind(rawAssembly, pdbSymbolStore, out bindResult, out exception))
54             {
55                 if (exception != null)
56                     throw exception;
57                 else
58                     throw new BadImageFormatException();
59             }
60 
61             RuntimeAssembly result = GetRuntimeAssembly(bindResult);
62             return result;
63         }
64 
65         /// <summary>
66         /// Returns null if no assembly matches the assemblyRefName. Throws for other error cases.
67         /// </summary>
GetRuntimeAssemblyIfExists(RuntimeAssemblyName assemblyRefName)68         internal static RuntimeAssembly GetRuntimeAssemblyIfExists(RuntimeAssemblyName assemblyRefName)
69         {
70             object runtimeAssemblyOrException = s_assemblyRefNameToAssemblyDispenser.GetOrAdd(assemblyRefName);
71             if (runtimeAssemblyOrException is RuntimeAssembly runtimeAssembly)
72                 return runtimeAssembly;
73             return null;
74         }
75 
TryGetRuntimeAssembly(RuntimeAssemblyName assemblyRefName, out RuntimeAssembly result)76         internal static Exception TryGetRuntimeAssembly(RuntimeAssemblyName assemblyRefName, out RuntimeAssembly result)
77         {
78             object runtimeAssemblyOrException = s_assemblyRefNameToAssemblyDispenser.GetOrAdd(assemblyRefName);
79             if (runtimeAssemblyOrException is RuntimeAssembly runtimeAssembly)
80             {
81                 result = runtimeAssembly;
82                 return null;
83             }
84             else
85             {
86                 result = null;
87                 return (Exception)runtimeAssemblyOrException;
88             }
89         }
90 
91         // The "object" here is either a RuntimeAssembly or an Exception.
92         private static readonly Dispenser<RuntimeAssemblyName, object> s_assemblyRefNameToAssemblyDispenser =
93             DispenserFactory.CreateDispenser<RuntimeAssemblyName, object>(
94                 DispenserScenario.AssemblyRefName_Assembly,
95                 delegate (RuntimeAssemblyName assemblyRefName)
96                 {
97                     AssemblyBinder binder = ReflectionCoreExecution.ExecutionDomain.ReflectionDomainSetup.AssemblyBinder;
98                     AssemblyBindResult bindResult;
99                     Exception exception;
100                     if (!binder.Bind(assemblyRefName, out bindResult, out exception))
101                         return exception;
102 
103                     return GetRuntimeAssembly(bindResult);
104                 }
105         );
106 
GetRuntimeAssembly(AssemblyBindResult bindResult)107         private static RuntimeAssembly GetRuntimeAssembly(AssemblyBindResult bindResult)
108         {
109             RuntimeAssembly result = null;
110 
111             GetNativeFormatRuntimeAssembly(bindResult, ref result);
112             if (result != null)
113                 return result;
114 
115             GetEcmaRuntimeAssembly(bindResult, ref result);
116             if (result != null)
117                 return result;
118 
119             throw new PlatformNotSupportedException();
120         }
121 
122         // Use C# partial method feature to avoid complex #if logic, whichever code files are included will drive behavior
GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly)123         static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly);
GetEcmaRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly)124         static partial void GetEcmaRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly);
125     }
126 }
127 
128 namespace System.Reflection.Runtime.MethodInfos
129 {
130     //-----------------------------------------------------------------------------------------------------------
131     // ConstructorInfos
132     //-----------------------------------------------------------------------------------------------------------
133     internal sealed partial class RuntimePlainConstructorInfo<TRuntimeMethodCommon> : RuntimeConstructorInfo
134     {
GetRuntimePlainConstructorInfo(TRuntimeMethodCommon common)135         internal static RuntimePlainConstructorInfo<TRuntimeMethodCommon> GetRuntimePlainConstructorInfo(TRuntimeMethodCommon common)
136         {
137             return new RuntimePlainConstructorInfo<TRuntimeMethodCommon>(common);
138         }
139     }
140 
141     //-----------------------------------------------------------------------------------------------------------
142     // Constructors for array types.
143     //-----------------------------------------------------------------------------------------------------------
144     internal sealed partial class RuntimeSyntheticConstructorInfo : RuntimeConstructorInfo
145     {
GetRuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, InvokerOptions options, CustomMethodInvokerAction action)146         internal static RuntimeSyntheticConstructorInfo GetRuntimeSyntheticConstructorInfo(SyntheticMethodId syntheticMethodId, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, InvokerOptions options, CustomMethodInvokerAction action)
147         {
148             return new RuntimeSyntheticConstructorInfo(syntheticMethodId, declaringType, runtimeParameterTypes, options, action);
149         }
150     }
151 
152     //-----------------------------------------------------------------------------------------------------------
153     // Nullary constructor for types manufactured by Type.GetTypeFromCLSID().
154     //-----------------------------------------------------------------------------------------------------------
155     internal sealed partial class RuntimeCLSIDNullaryConstructorInfo : RuntimeConstructorInfo
156     {
GetRuntimeCLSIDNullaryConstructorInfo(RuntimeCLSIDTypeInfo declaringType)157         internal static RuntimeCLSIDNullaryConstructorInfo GetRuntimeCLSIDNullaryConstructorInfo(RuntimeCLSIDTypeInfo declaringType)
158         {
159             return new RuntimeCLSIDNullaryConstructorInfo(declaringType);
160         }
161     }
162 
163     //-----------------------------------------------------------------------------------------------------------
164     // MethodInfos for method definitions (i.e. Foo.Moo() or Foo.Moo<>() but not Foo.Moo<int>)
165     //-----------------------------------------------------------------------------------------------------------
166     internal sealed partial class RuntimeNamedMethodInfo<TRuntimeMethodCommon>
167     {
GetRuntimeNamedMethodInfo(TRuntimeMethodCommon common, RuntimeTypeInfo reflectedType)168         internal static RuntimeNamedMethodInfo<TRuntimeMethodCommon> GetRuntimeNamedMethodInfo(TRuntimeMethodCommon common, RuntimeTypeInfo reflectedType)
169         {
170             RuntimeNamedMethodInfo<TRuntimeMethodCommon> method = new RuntimeNamedMethodInfo<TRuntimeMethodCommon>(common, reflectedType);
171             method.WithDebugName();
172             return method;
173         }
174     }
175 
176     //-----------------------------------------------------------------------------------------------------------
177     // MethodInfos for constructed generic methods (Foo.Moo<int> but not Foo.Moo<>)
178     //-----------------------------------------------------------------------------------------------------------
179     internal sealed partial class RuntimeConstructedGenericMethodInfo : RuntimeMethodInfo
180     {
GetRuntimeConstructedGenericMethodInfo(RuntimeNamedMethodInfo genericMethodDefinition, RuntimeTypeInfo[] genericTypeArguments)181         internal static RuntimeMethodInfo GetRuntimeConstructedGenericMethodInfo(RuntimeNamedMethodInfo genericMethodDefinition, RuntimeTypeInfo[] genericTypeArguments)
182         {
183             return new RuntimeConstructedGenericMethodInfo(genericMethodDefinition, genericTypeArguments).WithDebugName();
184         }
185     }
186 
187     //-----------------------------------------------------------------------------------------------------------
188     // MethodInfos for the Get/Set methods on array types.
189     //-----------------------------------------------------------------------------------------------------------
190     internal sealed partial class RuntimeSyntheticMethodInfo : RuntimeMethodInfo
191     {
GetRuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, RuntimeTypeInfo returnType, InvokerOptions options, CustomMethodInvokerAction action)192         internal static RuntimeMethodInfo GetRuntimeSyntheticMethodInfo(SyntheticMethodId syntheticMethodId, String name, RuntimeArrayTypeInfo declaringType, RuntimeTypeInfo[] runtimeParameterTypes, RuntimeTypeInfo returnType, InvokerOptions options, CustomMethodInvokerAction action)
193         {
194             return new RuntimeSyntheticMethodInfo(syntheticMethodId, name, declaringType, runtimeParameterTypes, returnType, options, action).WithDebugName();
195         }
196     }
197 }
198 
199 namespace System.Reflection.Runtime.ParameterInfos
200 {
201     //-----------------------------------------------------------------------------------------------------------
202     // ParameterInfos for MethodBase objects with no Parameter metadata.
203     //-----------------------------------------------------------------------------------------------------------
204     internal sealed partial class RuntimeThinMethodParameterInfo : RuntimeMethodParameterInfo
205     {
GetRuntimeThinMethodParameterInfo(MethodBase member, int position, QSignatureTypeHandle qualifiedParameterType, TypeContext typeContext)206         internal static RuntimeThinMethodParameterInfo GetRuntimeThinMethodParameterInfo(MethodBase member, int position, QSignatureTypeHandle qualifiedParameterType, TypeContext typeContext)
207         {
208             return new RuntimeThinMethodParameterInfo(member, position, qualifiedParameterType, typeContext);
209         }
210     }
211 
212     //-----------------------------------------------------------------------------------------------------------
213     // ParameterInfos returned by PropertyInfo.GetIndexParameters()
214     //-----------------------------------------------------------------------------------------------------------
215     internal sealed partial class RuntimePropertyIndexParameterInfo : RuntimeParameterInfo
216     {
GetRuntimePropertyIndexParameterInfo(RuntimePropertyInfo member, RuntimeParameterInfo backingParameter)217         internal static RuntimePropertyIndexParameterInfo GetRuntimePropertyIndexParameterInfo(RuntimePropertyInfo member, RuntimeParameterInfo backingParameter)
218         {
219             return new RuntimePropertyIndexParameterInfo(member, backingParameter);
220         }
221     }
222 
223     //-----------------------------------------------------------------------------------------------------------
224     // ParameterInfos returned by Get/Set methods on array types.
225     //-----------------------------------------------------------------------------------------------------------
226     internal sealed partial class RuntimeSyntheticParameterInfo : RuntimeParameterInfo
227     {
GetRuntimeSyntheticParameterInfo(MemberInfo member, int position, RuntimeTypeInfo parameterType)228         internal static RuntimeSyntheticParameterInfo GetRuntimeSyntheticParameterInfo(MemberInfo member, int position, RuntimeTypeInfo parameterType)
229         {
230             return new RuntimeSyntheticParameterInfo(member, position, parameterType);
231         }
232     }
233 }
234