818331d3a26b40d61edb1c08acb3f36d51779e54
[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.Collections.Generic;
6 using System.Globalization;
7 using System.IO;
8 using System.Runtime.Serialization;
9 using System.Text;
10
11 namespace System.Reflection.TypeLoading
12 {
13     /// <summary>
14     /// Base class for all Assembly objects created by a MetadataLoadContext.
15     /// </summary>
16     internal abstract partial class RoAssembly : LeveledAssembly
17     {
18         private readonly RoModule[] _loadedModules; // Any loaded modules indexed by [rid - 1]. Does NOT include the manifest module.
19
20         protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount)
21             : base()
22         {
23             Loader = loader;
24             IsSingleModule = (assemblyFileCount == 0);
25             _loadedModules = (assemblyFileCount == 0) ? Array.Empty<RoModule>() : new RoModule[assemblyFileCount];
26         }
27
28         public sealed override Module ManifestModule => GetRoManifestModule();
29         internal abstract RoModule GetRoManifestModule();
30         protected bool IsSingleModule { get; }
31
32         public sealed override string ToString() => Loader.GetDisposedString() ?? base.ToString();
33
34         // Naming
35         public sealed override AssemblyName GetName(bool copiedName) => GetAssemblyNameDataNoCopy().CreateAssemblyName();
36         internal AssemblyNameData GetAssemblyNameDataNoCopy() => _lazyAssemblyNameData ?? (_lazyAssemblyNameData = ComputeNameData());
37         protected abstract AssemblyNameData ComputeNameData();
38         private volatile AssemblyNameData _lazyAssemblyNameData;
39
40         public sealed override string FullName => _lazyFullName ?? (_lazyFullName = GetName().FullName);
41         private volatile string _lazyFullName;
42
43         // Location and codebase
44         public abstract override string Location { get; }
45         public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase);
46         public sealed override string EscapedCodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase);
47
48         // Custom Attributes
49         public sealed override IList<CustomAttributeData> GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection();
50         public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; }
51
52         // Apis to retrieved types physically defined in this module.
53         public sealed override Type[] GetTypes() => IsSingleModule ? ManifestModule.GetTypes() : base.GetTypes();
54         public sealed override IEnumerable<TypeInfo> DefinedTypes => GetDefinedRoTypes();
55
56         private IEnumerable<RoType> GetDefinedRoTypes() => IsSingleModule ? GetRoManifestModule().GetDefinedRoTypes() : MultiModuleGetDefinedRoTypes();
57         private IEnumerable<RoType> MultiModuleGetDefinedRoTypes()
58         {
59             foreach (RoModule module in ComputeRoModules(getResourceModules: false))
60             {
61                 foreach (RoType t in module.GetDefinedRoTypes())
62                 {
63                     yield return t;
64                 }
65             }
66         }
67
68         // Apis to retrieve public types physically defined in this module.
69         public sealed override Type[] GetExportedTypes()
70         {
71             // todo: use IEnumerable<T> extension instead: ExportedTypes.ToArray();
72             List<Type> list = new List<Type>(ExportedTypes);
73             return list.ToArray();
74         }
75
76         public sealed override IEnumerable<Type> ExportedTypes
77         {
78             get
79             {
80                 foreach (RoType type in GetDefinedRoTypes())
81                 {
82                     if (type.IsVisibleOutsideAssembly())
83                         yield return type;
84                 }
85             }
86         }
87
88         // Api to retrieve types by name. Retrieves both types physically defined in this module and types this assembly forwards from another assembly.
89         public sealed override Type GetType(string name, bool throwOnError, bool ignoreCase)
90         {
91             if (name == null)
92                 throw new ArgumentNullException(nameof(name));
93
94             // Known compat disagreement: This api is supposed to throw an ArgumentException if the name has an assembly qualification
95             // (though the intended meaning seems clear.) This is difficult for us to implement as we don't have our own type name parser.
96             // (We can't just throw in the assemblyResolve delegate because assembly qualifications are permitted inside generic arguments,
97             // just not in the top level type name.) In the bigger scheme of things, this does not seem worth worrying about.
98
99             return Helpers.LoadTypeFromAssemblyQualifiedName(name, defaultAssembly: this, ignoreCase: ignoreCase, throwOnError: throwOnError);
100         }
101
102         /// <summary>
103         /// Helper routine for the more general Assembly.GetType() family of apis. Also used in typeRef resolution.
104         ///
105         /// Resolves top-level named types only. No nested types. No constructed types. The input name must not be escaped.
106         ///
107         /// If a type is not contained or forwarded from the assembly, this method returns null (does not throw.)
108         /// This supports the "throwOnError: false" behavior of Assembly.GetType(string, bool).
109         /// </summary>
110         internal RoDefinitionType GetTypeCore(string ns, string name, bool ignoreCase, out Exception e) => GetTypeCore(ns.ToUtf8(), name.ToUtf8(), ignoreCase, out e);
111         internal RoDefinitionType GetTypeCore(ReadOnlySpan<byte> ns, ReadOnlySpan<byte> name, bool ignoreCase, out Exception e)
112         {
113             RoDefinitionType result = GetRoManifestModule().GetTypeCore(ns, name, ignoreCase, out e);
114             if (IsSingleModule || result != null)
115                 return result;
116
117             foreach (RoModule module in ComputeRoModules(getResourceModules: false))
118             {
119                 if (module == ManifestModule)
120                     continue;
121
122                 result = module.GetTypeCore(ns, name, ignoreCase, out e);
123                 if (result != null)
124                     return result;
125             }
126             return null;
127         }
128
129         // Assembly dependencies
130         public sealed override AssemblyName[] GetReferencedAssemblies()
131         {
132             // For compat, this api only searches the manifest module. Tools normally ensure the manifest module's assemblyRef
133             // table represents the union of all module's assemblyRef table.
134             AssemblyNameData[] data = GetReferencedAssembliesNoCopy();
135             AssemblyName[] result = new AssemblyName[data.Length];
136             for (int i = 0; i < data.Length; i++)
137             {
138                 result[i] = data[i].CreateAssemblyName();
139             }
140             return result;
141         }
142
143         private AssemblyNameData[] GetReferencedAssembliesNoCopy() => _lazyAssemblyReferences ?? (_lazyAssemblyReferences = ComputeAssemblyReferences());
144         protected abstract AssemblyNameData[] ComputeAssemblyReferences();
145         private volatile AssemblyNameData[] _lazyAssemblyReferences;
146
147         // Miscellaneous properties
148         public sealed override bool ReflectionOnly => true;
149         public sealed override bool GlobalAssemblyCache => false;
150         public sealed override long HostContext => 0;
151         public abstract override string ImageRuntimeVersion { get; }
152         public abstract override bool IsDynamic { get; }
153         public abstract override MethodInfo EntryPoint { get; }
154
155         // Manifest resource support.
156         public abstract override ManifestResourceInfo GetManifestResourceInfo(string resourceName);
157         public abstract override string[] GetManifestResourceNames();
158         public abstract override Stream GetManifestResourceStream(string name);
159         public sealed override Stream GetManifestResourceStream(Type type, string name)
160         {
161             StringBuilder sb = new StringBuilder();
162             if (type == null)
163             {
164                 if (name == null)
165                     throw new ArgumentNullException(nameof(type));
166             }
167             else
168             {
169                 string ns = type.Namespace;
170                 if (ns != null)
171                 {
172                     sb.Append(ns);
173                     if (name != null)
174                         sb.Append(Type.Delimiter);
175                 }
176             }
177
178             if (name != null)
179                 sb.Append(name);
180
181             return GetManifestResourceStream(sb.ToString());
182         }
183
184         // Serialization
185         public sealed override void GetObjectData(SerializationInfo info, StreamingContext context) => throw new NotSupportedException();
186
187         // Satellite assemblies
188         public sealed override Assembly GetSatelliteAssembly(CultureInfo culture) => throw new NotSupportedException(SR.NotSupported_SatelliteAssembly);
189         public sealed override Assembly GetSatelliteAssembly(CultureInfo culture, Version version) => throw new NotSupportedException(SR.NotSupported_SatelliteAssembly);
190
191         // Operations that are invalid for ReflectionOnly objects.
192         public sealed override object[] GetCustomAttributes(bool inherit) => throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA);
193         public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA);
194         public sealed override bool IsDefined(Type attributeType, bool inherit) => throw new InvalidOperationException(SR.Arg_ReflectionOnlyCA);
195         // Compat quirk: Why ArgumentException instead of InvalidOperationException?
196         public sealed override object CreateInstance(string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) => throw new ArgumentException(SR.Arg_ReflectionOnlyInvoke);
197
198         internal MetadataLoadContext Loader { get; }
199     }
200 }