用C#编写插件或插件框架

本文关键字:插件 框架 | 更新日期: 2023-09-27 18:21:36

我正在用C#编写一个Addin框架,我想知道如何在不需要重新启动应用程序的情况下使Addin不可加载。

我听说过AppDomains,但它们是如何工作的?Addin是否可以添加可扩展性类,并在主AppDomain中由接口调用,但仍然不可加载,并调用清理代码,导致这些类在没有该程序集位于主AppDomain的情况下被删除?

或者是否有其他方法可以实现不可卸载的加载项,但除了AppDomain之外的IIRC,您无法卸载程序集。

如果可能的话,我还希望插件引擎与Mono兼容,所以任何答案都尽量与Mono保持兼容。

用C#编写插件或插件框架

您可能想看看Mono.Addins。这里有一些好看的示例,下面是一些详细信息:。

以下代码是外接程序主机应用程序的基本示例。此应用程序运行一组命令,这些命令可以通过加载项:

using System;
using Mono.Addins;
[assembly:AddinRoot ("HelloWorld", "1.0")]
class MainClass
{
    public static void Main ()
    {
        AddinManager.Initialize ();
        AddinManager.Registry.Update ();
        foreach (ICommand cmd in AddinManager.GetExtensionObjects<ICommand> ())
            cmd.Run ();
    }
}

上面例子的扩展点可以这样声明:

using Mono.Addins;
[TypeExtensionPoint]
public interface ICommand
{
    void Run ();
}

扩展上述扩展点的插件如下所示:

using System;
using Mono.Addins;
[assembly:Addin]
[assembly:AddinDependency ("HelloWorld", "1.0")]
[Extension]
public class HelloCommand: ICommand
{
    public void Run ()
    {
        Console.WriteLine ("Hello World!");
    }
}

动态加载插件/外接程序

您没有明确询问如何动态加载外接程序或插件,但您可以在StackOverflow.com上看到这个问题(以及我的答案),了解如何做到这一点

卸载插件和外接程序

我知道只有一种方法可以卸载动态加载的插件和外接程序:在单独的AppDomain中加载外接程序,然后卸载AppDomain。有关更多信息,请参阅MSDN上的这篇文章。

现有的外接程序/插件框架

为什么要重新发明已经存在的东西?我知道两个插件框架。

  • Mono.Add-ins——正如伊恩的回答中提到的
  • 托管外接程序框架(MAF)-这是System.AddIn命名空间

有些人将托管可扩展性框架(MEF)称为插件或外接程序框架,但事实并非如此。有关更多信息,请参阅此StackOverflow.com问题和此StackOverflow.com问题。

"卸载"外接程序有两部分。

  1. 注销加载项,使其不"连接"到您的程序(它没有连接到任何事件,持有任何资源锁,主程序在任何时候都不需要或调用它,并且没有主动运行任何代码)。

  2. 卸载包含加载项代码的程序集。

第一部分完全由你控制——如果你的插件订阅了一个事件,那么当你要求它关闭时,它必须取消订阅。如果你的程序为加载项创建了按钮和菜单项,那么它必须知道它们,并且能够在加载项关闭时删除它们。等

这取决于你来决定插件是否对此负责(在这种情况下,如果不正确清理,流氓插件可能会关闭整个应用程序),或者addin框架是否必须提供连接到主应用程序的机制,以便能够自动清理应用程序和addin之间的所有链接(即在更安全的"沙盒"中运行addin,在那里它不太可能对应用程序或其他addin的稳定性产生不利影响)。

一旦插件被关闭,它将完全休眠,然后卸载它将是安全的。(然而,除非你想在程序运行时更新插件dll,否则你可能会发现你甚至不需要卸载插件-简单地禁用它就可以满足你的需求)