[英]Loading of plugin from dll
I've started on a simple plugin loader that monitors a directory and loads plugins if the dll(s) in it contain the IPlugin interface. 我从一个简单的插件加载程序开始,该加载程序监视目录并在其中的dll包含IPlugin接口的情况下加载插件。
public class PluginLoader : Dictionary<string, IPlugin>
{
private FileSystemWatcher watcher;
private string pluginPath;
public PluginLoader()
: base()
{
pluginPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "plugins");
if (!Directory.Exists(pluginPath))
Directory.CreateDirectory(pluginPath);
watcher = new FileSystemWatcher(pluginPath, "*.dll");
watcher.IncludeSubdirectories = true;
watcher.Created += watcher_Created;
watcher.EnableRaisingEvents = true;
}
private void watcher_Created(object sender, FileSystemEventArgs e)
{
LoadPlugin(e.FullPath);
}
private void LoadPlugin(string path)
{
IPlugin plugin = null;
Assembly assembly = Assembly.LoadFrom(path);
foreach (Type type in assembly.GetExportedTypes())
{
if (type.IsClass && type.GetInterfaces().Count(iType => iType == typeof(IPlugin)) == 1)
{
ConstructorInfo constructor = type.GetConstructor(new Type[] { });
object instance = constructor.Invoke(new object[] { });
plugin = instance as IPlugin;
// plugin is now not null
}
}
if (plugin != null && !this.ContainsKey(plugin.PluginName))
{
this[plugin.PluginName] = plugin;
}
}
}
This version of LoadPlugin() works, the plugin variable ends up being != null. 此版本的LoadPlugin()可以工作,插件变量最终为!= null。 This one, however, does not work:
但是,这不起作用:
private void LoadPlugin(string path)
{
IPlugin plugin = null;
Assembly assembly = Assembly.LoadFrom(path);
foreach (Type type in assembly.GetExportedTypes())
{
if (type.IsClass && type.GetInterface(typeof(IPlugin).FullName) != null)
{
ConstructorInfo constructor = type.GetConstructor(new Type[] { });
object instance = constructor.Invoke(new object[] { });
plugin = instance as IPlugin;
// plugin is still null
}
}
if (plugin != null && !this.ContainsKey(plugin.PluginName))
{
this[plugin.PluginName] = plugin;
}
}
I just don't understand why. 我只是不明白为什么。 So my question is: Why does plugin end up being null in the second example?
所以我的问题是:为什么在第二个示例中插件最终会为null?
Solution: Problem was that I had two different IPlugin
types because its assembly existed in two different locations. 解决方案:问题是我有两种不同的
IPlugin
类型,因为它的组件存在于两个不同的位置。 So deleting the Framework.Lib.dll
in the plugin directory solved it. 因此,删除插件目录中的
Framework.Lib.dll
解决该问题。
The only reason I can think of is that the type implements an IPlugin
with the same namespace but from a different assembly. 我能想到的唯一原因是该类型实现的
IPlugin
具有相同的名称空间,但来自不同的程序集。 The typeof(IPlugin).FullName
would then match between your plugin loader and the plugin, but the implemented type still does not equal the expected type. 然后,
typeof(IPlugin).FullName
将在插件加载程序和插件之间匹配,但是实现的类型仍然不等于预期的类型。
The first example does match the exact same type, in the second example you're matching by the FullName
which only includes the namespace, not the assembly a type is loaded from. 第一个示例确实匹配完全相同的类型,在第二个示例中,您是通过
FullName
进行匹配的, FullName
仅包括名称空间,而不是从中加载类型的程序集。
To determine whether this is the case, try log the following value: 要确定是否是这种情况,请尝试记录以下值:
bool matches = typeof(IPlugin).IsAssignableFrom(type);
string expected = typeof(IPlugin).AssemblyQualifiedName;
string actual = type.GetInterface(typeof(IPlugin).FullName).AssemblyQualifiedName;
typeof(IPlugin).IsAssignableFrom(type)
is probably what you were looking for in the first place. typeof(IPlugin).IsAssignableFrom(type)
可能首先是您要寻找的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.