| File: System\Reflection\Runtime\Assemblies\RuntimeAssemblyInfo.cs | Web Access |
| Project: src\runtime\src\coreclr\nativeaot\System.Private.CoreLib\src\System.Private.CoreLib.csproj (System.Private.CoreLib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Runtime.General; using System.Reflection.Runtime.TypeInfos; using System.Runtime.Serialization; using System.Security; using Internal.Reflection.Core; using Internal.Reflection.Core.Execution; namespace System.Reflection.Runtime.Assemblies { // // The runtime's implementation of an Assembly. // internal abstract partial class RuntimeAssemblyInfo : RuntimeAssembly, IEquatable<RuntimeAssemblyInfo> { public bool Equals(RuntimeAssemblyInfo? other) { if (other == null) return false; return this.Equals((object)other); } public sealed override string FullName { get { return GetName().FullName; } } [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] public sealed override void GetObjectData(SerializationInfo info, StreamingContext context) { throw new PlatformNotSupportedException(); } public abstract override Module ManifestModule { get; } public sealed override IEnumerable<Module> Modules { get { yield return ManifestModule; } } public sealed override Module GetModule(string name) { if (name == ManifestModule.ScopeName) return ManifestModule; return null; } [RequiresUnreferencedCode("Types might be removed")] public sealed override Type GetType(string name, bool throwOnError, bool ignoreCase) { ArgumentException.ThrowIfNullOrEmpty(name); return TypeNameResolver.GetType(name, throwOnError: throwOnError, ignoreCase: ignoreCase, topLevelAssembly: this); } #pragma warning disable 0067 // Silence warning about ModuleResolve not being used. public sealed override event ModuleResolveEventHandler? ModuleResolve; #pragma warning restore 0067 public sealed override bool ReflectionOnly => false; // ReflectionOnly loading not supported. public sealed override bool IsCollectible => false; // Unloading not supported. internal abstract RuntimeAssemblyName RuntimeAssemblyName { get; } public sealed override AssemblyName GetName() { return RuntimeAssemblyName.ToAssemblyName(); } [RequiresUnreferencedCode("Types might be removed")] public sealed override Type[] GetForwardedTypes() { List<Type> types = new List<Type>(); List<Exception>? exceptions = null; foreach (TypeForwardInfo typeForwardInfo in TypeForwardInfos) { string fullTypeName = typeForwardInfo.NamespaceName.Length == 0 ? typeForwardInfo.TypeName : typeForwardInfo.NamespaceName + "." + typeForwardInfo.TypeName; RuntimeAssemblyName redirectedAssemblyName = typeForwardInfo.RedirectedAssemblyName; Type? type = null; RuntimeAssemblyInfo redirectedAssembly; Exception exception = TryGetRuntimeAssembly(redirectedAssemblyName, out redirectedAssembly); if (exception == null) { type = redirectedAssembly.GetTypeCore(fullTypeName, throwOnError: true, ignoreCase: false); // GetTypeCore() will follow any further type-forwards if needed. } Debug.Assert((type != null) != (exception != null)); // Exactly one of these must be non-null. if (type != null) { types.Add(type); AddPublicNestedTypes(type, types); } else { exceptions ??= new List<Exception>(); exceptions.Add(exception); } } if (exceptions != null) { int numTypes = types.Count; int numExceptions = exceptions.Count; types.AddRange(new Type[numExceptions]); // add one null Type for each exception. exceptions.InsertRange(0, new Exception[numTypes]); // align the Exceptions with the null Types. throw new ReflectionTypeLoadException(types.ToArray(), exceptions.ToArray()); } return types.ToArray(); } /// <summary> /// Intentionally excludes forwards to nested types. /// </summary> protected abstract IEnumerable<TypeForwardInfo> TypeForwardInfos { get; } [RequiresUnreferencedCode("Types might be removed")] private static void AddPublicNestedTypes(Type type, List<Type> types) { foreach (Type nestedType in type.GetNestedTypes(BindingFlags.Public)) { types.Add(nestedType); AddPublicNestedTypes(nestedType, types); } } /// <summary> /// Helper routine for the more general Type.GetType() family of apis. /// /// Resolves top-level named types only. No nested types. No constructed types. /// /// Returns null if the type does not exist. Throws for all other error cases. /// </summary> internal Type GetTypeCore(string fullName, bool throwOnError, bool ignoreCase) { RuntimeTypeInfo? type = ignoreCase ? GetTypeCoreCaseInsensitive(fullName) : GetTypeCoreCaseSensitive(fullName); if (type == null) { if (throwOnError) throw Helpers.CreateTypeLoadException(fullName, this.FullName); return null; } return type.ToType(); } // Types that derive from RuntimeAssembly must implement the following public surface area members public abstract override IEnumerable<CustomAttributeData> CustomAttributes { get; } public abstract override IEnumerable<TypeInfo> DefinedTypes { [RequiresUnreferencedCode("Types might be removed")] get; } public abstract override MethodInfo EntryPoint { get; } public abstract override IEnumerable<Type> ExportedTypes { [RequiresUnreferencedCode("Types might be removed")] get; } public abstract override ManifestResourceInfo GetManifestResourceInfo(string resourceName); public abstract override string[] GetManifestResourceNames(); public abstract override Stream GetManifestResourceStream(string name); public abstract override string ImageRuntimeVersion { get; } public abstract override bool Equals(object obj); public abstract override int GetHashCode(); /// <summary> /// Perform a lookup for a type based on a name. Overriders are expected to /// have a non-cached implementation, as the result is expected to be cached by /// callers of this method. Should be implemented by every format specific /// RuntimeAssembly implementor /// </summary> internal abstract RuntimeTypeInfo UncachedGetTypeCoreCaseSensitive(string fullName); /// <summary> /// Perform a lookup for a type based on a name. Overriders may or may not /// have a cached implementation, as the result is not expected to be cached by /// callers of this method, but it is also a rarely used api. Should be /// implemented by every format specific RuntimeAssembly implementor /// </summary> internal abstract RuntimeTypeInfo GetTypeCoreCaseInsensitive(string fullName); internal RuntimeTypeInfo GetTypeCoreCaseSensitive(string fullName) { return this.CaseSensitiveTypeTable.GetOrAdd(fullName); } private CaseSensitiveTypeCache CaseSensitiveTypeTable { get { return _lazyCaseSensitiveTypeTable ??= new CaseSensitiveTypeCache(this); } } #pragma warning disable 0672 // GlobalAssemblyCache is Obsolete. public sealed override bool GlobalAssemblyCache { get { return false; } } #pragma warning restore 0672 public sealed override long HostContext { get { return 0; } } [RequiresUnreferencedCode("Types and members the loaded module depends on might be removed")] public sealed override Module LoadModule(string moduleName, byte[] rawModule, byte[] rawSymbolStore) { throw new PlatformNotSupportedException(); } [RequiresAssemblyFiles(ThrowingMessageInRAF)] public sealed override FileStream GetFile(string name) { throw new FileNotFoundException(); } [RequiresAssemblyFiles(ThrowingMessageInRAF)] public sealed override FileStream[] GetFiles(bool getResourceModules) { throw new FileNotFoundException(); } public sealed override SecurityRuleSet SecurityRuleSet { get { return SecurityRuleSet.None; } } /// <summary> /// Returns a *freshly allocated* array of loaded Assemblies. /// </summary> internal static Assembly[] GetLoadedAssemblies() { // Important: The result of this method is the return value of the AppDomain.GetAssemblies() api so // so it must return a freshly allocated array on each call. AssemblyBinder binder = ReflectionCoreExecution.ExecutionEnvironment.AssemblyBinder; IList<AssemblyBindResult> bindResults = binder.GetLoadedAssemblies(); Assembly[] results = new Assembly[bindResults.Count]; for (int i = 0; i < bindResults.Count; i++) { Assembly assembly = GetRuntimeAssembly(bindResults[i]); results[i] = assembly; } return results; } private volatile CaseSensitiveTypeCache _lazyCaseSensitiveTypeTable; private sealed class CaseSensitiveTypeCache : ConcurrentUnifier<string, RuntimeTypeInfo> { public CaseSensitiveTypeCache(RuntimeAssemblyInfo runtimeAssembly) { _runtimeAssembly = runtimeAssembly; } protected sealed override RuntimeTypeInfo Factory(string key) { return _runtimeAssembly.UncachedGetTypeCoreCaseSensitive(key); } private readonly RuntimeAssemblyInfo _runtimeAssembly; } } }