| File: Internal\Reflection\Execution\AssemblyBinderImplementation.cs | Web Access |
| Project: src\runtime\src\coreclr\nativeaot\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj (System.Private.TypeLoader) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Runtime.General; using Internal.Metadata.NativeFormat; using Internal.Reflection.Core; using Internal.Runtime.TypeLoader; namespace Internal.Reflection.Execution { //============================================================================================================================= // The assembly resolution policy for emulation of "classic reflection." // // The policy is very simple: the only assemblies that can be "loaded" are those that are statically linked into the running // native process. There is no support for probing for assemblies in directories, user-supplied files, GACs, NICs or any // other repository. //============================================================================================================================= public sealed partial class AssemblyBinderImplementation : AssemblyBinder { private AssemblyBinderImplementation() { ArrayBuilder<KeyValuePair<RuntimeAssemblyName, QScopeDefinition>> scopes = default; foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules()) { MetadataReader reader = module.MetadataReader; foreach (ScopeDefinitionHandle scopeDefinitionHandle in reader.ScopeDefinitions) { scopes.Add(new KeyValuePair<RuntimeAssemblyName, QScopeDefinition>( scopeDefinitionHandle.ToRuntimeAssemblyName(reader), new QScopeDefinition(reader, scopeDefinitionHandle) )); } } ScopeGroups = scopes.ToArray(); } public static AssemblyBinderImplementation Instance { get; } = new AssemblyBinderImplementation(); public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLookups, out AssemblyBindResult result, out Exception exception) { bool foundMatch = false; result = default(AssemblyBindResult); exception = null; Exception preferredException = null; foreach (KeyValuePair<RuntimeAssemblyName, QScopeDefinition> group in ScopeGroups) { if (AssemblyNameMatches(refName, group.Key, ref preferredException)) { if (foundMatch) { exception = new AmbiguousMatchException(SR.Format(SR.AmbiguousMatchException_Assembly, refName.FullName)); return false; } foundMatch = true; QScopeDefinition scopeDefinitionGroup = group.Value; result.Reader = scopeDefinitionGroup.Reader; result.ScopeDefinitionHandle = scopeDefinitionGroup.Handle; } } if (!foundMatch) { exception = preferredException ?? new FileNotFoundException(SR.Format(SR.FileNotFound_AssemblyNotFound, refName.FullName)); return false; } return true; } public sealed override IList<AssemblyBindResult> GetLoadedAssemblies() { List<AssemblyBindResult> loadedAssemblies = new List<AssemblyBindResult>(ScopeGroups.Length); foreach (KeyValuePair<RuntimeAssemblyName, QScopeDefinition> group in ScopeGroups) { QScopeDefinition scopeDefinitionGroup = group.Value; AssemblyBindResult result = default(AssemblyBindResult); result.Reader = scopeDefinitionGroup.Reader; result.ScopeDefinitionHandle = scopeDefinitionGroup.Handle; loadedAssemblies.Add(result); } return loadedAssemblies; } public sealed override int GetLoadedAssembliesCount() { return ScopeGroups.Length; } // // Encapsulates the assembly ref->def matching policy. // private static bool AssemblyNameMatches(RuntimeAssemblyName refName, RuntimeAssemblyName defName, ref Exception preferredException) { // // The defName came from trusted metadata so it should be fully specified. // Debug.Assert(defName.Version != null); Debug.Assert(defName.CultureName != null); if (!(refName.Name.Equals(defName.Name, StringComparison.OrdinalIgnoreCase))) return false; if (refName.Version != null) { if (!AssemblyVersionMatches(refVersion: refName.Version, defVersion: defName.Version)) { preferredException = new FileLoadException(SR.Format(SR.FileLoadException_RefDefMismatch, refName.FullName, defName.Version, refName.Version)); return false; } } if (refName.CultureName != null) { if (!(refName.CultureName.Equals(defName.CultureName))) return false; } // Strong names are ignored in .NET Core return true; } private static bool AssemblyVersionMatches(Version refVersion, Version defVersion) { if (defVersion.Major < refVersion.Major) return false; if (defVersion.Major > refVersion.Major) return true; if (defVersion.Minor < refVersion.Minor) return false; if (defVersion.Minor > refVersion.Minor) return true; if (refVersion.Build == -1) return true; if (defVersion.Build < refVersion.Build) return false; if (defVersion.Build > refVersion.Build) return true; if (refVersion.Revision == -1) return true; if (defVersion.Revision < refVersion.Revision) return false; return true; } private KeyValuePair<RuntimeAssemblyName, QScopeDefinition>[] ScopeGroups { get; } } }