C# 从dll加载插件
我已经开始使用一个简单的插件加载器,它监视一个目录,并在其中的dll包含IPlugin接口时加载插件C# 从dll加载插件,c#,.net,plugins,dll,.net-assembly,C#,.net,Plugins,Dll,.net Assembly,我已经开始使用一个简单的插件加载器,它监视一个目录,并在其中的dll包含IPlugin接口时加载插件 public class PluginLoader : Dictionary<string, IPlugin> { private FileSystemWatcher watcher; private string pluginPath; public PluginLoader() : base() {
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;
}
}
}
我只是不明白为什么。所以我的问题是:为什么在第二个例子中插件最终是空的
解决方案:
问题是我有两种不同的
IPlugin
类型,因为它的程序集存在于两个不同的位置。因此,删除plugin目录中的Framework.Lib.dll
解决了这个问题。我能想到的唯一原因是该类型实现了一个IPlugin
,它具有相同的名称空间,但来自不同的程序集。typeof(IPlugin).FullName将在插件加载程序和插件之间匹配,但实现的类型仍然不等于预期的类型
第一个示例与完全相同的类型匹配,在第二个示例中,您通过FullName
进行匹配,它只包括名称空间,而不包括从中加载类型的程序集
要确定是否是这种情况,请尝试记录以下值:
bool matches = typeof(IPlugin).IsAssignableFrom(type);
string expected = typeof(IPlugin).AssemblyQualifiedName;
string actual = type.GetInterface(typeof(IPlugin).FullName).AssemblyQualifiedName;
typeof(IPlugin)。IsAssignableFrom(type)
可能是您首先要查找的内容。成功加载插件后,使用break
停止对其余类型的迭代。预期值等于实际值,但匹配值为false。插件加载器在“Framework”程序集中,IPlugin接口在“Framework.Lib”程序集中,我的测试插件(“test”程序集)引用“Framework.Lib”并实现IPlugin
和stringactual=type.GetInterface(typeof(IPlugin).FullName).Location代码>?如果IsAssignableFrom()
返回false,那么第一个示例也将导致null。示例1中的第一个匹配类型是否与示例2中的第一个匹配类型相同?是的,位置不同。。第一个位置是\Framework.Lib.dll
,第二个位置是\plugins\testplugin\Framework.Lib.dll
。你是对的,第一个例子也应该返回false。现在它确实返回false。我也不知道我“弄坏”了什么。如果你从插件目录中删除Framework.Lib.dll
,它还会运行吗?当然会!现在是语句type.GetInterface(typeof(IPlugin.FullName)!=null
,type.GetInterfaces().Count(iType=>iType==typeof(IPlugin))==1
,typeof(IPlugin)。IsAssignableFrom(type)
为真。我想我现在明白了。。谢谢
bool matches = typeof(IPlugin).IsAssignableFrom(type);
string expected = typeof(IPlugin).AssemblyQualifiedName;
string actual = type.GetInterface(typeof(IPlugin).FullName).AssemblyQualifiedName;