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.
5 using System.Collections.Generic;
6 using System.Globalization;
8 using System.Runtime.Serialization;
11 namespace System.Reflection.TypeLoading
14 /// Base class for all Assembly objects created by a MetadataLoadContext.
16 internal abstract partial class RoAssembly : LeveledAssembly
18 private readonly RoModule[] _loadedModules; // Any loaded modules indexed by [rid - 1]. Does NOT include the manifest module.
20 protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount)
24 IsSingleModule = (assemblyFileCount == 0);
25 _loadedModules = (assemblyFileCount == 0) ? Array.Empty<RoModule>() : new RoModule[assemblyFileCount];
28 public sealed override Module ManifestModule => GetRoManifestModule();
29 internal abstract RoModule GetRoManifestModule();
30 protected bool IsSingleModule { get; }
32 public sealed override string ToString() => Loader.GetDisposedString() ?? base.ToString();
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;
40 public sealed override string FullName => _lazyFullName ?? (_lazyFullName = GetName().FullName);
41 private volatile string _lazyFullName;
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);
49 public sealed override IList<CustomAttributeData> GetCustomAttributesData() => CustomAttributes.ToReadOnlyCollection();
50 public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; }
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();
56 private IEnumerable<RoType> GetDefinedRoTypes() => IsSingleModule ? GetRoManifestModule().GetDefinedRoTypes() : MultiModuleGetDefinedRoTypes();
57 private IEnumerable<RoType> MultiModuleGetDefinedRoTypes()
59 foreach (RoModule module in ComputeRoModules(getResourceModules: false))
61 foreach (RoType t in module.GetDefinedRoTypes())
68 // Apis to retrieve public types physically defined in this module.
69 public sealed override Type[] GetExportedTypes()
71 // todo: use IEnumerable<T> extension instead: ExportedTypes.ToArray();
72 List<Type> list = new List<Type>(ExportedTypes);
73 return list.ToArray();
76 public sealed override IEnumerable<Type> ExportedTypes
80 foreach (RoType type in GetDefinedRoTypes())
82 if (type.IsVisibleOutsideAssembly())
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)
92 throw new ArgumentNullException(nameof(name));
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.
99 return Helpers.LoadTypeFromAssemblyQualifiedName(name, defaultAssembly: this, ignoreCase: ignoreCase, throwOnError: throwOnError);
103 /// Helper routine for the more general Assembly.GetType() family of apis. Also used in typeRef resolution.
105 /// Resolves top-level named types only. No nested types. No constructed types. The input name must not be escaped.
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).
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)
113 RoDefinitionType result = GetRoManifestModule().GetTypeCore(ns, name, ignoreCase, out e);
114 if (IsSingleModule || result != null)
117 foreach (RoModule module in ComputeRoModules(getResourceModules: false))
119 if (module == ManifestModule)
122 result = module.GetTypeCore(ns, name, ignoreCase, out e);
129 // Assembly dependencies
130 public sealed override AssemblyName[] GetReferencedAssemblies()
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++)
138 result[i] = data[i].CreateAssemblyName();
143 private AssemblyNameData[] GetReferencedAssembliesNoCopy() => _lazyAssemblyReferences ?? (_lazyAssemblyReferences = ComputeAssemblyReferences());
144 protected abstract AssemblyNameData[] ComputeAssemblyReferences();
145 private volatile AssemblyNameData[] _lazyAssemblyReferences;
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; }
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)
161 StringBuilder sb = new StringBuilder();
165 throw new ArgumentNullException(nameof(type));
169 string ns = type.Namespace;
174 sb.Append(Type.Delimiter);
181 return GetManifestResourceStream(sb.ToString());
185 public sealed override void GetObjectData(SerializationInfo info, StreamingContext context) => throw new NotSupportedException();
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);
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);
198 internal MetadataLoadContext Loader { get; }