Dynamic Loading of .Net Assemblies

Problem: You have dependencies which can be in a number of directories outside of the directory your app is running in. DotNet AppDomains are heavy to say the least and very high in ceremony.  You do not want to deal with secondary app domain creation.

Solution: Override  AssemblyResolve event on your current app domain.

 

    public class AppDomainLoader : IAppDomainLoader
    {
       
        private ResolveEventHandler _searchAssemblyMethod = _searchDir;
        public ResolveEventHandler FindAssemblyMethod
        {
            set { _searchAssemblyMethod = value}
        }
        private static string[] _directoriesToSearch;
        private  static Assembly _searchDir(Object o, ResolveEventArgs e)
        {
            foreach (var s in _directoriesToSearch)
            {
                var filetoload = s +  e.Name.Split(‘,’)[0] + “.dll”//bad one liner that parses the first part of the assembly name and adds .dll at the end
                if (File.Exists(filetoload)) //sees if the file is even in the directory
                {
                   return Assembly.LoadFrom(filetoload);  //returns assembly once found, a bit naive and does not handle version conflicts well.
                }
            }
            return null;
          
        }
     
        public void Search(string[] directoriesToSearch)
        {
            _directoriesToSearch = directoriesToSearch; //sets directories to search to allow entry point for dynamic searching
            AppDomain.CurrentDomain.AssemblyResolve -= _searchAssemblyMethod; //cleans up previous events, may not be needed.
            AppDomain.CurrentDomain.AssemblyResolve += _searchAssemblyMethod; //registered the event

        }
    }

Now whenever there is a missing Assembly, the _searchAssemblyMethod will be fired,  and all directories given to the Search method will attempt to find an assembly with the matching name.

Related Articles:

    Post Footer automatically generated by Add Post Footer Plugin for wordpress.

    About Ryan Svihla

    I consider myself a full stack polyglot, and I have been writing a lot of JS and Ruby as of late. Currently, I'm a solutions architect at DataStax
    This entry was posted in AppDomain, DotNet, Hate. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
    • http://richarddingwall.name Richard Dingwall

      This trick is also good for including assemblies as embedded resources in WPF apps, where ilmerge doesn’t work.

    • Arnis L.

      I might sound stupid – but isn’t this the same what assembly probing provides? If so – are there any difference why this approach is supposed to be preferable?

    • http://www.lostechies.com/members/rssvihla/default.aspx Ryan Svihla

      @Arnis This is for when the default assembly probing can’t work easily. I’ve implemented this for configurable plugin architectures and most recently with a command line client for my BDD project SpecMaker.

      In all those cases the consumer of software was passing in locations to “search” for assemblies. SpecMaker.exe originally was relying on default assembly loading and this required it to be run where all assemblies needed were already placed next to it. This was a non-issue for most but some people didn’t A) want to have to copy specmaker to their build directory or B) have a spread out build structure where different components are located in different side by side directories.

      thanks again for the feedback and I hope that answers your questions.

    • http://www.lostechies.com/members/rssvihla/default.aspx Ryan Svihla

      @Arnis to answer to your second question, this is not preferable to assembly probing itself, its more like extending it.