Question

Apologies for the dodgy question - happy to rephrase if someone has a better suggestion.

I'm trying to create an object by dynamically invoking an assembly belonging to another application.

The following PowerShell code is working nicely for me:

[Reflection.Assembly]::LoadFrom("C:\Program Files\Vendor\Product\ProductAPI.dll")
$bobject = new-object ProductAPI.BasicObject    
$bobject.AddName("Some Name") 

I'm struggling to do the same thing in C#. Based on other posts on StackOverflow I currently have this:

System.Reflection.Assembly myDllAssembly =
System.Reflection.Assembly.LoadFile("C:\\Program Files\\Vendor\\Product\\ProductAPI.dll");

System.Type BasicObjectType = myDllAssembly.GetType("ProductAPI.BasicObject");

var basicObjectInstance = Activator.CreateInstance(BasicObjectType);

The final line results in a TargetInvocationException.

{"Could not load file or assembly 'AnotherObject, Version=1.2.345.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."

It appears that the BasicObject constructor is trying to invoke AnotherObject (from AnotherObject.dll in the same folder) but can't find it.

Any tips on how to get around this?

Was it helpful?

Solution

If it can't find a dependent assembly in the usual places, you'll need to manually specify how to find them.

The two easiest ways I'm aware of for doing this:

  1. manually load the dependent assemblies in advance with Assembly.Load.

  2. handle the AssemblyResolve event for the domain which is loading the assembly with additional assembly dependencies.

Both essentially require you to know the dependencies for the assembly you're trying to load in advance but I don't think that's such a big ask.

If you go with the first option, it would also be worthwhile looking into the difference between a full Load and a reflection-only Load.

If you would rather go with 2 (which I'd recommend), you can try something like this which has the added benefit of working with nested dependency chains (eg MyLib.dll references LocalStorage.dll references Raven.Client.dll references NewtonSoft.Json.dll) and will additionally give you information about what dependencies it can't find:

AppDomain.CurrentDomain.AssemblyResolve += (sender,args) => {

    // Change this to wherever the additional dependencies are located    
    var dllPath = @"C:\Program Files\Vendor\Product\lib";

    var assemblyPath = Path.Combine(dllPath,args.Name.Split(',').First() + ".dll");

    if(!File.Exists(assemblyPath))
       throw new ReflectionTypeLoadException(new[] {args.GetType()},
           new[] {new FileNotFoundException(assemblyPath) });

    return Assembly.LoadFrom(assemblyPath);
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top