【问题标题】:Writing C# Plugin System编写 C# 插件系统
【发布时间】:2010-11-07 10:23:42
【问题描述】:

我正在尝试编写一个插件系统,以便为我的应用程序提供一些可扩展性,以便有人可以为该应用程序编写插件,而无需接触主应用程序的代码(并冒着破坏某些东西的风险)。

我已经编写了基本的“IPlugin”接口(atm,尚未实现)

这是我的加载方式:

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 加载的,我的可执行文件也引用了它。类型“IPlugin”也在 Lab.Core.dll 中。 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;
            }
        }
    }

【问题讨论】:

  • 我注意到您实际上并没有提出问题,您只是描述了您要做什么。你能用问题的形式表达你的问题吗?
  • 错误。抱歉,挂断了电话,试图解释我在做什么,但忘记了问题。 :x 我会做那个编辑。
  • 请发布您收到的完整异常,包括堆栈跟踪和任何内部异常。发布 ex.ToString() 的结果。
  • asm.GetType(asm.FullName)是什么原因?失败时 asm.FullName 的值是多少?
  • 扎克,在下面查看我的答案。为了证明这一点,请将您的插件目录配置为与可执行文件和其他 DLL 相同的目录。

标签: c# plugins extensibility


【解决方案1】:

托管可扩展性框架 (MEF) 是 .NET 中的一个新库,可以更好地重用应用程序和组件。使用 MEF,.NET 应用程序可以从静态编译转变为动态组合。如果您正在构建可扩展的应用程序、可扩展框架和应用程序扩展,那么 MEF 适合您。

http://www.codeplex.com/MEF

编辑:CodePlex 即将消失 - 代码已移至 Github 仅用于存档目的:https://github.com/MicrosoftArchive/mef

MEF 现在是 Microsoft .NET Framework 的一部分,其类型主要位于 System.Composition 下。命名空间。 MEF 有两个版本

  • System.ComponentModel.Composition,随 .NET 4.0 及更高版本一起提供。这提供了已在 Visual Studio 中使用的标准扩展模型。此版本 MEF 的文档可以在 here 找到
  • System.Compostion 是 MEF 的轻量级版本,已针对静态合成场景进行了优化,并提供更快的合成。它也是唯一的 MEF 版本,它是一个可移植的类库,可用于手机、商店、桌面和 Web 应用程序。此版本的 MEF 可通过NuGet 获得,文档可通过here 获得

【讨论】:

  • 这在不使用 MEF 的情况下应该是可能的。
  • 当然可以不使用MEF。 MEF 没有什么神奇之处。但是 MEF 是由插件架构专家多年来设计和实现的。 (早在 2004 年 IIRC,我就对 MEF 的初始设计做了一些工作。)你真的想尝试复制专业建筑师在这个领域五年的工作成果吗?
  • 好吧,如果我的第一条评论被认为是对抗性的,我的答案没有问题。将它放在这里以知道它的存在实际上很好。不过,我希望我们能看看这个插件示例有什么问题。
  • @Brad:我和你在一起。我希望我的帖子不会让人觉得“匆忙”或绝望,哈哈。
  • @Brad- 没有框架一切皆有可能,但 MEF 看起来是评估插件场景的绝佳候选者。以我的经验,太多的开发人员在没有正确评估它们的情况下迅速放弃框架。例如,我看到很多人在可以使用 log4net 之类的东西时编写垃圾日志框架。
【解决方案2】:

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

我误解了这里发生的事情吗?

编辑:好的,现在您已将问题添加到问题中......

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

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

【讨论】:

  • 感谢您的帮助。我最终根据朋友的源代码重写了它。编辑原始帖子以包含我的解决方案。 :)
【解决方案3】:

作为一个侧面答案,我使用这两个接口来实现它

    public interface IPlugin {
        string Name { get; }
        string Description { get; }
        string Author { get; }
        string Version { get; }

        IPluginHost Host { get; set; }

        void Init();
        void Unload();

        IDictionary<int, string> GetOptions();
        void ExecuteOption(int option);
}

    public interface IPluginHost {
        IDictionary<string, object> Variables { get; }
        void Register(IPlugin plugin);
     }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多