GetType(string) returns null after AppDomain.CurrentDomain.Load

2.9k views Asked by At

I'am building a small plugin architecture (unfortunately MEF is not an options because it needs to run on .NET 2.0). I want to be able to put dll's in a directory without recompiling the main project. My main project is a winforms application which has some dialogs to pick an implementation of an interface the main program needs.

I have a method that searches a certain directory and gives a List of locations of the dll's I want to search for Types that implement the interface.

public List<Type> GetPluginTypes()
{
  List<Type> types = new List<Type>();
  foreach (string dll in this.Plugins)
  {
    Assembly assembly;
    try
    {
      assembly = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(dll));
    }
    catch
    {
      continue;
    }
    foreach (Type type in assembly.GetExportedTypes())
    {
      if (type.IsInterface || type.IsAbstract)
        continue;

      if (typeof(IMyInterface).IsAssignableFrom(type))
       types.Add(type);
    }
  }
  return types;
}

Using this method I show the user a list of implementations, one is chosen and it's AssemblyQualifiedName is saved to a settings file.

When I start the main application, I load the AQN from the settings and load all the plugins into the AppDomain by calling the above method.

string typeName = GetSetting("MyPlugin");
GetPluginTypes(); // just to load the plugins into the app domain
Type.GetType(typeName); // allways returns null.

Here is my problem: Type.GetType(typeName), always returns null.

I used Type.GetType(typeName, true), to enforce an exception, which I got: Could not load file or assembly 'MyImpl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.":"MyImpl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}

I am clueless. I've already loaded the assembly into the AppDomain, and still Type.GetType(string) can't find it when I specify the AQN.

2

There are 2 answers

1
Jim Mischel On

Perhaps this is relevant. From the documentation for Type.GetType(String, Boolean):

If typeName includes only the name of the Type, this method searches in the calling object's assembly, then in the mscorlib.dll assembly. If typeName is fully qualified with the partial or complete assembly name, this method searches in the specified assembly.

You said that you try calling with type.AssemblyQualifiedName, but it failed. Did you check the qualified name to see if it was reasonable?

0
Michael Rätzel On

This can be solved by registering the AppDomain.AssemblyResolve event for the AppDomain which will request the assembly and make the handler return the already loaded assembly.

Here is what the handler looks like in C#:

    private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        return
            AppDomain.CurrentDomain.GetAssemblies()
            .FirstOrDefault(Kandidaat => string.Equals(Kandidaat.GetName().FullName, args.Name));
    }

a detailed explanation can be found here: https://msdn.microsoft.com/en-us//library/ff527268(v=vs.110).aspx