77497f1ff9422f56f0a886f86617152bf015193d
[platform/upstream/dotnet/runtime.git] /
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.Reflection.Metadata;
6
7 namespace System.Reflection.TypeLoading.Ecma
8 {
9     internal sealed partial class EcmaModule
10     {
11
12         /// <summary>
13         /// Helper routine for the more general Module.GetType() family of apis. Also used in typeRef resolution.
14         ///
15         /// Resolves top-level named types only. No nested types. No constructed types. The input name must not be escaped.
16         ///
17         /// If a type is not contained or forwarded from the assembly, this method returns null (does not throw.)
18         /// This supports the "throwOnError: false" behavior of Module.GetType(string, bool).
19         /// </summary>
20         protected sealed override RoDefinitionType GetTypeCoreNoCache(ReadOnlySpan<byte> ns, ReadOnlySpan<byte> name, out Exception e)
21         {
22             MetadataReader reader = Reader;
23
24             // Look through types declared in the manifest module.
25             foreach (TypeDefinitionHandle h in reader.TypeDefinitions)
26             {
27                 TypeDefinition td = h.GetTypeDefinition(reader);
28                 if (td.IsNested)
29                     continue;  // GetTypeCore() is never asked to look for nested types.
30                 if (!(td.Name.Equals(name, reader)))
31                     continue;
32                 if (!(td.Namespace.Equals(ns, reader)))
33                     continue;
34
35                 e = null;
36                 return h.ResolveTypeDef(this);
37             }
38
39             // Look for forwarded types.
40             foreach (ExportedTypeHandle h in reader.ExportedTypes)
41             {
42                 ExportedType et = h.GetExportedType(reader);
43                 if (!et.IsForwarder)
44                     continue;
45
46                 EntityHandle implementation = et.Implementation;
47                 if (implementation.Kind != HandleKind.AssemblyReference) // This check also weeds out nested types. This is intentional.
48                     continue;
49
50                 if (!(et.Name.Equals(name, reader)))
51                     continue;
52
53                 if (!(et.Namespace.Equals(ns, reader)))
54                     continue;
55
56                 RoAssembly assembly = ((AssemblyReferenceHandle)implementation).TryResolveAssembly(this, out e);
57                 return assembly?.GetTypeCore(ns, name, ignoreCase: false, out e);
58             }
59
60             e = new TypeLoadException(SR.Format(SR.TypeNotFound, ns.ToUtf16().AppendTypeName(name.ToUtf16()), FullyQualifiedName));
61             return null;
62         }
63     }
64 }