/// <summary> /// Load an IL or NI assembly from its file path. /// </summary> internal Assembly LoadFrom(string assemblyPath) { ValidateAssemblyPath(assemblyPath, "assemblyPath"); Assembly asmLoaded; AssemblyName assemblyName = GetAssemblyName(assemblyPath); // Probe the assembly cache if (TryGetAssemblyFromCache(assemblyName, out asmLoaded)) { return(asmLoaded); } // Prepare to load the assembly lock (s_syncObj) { // Probe the cache again in case it's already loaded if (TryGetAssemblyFromCache(assemblyName, out asmLoaded)) { return(asmLoaded); } // Load the assembly through 'LoadFromNativeImagePath' or 'LoadFromAssemblyPath' asmLoaded = assemblyPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase) ? _activeLoadContext.LoadFromNativeImagePath(assemblyPath, null) : _activeLoadContext.LoadFromAssemblyPath(assemblyPath); if (asmLoaded != null) { // Add the loaded assembly to the cache s_assemblyCache.TryAdd(assemblyName.Name, asmLoaded); // Add its parent path to our probing paths string parentPath = Path.GetDirectoryName(assemblyPath); if (!_probingPaths.Contains(parentPath)) { _probingPaths.Add(parentPath); } } } // Raise AssemblyLoad event OnAssemblyLoaded(asmLoaded); return(asmLoaded); }
/// <summary> /// The handler for the Resolving event /// </summary> private Assembly Resolve(AssemblyLoadContext loadContext, AssemblyName assemblyName) { // Probe the assembly cache Assembly asmLoaded; if (TryGetAssemblyFromCache(assemblyName, out asmLoaded)) { return(asmLoaded); } // Prepare to load the assembly lock (s_syncObj) { // Probe the cache again in case it's already loaded if (TryGetAssemblyFromCache(assemblyName, out asmLoaded)) { return(asmLoaded); } // Search the specified assembly in probing paths, and load it through 'LoadFromAssemblyPath' if the file exists and matches the requested AssemblyName. // If the CultureName of the requested assembly is not NullOrEmpty, then it's a resources.dll and we need to search corresponding culture sub-folder. bool isAssemblyFileFound = false, isAssemblyFileMatching = false; string asmCultureName = assemblyName.CultureName ?? string.Empty; string asmFilePath = null; for (int i = 0; i < _probingPaths.Length; i++) { string probingPath = _probingPaths[i]; string asmCulturePath = Path.Combine(probingPath, asmCultureName); for (int k = 0; k < _extensions.Length; k++) { string asmFileName = assemblyName.Name + _extensions[k]; asmFilePath = Path.Combine(asmCulturePath, asmFileName); if (File.Exists(asmFilePath)) { isAssemblyFileFound = true; AssemblyName asmNameFound = AssemblyLoadContext.GetAssemblyName(asmFilePath); if (IsAssemblyMatching(assemblyName, asmNameFound)) { isAssemblyFileMatching = true; break; } } } if (isAssemblyFileFound && isAssemblyFileMatching) { break; } } // We failed to find the assembly file; or we found the file, but the assembly file doesn't match the request. // In this case, return null so that other Resolving event handlers can kick in to resolve the request. if (!isAssemblyFileFound || !isAssemblyFileMatching) { #if !UNIX //Try loading from GAC if (!TryFindInGAC(assemblyName, out asmFilePath)) { return(null); } #else return(null); #endif } asmLoaded = asmFilePath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase) ? loadContext.LoadFromNativeImagePath(asmFilePath, null) : loadContext.LoadFromAssemblyPath(asmFilePath); if (asmLoaded != null) { // Add the loaded assembly to the cache s_assemblyCache.TryAdd(assemblyName.Name, asmLoaded); } } return(asmLoaded); }