diff --git a/src/libraries/System.Reflection.MetadataLoadContext/ref/System.Reflection.MetadataLoadContext.cs b/src/libraries/System.Reflection.MetadataLoadContext/ref/System.Reflection.MetadataLoadContext.cs index 8def4aa07a1792..777696eb825b78 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/ref/System.Reflection.MetadataLoadContext.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/ref/System.Reflection.MetadataLoadContext.cs @@ -14,7 +14,7 @@ protected MetadataAssemblyResolver() { } public sealed partial class MetadataLoadContext : System.IDisposable { public MetadataLoadContext(System.Reflection.MetadataAssemblyResolver resolver, string? coreAssemblyName = null) { } - public System.Reflection.Assembly? CoreAssembly { get { throw null; } } + public System.Reflection.Assembly CoreAssembly { get { throw null; } } public void Dispose() { } public System.Collections.Generic.IEnumerable GetAssemblies() { throw null; } public System.Reflection.Assembly LoadFromAssemblyName(System.Reflection.AssemblyName assemblyName) { throw null; } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.Apis.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.Apis.cs index 425be1dc7d0b34..594655c2c02090 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.Apis.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.Apis.cs @@ -109,14 +109,9 @@ public MetadataLoadContext(MetadataAssemblyResolver resolver, string? coreAssemb this.resolver = resolver; - if (coreAssemblyName != null) - { - // Validate now that the value is a parsable assembly name. - new AssemblyName(coreAssemblyName); - } - // Resolve the core assembly now - _coreTypes = new CoreTypes(this, coreAssemblyName); + _coreAssembly = LoadCoreAssembly(coreAssemblyName); + _coreTypes = new CoreTypes(_coreAssembly); } /// @@ -205,10 +200,9 @@ public Assembly LoadFromAssemblyName(AssemblyName assemblyName) /// The core assembly is treated differently than other assemblies because references to these well-known types do /// not include the assembly reference, unlike normal types. /// - /// Typically, this assembly is named "mscorlib", or "netstandard". If the core assembly cannot be found, the value will be - /// null and many other reflection methods, including those that parse method signatures, will throw. + /// Typically, this assembly is named "System.Runtime", "mscorlib", or "netstandard". /// - /// The CoreAssembly is determined by passing the coreAssemblyName parameter passed to the MetadataAssemblyResolver constructor + /// The CoreAssembly is determined by passing the coreAssemblyName parameter passed to the MetadataLoadContext constructor /// to the MetadataAssemblyResolver's Resolve method. /// If no coreAssemblyName argument was specified in the constructor of MetadataLoadContext, then default values are used /// including "mscorlib", "System.Runtime" and "netstandard". @@ -220,27 +214,9 @@ public Assembly LoadFromAssemblyName(AssemblyName assemblyName) /// such as DllImportAttribute. However, it can serve if you have no interest in those attributes. The CustomAttributes api /// will skip those attributes if the core assembly does not include the necessary types. /// - /// The CoreAssembly is not loaded until necessary. These APIs do not trigger the search for the core assembly: - /// MetadataLoadContext.LoadFromStream(), LoadFromAssemblyPath(), LoadFromByteArray() - /// Assembly.GetName(), Assembly.FullName, Assembly.GetReferencedAssemblies() - /// Assembly.GetTypes(), Assembly.DefinedTypes, Assembly.GetExportedTypes(), Assembly.GetForwardedTypes() - /// Assembly.GetType(string, bool, bool) - /// Type.Name, Type.FullName, Type.AssemblyQualifiedName - /// - /// If a core assembly cannot be found or if the core assembly is missing types, this will affect the behavior of the MetadataLoadContext as follows: - /// - /// - Apis that need to parse signatures or typespecs and return the results as Types will throw. For example, - /// MethodBase.ReturnType, MethodBase.GetParameters(), Type.BaseType, Type.GetInterfaces(). - /// - /// - Apis that need to compare types to well known core types will not throw and the comparison will evaluate to "false." - /// For example, if you do not specify a core assembly, Type.IsPrimitive will return false for everything, - /// even types named "System.Int32". Similarly, Type.GetTypeCode() will return TypeCode.Object for everything. - /// - /// - If a metadata entity sets flags that surface as a pseudo-custom attribute, and the core assembly does not contain the pseudo-custom attribute - /// type, the necessary constructor or any of the parameter types of the constructor, the MetadataLoadContext will not throw. It will omit the pseudo-custom - /// attribute from the list of returned attributes. + /// If a core assembly cannot be found or if the core assembly is missing types, the constructor of MetadataLoadContext will throw an exception. /// - public Assembly? CoreAssembly + public Assembly CoreAssembly { get { diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.CoreAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.CoreAssembly.cs index 90617b18a448ce..ca1d873b1e998c 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.CoreAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/MetadataLoadContext.CoreAssembly.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.IO; using System.Reflection.TypeLoading; @@ -11,21 +10,25 @@ public sealed partial class MetadataLoadContext { private static readonly string[] s_CoreNames = { "mscorlib", "System.Runtime", "netstandard" }; - // Cache loaded coreAssembly and core types. - internal RoAssembly? TryGetCoreAssembly(string? coreAssemblyName, out Exception? e) + internal RoAssembly LoadCoreAssembly(string? coreAssemblyName) { - Debug.Assert(_coreAssembly == null); + RoAssembly? coreAssembly; + Exception? e; if (coreAssemblyName == null) { - _coreAssembly = TryGetDefaultCoreAssembly(out e); + coreAssembly = TryGetDefaultCoreAssembly(out e); } else { RoAssemblyName roAssemblyName = new AssemblyName(coreAssemblyName).ToRoAssemblyName(); - _coreAssembly = TryResolveAssembly(roAssemblyName, out e); + coreAssembly = TryResolveAssembly(roAssemblyName, out e); } - return _coreAssembly; + if (coreAssembly == null) + { + throw e!; + } + return coreAssembly; } private RoAssembly? TryGetDefaultCoreAssembly(out Exception? e) @@ -47,7 +50,7 @@ public sealed partial class MetadataLoadContext return null; } - private RoAssembly? _coreAssembly; + private readonly RoAssembly _coreAssembly; /// /// Returns a lazily created and cached Type instance corresponding to the indicated core type. This method throws diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/CoreTypes.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/CoreTypes.cs index c40fd5efb042b2..c2d90d90858ad0 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/CoreTypes.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/CoreTypes.cs @@ -11,28 +11,19 @@ internal sealed class CoreTypes private readonly RoType?[] _coreTypes; private readonly Exception?[] _exceptions; - internal CoreTypes(MetadataLoadContext loader, string? coreAssemblyName) + internal CoreTypes(RoAssembly coreAssembly) { int numCoreTypes = (int)CoreType.NumCoreTypes; RoType?[] coreTypes = new RoType[numCoreTypes]; Exception?[] exceptions = new Exception[numCoreTypes]; - RoAssembly? coreAssembly = loader.TryGetCoreAssembly(coreAssemblyName, out Exception? e); - if (coreAssembly == null) + for (int i = 0; i < numCoreTypes; i++) { - // If the core assembly was not found, don't continue. - throw e!; - } - else - { - for (int i = 0; i < numCoreTypes; i++) + ((CoreType)i).GetFullName(out ReadOnlySpan ns, out ReadOnlySpan name); + RoType? type = coreAssembly.GetTypeCore(ns, name, ignoreCase: false, out Exception? e); + coreTypes[i] = type; + if (type == null) { - ((CoreType)i).GetFullName(out ReadOnlySpan ns, out ReadOnlySpan name); - RoType? type = coreAssembly.GetTypeCore(ns, name, ignoreCase: false, out e); - coreTypes[i] = type; - if (type == null) - { - exceptions[i] = e; - } + exceptions[i] = e; } } _coreTypes = coreTypes;