简体   繁体   English

从DLL加载插件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM