Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving Assemblies, the fuzzy way

Here's the setup:

A pure DotNET class library is loaded by an unmanaged desktop application. The Class Library acts as a plugin. This plugin loads little baby plugins of its own (all DotNET Class Libraries), and it does so by reading the dll into memory as a byte-stream, then

Assembly asm = Assembly.Load(COFF_Image);

The problem arises when those little baby plugins have references to other dlls. Since they are loaded via the memory rather than directly from the disk, the framework often cannot find these referenced assemblies and is thus incapable of loading them.

I can add an AssemblyResolver handler to my project and I can see these referenced assemblies drop past. I have a reasonably good idea about where to find these referenced assemblies on the disk, but how can I make sure that the Assmebly I load is the correct one?

In short, how do I reliably go from the System.ResolveEventArgs.Name field to a dll file path, presuming I have a list of all the folders where this dll could be hiding)?

like image 919
David Rutten Avatar asked Apr 28 '10 12:04

David Rutten


2 Answers

When I have used this in the past we have just compared the file name with the part of the ResolveEventArgs.Name that has the name. If you want to be sure that you are loading the exact same version I suppose you could check if the names match, if they do then load the assembly and then check the assemblies full name against the ResolveEventArgs.Name.

something along these lines:

string name = GetAssemblyName (args); //gets just the name part of the assembly name
foreach (string searchDirectory in m_searchDirectories)
    {
    string assemblyPath = Path.Combine (executingAssemblyPath, searchDirectory);
    assemblyPath = Path.Combine (assemblyPath, name + ".dll");        
    if (File.Exists (assemblyPath))
        {            
        Assembly assembly = Assembly.LoadFrom (assemblyPath);
        if (assembly.FullName == args.Name)
            return assembly;
        }
    }

for completeness:

private string GetAssemblyName (ResolveEventArgs args)
    {
    String name;
    if (args.Name.IndexOf (",") > -1)
        {
        name = args.Name.Substring (0, args.Name.IndexOf (","));
        }
    else
        {
        name = args.Name;
        }
    return name;
    }
like image 134
Sam Holder Avatar answered Sep 19 '22 06:09

Sam Holder


The Managed Extensibility Framework (MEF) sounds like something that'll solve all your problems. It can scan folders to locate DLLs, resolve dependencies for any depth and manages plug-in composition in general. Each part (or 'plug-in') just has to declare what it needs and what it provides, and MEF takes care of the wiring. If MEF succeeded in taming VS2010's extensibility beast, then it can handle anything.

like image 34
Allon Guralnek Avatar answered Sep 22 '22 06:09

Allon Guralnek