/// <summary>
        /// Installs an assembly resolver, which will load *any* assembly which exists recursively within the supplied folder.
        /// </summary>
        /// <param name="RootDirectory">The directory to enumerate.</param>
        public static void InstallRecursiveAssemblyResolver(string RootDirectory)
        {
            RefreshAssemblyCache(RootDirectory);

            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                // Name is fully qualified assembly definition - e.g. "p4dn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ff968dc1933aba6f"
                string AssemblyName = args.Name.Split(',')[0];
                string AssemblyLocation;
                if (AssemblyLocationCache.TryGetValue(AssemblyName, out AssemblyLocation))
                {
                    // We have this assembly in our folder.
                    if (File.Exists(AssemblyLocation))
                    {
                        // The assembly still exists, so load it.
                        return(Assembly.LoadFile(AssemblyLocation));
                    }
                    else
                    {
                        // The assembly no longer exists on disk, so remove it from our cache.
                        AssemblyLocationCache.Remove(AssemblyName);
                    }
                }

                // The assembly wasn't found, though may have been compiled or copied as a dependency
                RefreshAssemblyCache(RootDirectory, string.Format("{0}.dll", AssemblyName));
                if (AssemblyLocationCache.TryGetValue(AssemblyName, out AssemblyLocation))
                {
                    return(Assembly.LoadFile(AssemblyLocation));
                }

                return(null);
            };
        }
 private static void RefreshAssemblyCache(string RootDirectory, string Pattern = "*.dll")
 {
     // Initialize our cache of assemblies by enumerating all files in the given folder.
     foreach (string DiscoveredAssembly in Directory.EnumerateFiles(RootDirectory, Pattern, SearchOption.AllDirectories))
     {
         string   AssemblyName          = Path.GetFileNameWithoutExtension(DiscoveredAssembly);
         DateTime AssemblyLastWriteTime = File.GetLastWriteTimeUtc(DiscoveredAssembly);
         if (AssemblyLocationCache.ContainsKey(AssemblyName))
         {
             // We already have this assembly in our cache. Only replace it if the discovered file is newer (to avoid stale assemblies breaking stuff).
             if (AssemblyLastWriteTime > AssemblyWriteTimes[AssemblyName])
             {
                 AssemblyLocationCache[AssemblyName] = DiscoveredAssembly;
                 AssemblyWriteTimes[AssemblyName]    = AssemblyLastWriteTime;
             }
         }
         else
         {
             // This is the first copy of this assembly ... add it to our cache.
             AssemblyLocationCache.Add(AssemblyName, DiscoveredAssembly);
             AssemblyWriteTimes.Add(AssemblyName, AssemblyLastWriteTime);
         }
     }
 }