1

In my application I have an interface called IPlugin. This interface is used to identify dlls in a Plugin-folder and load them at application-startup.

The IPlugin interface looks like:

public interface IPlugin
{
  string Name { get; }

  void Initialize();
}

In my main-application I've used the following code to load all dll-files which are located in the Plugins-folder:

internal List<IPlugin> LoadPlugins()
{
    List<IPlugin> plugins = new List<IPlugin>();

    foreach (string file in Directory.GetFiles("Plugins", "*.dll", SearchOption.TopDirectoryOnly))
    {
        Assembly assembly = Assembly.LoadFile(Path.GetFullPath(file));
        Type targetType = assembly.GetTypes().FirstOrDefault(type => type.GetInterfaces().Contains(typeof(IPlugin)));
        if (targetType != null)
        {
            IPlugin plugin = Activator.CreateInstance(targetType) as IPlugin;
            if (plugin != null)
            {
                plugins.Add(plugin);
            }
        }
    }
    return plugins;
}

This just works fine for dlls which don't need another dll.

Now I've created a plugin which has two dlls.

  • Users.Interface
  • Users.Plugin

Users.Plugin has a references to Users.Interface. In the Users.Plugin there is an implementation of IPlugin. So the Users.Plugin-Dll will be identified to be loaded by my LoadPlugins-Method.

Now I get a ReflectionTypeLoadException with the Users.Plugin-File at the line:

Type targetType = assembly.GetTypes().FirstOrDefault(type => type.GetInterfaces().Contains(typeof(IPlugin)));

The LoaderException tells me, that the assembly Users.Interface or a reference could not be found.

I've tried to use Assembly.LoadFrom(...) but this doesn't work either.

I've also tried this approach with no success.

Any ideas how I can load assemblies with all dependencies and then create an instance?

Tomtom
  • 9,087
  • 7
  • 52
  • 95
  • Did you try implementing the AppDomain.CurrentDomain.AssemblyResolve event handler? This one is called when an assembly cannot be resolved. – PepitoSh Jun 05 '18 at 07:04
  • No, didn't tried it yet. What do I have to do in the EventHandler when the assemly is resolved where another assembly is references? – Tomtom Jun 05 '18 at 08:21
  • This doesn't answer your question directly, but I too used `Activator` for plugin systems until I was told about MEF. See my answer here for the before & after of a plugin system, one using `Activator` and one using MEF which delegates the loading responsibility to Microsoft https://stackoverflow.com/a/43607694/5062791 – ColinM Jun 05 '18 at 08:39

1 Answers1

1

A code snippet to resolve assemblies at runtime:

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {

    String DllName = new AssemblyName(args.Name).Name + ".dll";

    return Assembly.LoadFile(DllName);
}

Set it at the beginning of your your plugin initializer:

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

No error checking is included.

The actual assembly can be loaded from any path, the example above loads it from the current working directory. You can load it from embedded resource as well.

PepitoSh
  • 1,774
  • 14
  • 13