一尘不染

编写C#插件系统

c#

我正在尝试编写一个插件系统,以为我的应用程序提供某些可扩展性,以便某人可以为该应用程序编写一个或多个插件,而无需接触主应用程序的代码(并且有可能破坏某些内容)。

我已经编写了基本的“ IPlugin”接口(自动柜员机,尚未执行任何操作)

这是我的加载方式:

public static void Load()
{
    // rawr: http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx
    String[] pluginFiles = Directory.GetFiles(Plugins.PluginsDirectory, "*.dll");
    foreach (var plugin in pluginFiles)
    {
        Type objType = null;
        try
        {
            //Assembly.GetExecutingAssembly().GetName().Name
            MessageBox.Show(Directory.GetCurrentDirectory());
            Assembly asm = Assembly.Load(plugin);
            if (asm != null)
            {
                objType = asm.GetType(asm.FullName);
                if (objType != null)
                {
                    if (typeof(IPlugin).IsAssignableFrom(objType))
                    {
                        MessageBox.Show(Directory.GetCurrentDirectory());
                        IPlugin ipi = (IPlugin)Activator.CreateInstance(objType);
                        ipi.Host = Plugins.m_PluginsHost;
                        ipi.Assembly = asm;
                    }
                }
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString(), "Unhandled Exception! (Please Report!)", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
        }
    }
}

一位朋友试图提供帮助,但我真的不明白出了什么问题。

插件的文件夹结构如下:

\
\插件\

所有插件都在[root]目录中引用了一个名为“ Lab.Core.dll”的.dll,并且由于加载了重复的引用,因此它在Plugins目录中不存在。

该插件系统是从Lab.Core.dll加载的,该文件也被我的可执行文件引用。Lab.Core.dll中也包含“
IPlugin”类型。顾名思义,Lab.Core.dll是我的应用程序的核心。

编辑:

问题:为什么/我要得到什么例外,我该如何解决?

最终编辑:

好的,所以我看了一个朋友为TF2调节器编写的源代码后,决定重新编写它。

这是我得到的,它可以正常工作:

    public class TestPlugin : IPlugin {
    #region Constructor

    public TestPlugin() {
        //
    }

    #endregion

    #region IPlugin Members

    public String Name {
        get {
            return "Test Plugin";
        }
    }

    public String Version {
        get {
            return "1.0.0";
        }
    }

    public String Author {
        get {
            return "Zack";
        }
    }

    public Boolean OnLoad() {
        MessageBox.Show("Loaded!");
        return true;
    }

    public Boolean OnAllLoaded() {
        MessageBox.Show("All loaded!");
        return true;
    }

    #endregion
}

        public static void Load(String file) {
        if (!File.Exists(file) || !file.EndsWith(".dll", true, null))
            return;

        Assembly asm = null;

        try {
            asm = Assembly.LoadFile(file);
        } catch (Exception) {
            // unable to load
            return;
        }

        Type pluginInfo = null;
        try {
            Type[] types = asm.GetTypes();
            Assembly core = AppDomain.CurrentDomain.GetAssemblies().Single(x => x.GetName().Name.Equals("Lab.Core"));
            Type type = core.GetType("Lab.Core.IPlugin");
            foreach (var t in types)
                if (type.IsAssignableFrom((Type)t)) {
                    pluginInfo = t;
                    break;
                }

            if (pluginInfo != null) {
                Object o = Activator.CreateInstance(pluginInfo);
                IPlugin plugin = (IPlugin)o;
                Plugins.Register(plugin);
            }
        } catch (Exception) {
        }
    }

    public static void LoadAll() {
        String[] files = Directory.GetFiles("./Plugins/", "*.dll");
        foreach (var s in files)
            Load(Path.Combine(Environment.CurrentDirectory, s));

        for (Int32 i = 0; i < Plugins.List.Count; ++i) {
            IPlugin p = Plugins.List.ElementAt(i);
            try {
                if (!p.OnAllLoaded()) {
                    Plugins.List.RemoveAt(i);
                    --i;
                }
            } catch (Exception) {
                Plugins.List.RemoveAt(i);
                --i;
            }
        }
    }

阅读 928

收藏
2020-05-19

共1个答案

一尘不染

听起来您有一个循环参考。您说您的插件引用了Lab.Core.DLL,但是您也说这些插件是从Lab.Core.DLL加载的。

我是不是误会了这里发生的事情?

编辑:确定,现在您已经将问题添加到问题中了…

您需要使Lab.Core.DLL可被加载的插件访问,因为它是依赖项。通常,这意味着将其放在同一目录或GAC中。

我怀疑这里存在更深层次的设计问题,但这是您的直接问题。

2020-05-19