C#插件加载器依赖/参考问题

时间:2018-09-16 12:09:59

标签: c# plugins

我有一个简单的用C#编写的插件加载程序项目作为控制台应用程序。 PluginLoader使用我的自定义抽象类MyPlugin类型在“ plugins”文件夹中查找.dll文件。 MyPlugin是一个IDisposable,包含插件的基本信息,例如Name,Author,Order。包含抽象的初始化方法。

PluginLoader将插件加载到程序集中,实例化,然后按顺序初始化它们。

我有Foo和Bar插件。 Bar引用Foo,以访问其中的一个对象(字符串Foo)。但是关于Foo组装,我在Bar中得到FileNotFoundException。问题是,Foo类已明确加载并初始化。

如果我添加

    <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="plugins" />
    </assemblyBinding>
</runtime>

这进入应用程序配置,FileNotFound异常消失了。但是然后我在Foo元素上得到了NullReferenceException。使用VisualStudio调试器,很明显实例不为null,并且所有对象都已设置。

PluginLoader代码

    class Program
{
    public static List<MyPlugin> Plugins = new List<MyPlugin>();

    static void Main(string[] args)
    {
        LoadPlugins();
        Console.ReadLine();
    }
    public static void LoadPlugins()
    {
        var pluginsDirectory = Directory.CreateDirectory("plugins");
        List<FileInfo> fileInfos = pluginsDirectory.GetFiles("*.dll").ToList();
        foreach (FileInfo fileInfo in fileInfos)
        {
            try
            {
                Assembly assembly = Assembly.Load(File.ReadAllBytes(fileInfo.FullName));
                foreach (Type type in assembly.GetExportedTypes())
                {
                    if (!type.IsSubclassOf(typeof(MyPlugin)) || !type.IsPublic || type.IsAbstract)
                        continue;

                    MyPlugin pluginInstance;

                    try
                    {
                        pluginInstance = (MyPlugin)Activator.CreateInstance(type);
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidOperationException(
                            string.Format("Could not create an instance of plugin class \"{0}\".", type.FullName), ex);
                    }
                    Plugins.Add(pluginInstance);
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                    string.Format("Failed to load assembly \"{0}\".", fileInfo.Name), ex);
            }
        }
        IOrderedEnumerable<MyPlugin> orderedPluginSelector =
            from x in Plugins
            orderby x.Order, x.Name
            select x;
        foreach (MyPlugin current in orderedPluginSelector)
        {
            try
            {
                current.Initialize();
            }
            catch (Exception ex)
            {
                // Broken plugins better stop the entire server init.
                throw new InvalidOperationException(string.Format(
                    "Plugin \"{0}\" has thrown an exception during initialization.", current.Name), ex);
            }
            Console.WriteLine($"Plugin {current.Name} initialized!");
        }

    }
}

Foo插件

public class Plugin : MyPlugin
{
    public override string Name => "Foo";
    public override string Author => "Patrikk";

    public static Plugin Instance;

    public string Foo;

    public Plugin()
    {
        Instance = this;
        Order = 0;
    }

    public override void Initialize()
    {
        Foo = "Foo";
    }
}

酒吧插件

    public class Plugin : MyPlugin
{
    public override string Name => "Bar";
    public override string Author => "Patrikk";

    public static string Bar;

    public Plugin()
    {

    }

    public override void Initialize()
    {
        Bar = "Bar";
        Console.WriteLine(Foo.Plugin.Instance.Foo + Bar);
    }
}

我真的不确定我缺少什么。 我试图创建一个PluginLoader,一个“核心”插件(Foo)和其他需要并依赖于核心插件的插件(Bar)。

0 个答案:

没有答案