private Assembly AssemblyResolve(object sender, ResolveEventArgs args) { string fullName = args.Name; string simpleName; if (!AssemblyIdentity.TryParseSimpleName(fullName, out simpleName)) { return(null); } if (args.RequestingAssembly != null) { string originalDllPath = null, originalExePath = null; string originalPath = null; lock (ReferencesLock) { LoadedAssembly loadedAssembly; if (loadedAssemblies.TryGetValue(args.RequestingAssembly, out loadedAssembly)) { originalPath = loadedAssembly.OriginalPath; string pathWithoutExtension = Path.Combine(Path.GetDirectoryName(originalPath), simpleName); originalDllPath = pathWithoutExtension + ".dll"; originalExePath = pathWithoutExtension + ".exe"; Assembly assembly; if (loadedAssembliesByPath.TryGetValue(originalDllPath, out assembly) || loadedAssembliesByPath.TryGetValue(originalExePath, out assembly)) { return(assembly); } } } // if the referring assembly is already loaded by our loader, load from its directory: if (originalPath != null) { // Copy & load both .dll and .exe, this is not a common scenario we would need to optimize for. // Remember both loaded assemblies for the next time, even though their versions might not match the current request // they might match the next one and we don't want to load them again. Assembly dll = ShadowCopyAndLoadDependency(originalDllPath); Assembly exe = ShadowCopyAndLoadDependency(originalExePath); if (dll == null ^ exe == null) { return(dll ?? exe); } if (dll != null && exe != null) { // .dll and an .exe of the same name might have different versions, // one of which might match the requested version. // Prefer .dll if they are both the same. return(FindHighestVersionOrFirstMatchingIdentity(fullName, new[] { dll, exe })); } } } return(GetOrLoadKnownAssembly(fullName, simpleName)); }