Example #1
0
        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            // Handle the RhinoCommon case.
            if (args.Name.StartsWith("RhinoCommon", StringComparison.OrdinalIgnoreCase) &&
                !args.Name.StartsWith("RhinoCommon.resources", StringComparison.OrdinalIgnoreCase))
            {
                return(Assembly.GetExecutingAssembly());
            }

            // Get the significant name of the assembly we're looking for.
            string searchname = args.Name;
            // Do not attempt to handle resource searching.
            int index = searchname.IndexOf(".resources", StringComparison.Ordinal);

            if (index > 0)
            {
                return(null);
            }

            // The resolver is commonly called multiple times with the same search name.
            // Keep the results around so we don't keep doing the same job over and over
            if (m_match_dictionary != null && m_match_dictionary.ContainsKey(args.Name))
            {
                return(m_match_dictionary[args.Name]);
            }

            bool probably_python = false;

            index = searchname.IndexOf(',');
            if (index > 0)
            {
                searchname = searchname.Substring(0, index);
            }
            else
            {
                // Python scripts typically just look for very short names, like "MyFunctions.dll"
                if (searchname.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
                {
                    searchname = searchname.Substring(0, searchname.Length - ".dll".Length);
                }
                probably_python = true;
            }

            // See if the assembly is already loaded.
            var loaded_assemblies = AppDomain.CurrentDomain.GetAssemblies();

            foreach (var loaded_assembly in loaded_assemblies)
            {
                if (loaded_assembly.FullName.StartsWith(searchname + ",", StringComparison.OrdinalIgnoreCase))
                {
                    return(loaded_assembly);
                }
            }



            List <string> potential_files = new List <string>();

            // Collect all potential files in the plug-in directories.
#if RHINO_SDK
            string[] plugin_folders = HostUtils.GetAssemblySearchPaths();
            if (plugin_folders != null)
            {
                foreach (string plugin_folder in plugin_folders)
                {
                    string[] files = Directory.GetFiles(plugin_folder, @"*.dll", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly?
                    if (files != null)
                    {
                        potential_files.AddRange(files);
                    }

                    files = Directory.GetFiles(plugin_folder, @"*.rhp", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly?
                    if (files != null)
                    {
                        potential_files.AddRange(files);
                    }
                }
            }
#endif
            if (probably_python)
            {
                string current_dir = Directory.GetCurrentDirectory();
                if (!string.IsNullOrEmpty(current_dir))
                {
                    string[] files = Directory.GetFiles(current_dir, @"*.dll", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly?
                    if (files != null)
                    {
                        potential_files.AddRange(files);
                    }
                }
            }

            // Collect all potential files in the custom directories.
            if (m_custom_folders != null)
            {
                foreach (string custom_folder in m_custom_folders)
                {
                    string[] files = Directory.GetFiles(custom_folder, @"*.dll", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly?
                    if (files != null)
                    {
                        potential_files.AddRange(files);
                    }

                    files = Directory.GetFiles(custom_folder, @"*.rhp", SearchOption.TopDirectoryOnly); //Why TopDirectoryOnly?
                    if (files != null)
                    {
                        potential_files.AddRange(files);
                    }
                }
            }

            // Collect all potential files in the custom file list.
            if (m_custom_files != null)
            {
                potential_files.AddRange(m_custom_files);
            }

            // Remove the already loaded assemblies from the "potential" list. We've
            // already tested these.
            for (int i = 0; i < loaded_assemblies.Length; i++)
            {
                if (loaded_assemblies[i].GlobalAssemblyCache)
                {
                    continue;
                }
                if (loaded_assemblies[i].IsDynamic)
                {
                    continue; //dynamic assemblies won't have a Location anyways.
                }
                try
                {
                    // 6 Feb 2017 S. Baer (RH-35794)
                    // Remove loaded assemblies using filename as comparison. On systems
                    // where the same assembly is located in multiple search path locations
                    // we will start throwing exceptions when attempting to load those
                    // assemblies (even if they are not the ones we are looking for).
                    string filename = Path.GetFileName(loaded_assemblies[i].Location);
                    for (int j = potential_files.Count - 1; j >= 0; j--)
                    {
                        string potential_filename = Path.GetFileName(potential_files[j]);
                        if (string.Compare(filename, potential_filename, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            potential_files.RemoveAt(j);
                        }
                    }
                }
                catch { }
            }

#if RHINO_SDK
            // 7 Feb 2017 S. Baer (RH-30818)
            // Remove native DLLs from the list of potentials
            for (int i = potential_files.Count - 1; i >= 0; i--)
            {
                if (!HostUtils.IsManagedDll(potential_files[i]))
                {
                    potential_files.RemoveAt(i);
                }
            }
#endif

            // Sort all potential files based on fuzzy name matches.
            FuzzyComparer fuzzy = new FuzzyComparer(searchname);
            potential_files.Sort(fuzzy);

            // 23 August 2012 S. Baer
            // Make sure that at least part of the searchname matches part of the filename
            // Just use the first 5 characters as a required pattern in the filename
            const int length_match        = 5;
            string    must_be_in_filename = searchname.Substring(0, searchname.Length > length_match ? length_match : searchname.Length);

            Assembly asm = null;
            foreach (string file in potential_files)
            {
                if (file.IndexOf(must_be_in_filename, StringComparison.InvariantCultureIgnoreCase) == -1)
                {
                    continue;
                }
                asm = TryLoadAssembly(file, searchname);
                if (asm != null)
                {
                    break;
                }
            }

            if (m_match_dictionary == null)
            {
                m_match_dictionary = new Dictionary <string, Assembly>();
            }
            if (!m_match_dictionary.ContainsKey(args.Name))
            {
                m_match_dictionary.Add(args.Name, asm);
            }

            return(asm);
        }