I am implementing a simple plugin architecture in an application. The plugin requirements are defined using an interface (IPlugin) that is in a *.dll that is referenced by the application and the plugin. The application has a plugin manager (also in the same *.dll) which loads the plugins by looking for all the *.dll's in a plugins folder, loads them, then checks that the plugin implements the interface. I have done this checking two different ways [previously by a simple if (plugin is IPlugin)], but neither one will recognize when a plugin implements the interface. Here's the code:
Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
foreach (Type currType in pluginAssembly.GetTypes())
{
if (currType.GetInterfaces().Contains(typeof(IPlugin)))
{
// Code here is never executing
// even when the currType derives from IPlugin
}
}
}
I used to test a particular class name ("Plugin"), but then I allowed it to cycle through all the classes in the assembly to no avail. (This follows an example that I found elsewhere.) To make this a little more complicated, there are two interfaces each of which implements the original interface (IPluginA, IPluginB). The plugin actually implements one of the more specific interfaces (IPluginB). However, I have tried it with the plugin just implementing the more general interface (IPlugin), and this still does not work.
[Edit: in response to the two responses that I first received] Yes, I have tried using IsAssignableFrom. See the following:
Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
foreach (Type currType in pluginAssembly.GetTypes())
{
if (typeof(IPlugin).IsAssignableFrom(currType))
{
string test = "test";
}
}
}
Have you tried:
typeof(IPlugin).IsAssignableFrom(currType)
Also, types implement interfaces, but they do not derive from them. The BaseType
property and IsSubclassOf
method show derivation, where IsAssignableFrom
shows derivation or implementation.
Edit: are your assemblies signed? They could be loading side-by-side versions of your assembly, and since Type
objects are compared with ReferenceEquals
, the same type in two side-by-side assemblies would be completely independent.
Edit 2: Try this:
public Type[] LoadPluginsInAssembly(Assembly otherAssembly)
{
List<Type> pluginTypes = new List<Type>();
foreach (Type type in otherAssembly.GetTypes())
{
// This is just a diagnostic. IsAssignableFrom is what you'll use once
// you find the problem.
Type otherInterfaceType =
type.GetInterfaces()
.Where(interfaceType => interfaceType.Name.Equals(typeof(IPlugin).Name, StringComparison.Ordinal)).FirstOrDefault();
if (otherInterfaceType != null)
{
if (otherInterfaceType == typeof(IPlugin))
{
pluginTypes.Add(type);
}
else
{
Console.WriteLine("Duplicate IPlugin types found:");
Console.WriteLine(" " + typeof(IPlugin).AssemblyQualifiedName);
Console.WriteLine(" " + otherInterfaceType.AssemblyQualifiedName);
}
}
}
if (pluginTypes.Count == 0)
return Type.EmptyTypes;
return pluginTypes.ToArray();
}