clamp
clamp

Reputation: 34046

.NET add directory for dependencies at runtime

From my main C# application i instantiate another application via reflection.

assembly.CreateInstance( ... )

however this other assembly relies on DLLs which are in another directory than the executing assembly. how can i add this directory to the lookup path?

Upvotes: 0

Views: 528

Answers (1)

Patrick from NDepend team
Patrick from NDepend team

Reputation: 13842

Here is how we implement this need in NDepend.PowerTools. These are a set of tools based on NDepend.API. The DLL NDepend.API.dll is in the directory .\Lib while the NDepend.PowerTools.exe assembly is inn the directory .\.

The NDepend.PowerTools.exe Main() method looks like:

[STAThread]
static void Main() {    
   AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolverHelper.AssemblyResolveHandler;
   MainSub();
}

// MainSub() is here to avoids that the Main() method uses something
// from NDepend.API without having registered AssemblyResolveHandler
[MethodImpl(MethodImplOptions.NoInlining)]
static void MainSub() {
   ...

And the AssemblyResolverHelper class is:

using System;
using System.Diagnostics;
using System.Reflection;


namespace NDepend.PowerTools {
   internal static class AssemblyResolverHelper {
      internal static Assembly AssemblyResolveHandler(object sender, ResolveEventArgs args) {
         var assemblyName = new AssemblyName(args.Name);
         Debug.Assert(assemblyName != null);
         var assemblyNameString = assemblyName.Name;
         Debug.Assert(assemblyNameString != null);

         // Special treatment for NDepend.API and NDepend.Core because they are defined in $NDependInstallDir$\Lib
         if (assemblyNameString != "NDepend.API" &&
             assemblyNameString != "NDepend.Core") {
            return null;
         }
         string binPath =
              System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) +
              System.IO.Path.DirectorySeparatorChar +
              "Lib" +
              System.IO.Path.DirectorySeparatorChar;

         const string extension = ".dll";

         var assembly = Assembly.LoadFrom(binPath + assemblyNameString + extension);
         return assembly;
      }
   }
}

This works within a single AppDomain. I wouldn't use an extra AppDomain here if not needed. AppDomain is a pretty costly facility (in terms of performance) + the thread that jumps the AppDomains boundaries, has to serialize/unserialize in/out data to feed your assembly code, and this can be a headache.

The only advantage of AppDomain is that it lets unload loaded assemblies. So if you expect load/unload assemblies on a regular basis within the life of your main AppDomain, using some extra temporary AppDomain is the way to go.

Upvotes: 1

Related Questions