用C#编写插件或插件框架
本文关键字:插件 框架 | 更新日期: 2023-09-27 18:21:36
我正在用C#编写一个Addin框架,我想知道如何在不需要重新启动应用程序的情况下使Addin不可加载。
我听说过AppDomains,但它们是如何工作的?Addin是否可以添加可扩展性类,并在主AppDomain中由接口调用,但仍然不可加载,并调用清理代码,导致这些类在没有该程序集位于主AppDomain的情况下被删除?
或者是否有其他方法可以实现不可卸载的加载项,但除了AppDomain之外的IIRC,您无法卸载程序集。
如果可能的话,我还希望插件引擎与Mono兼容,所以任何答案都尽量与Mono保持兼容。
您可能想看看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问题。
"卸载"外接程序有两部分。
-
注销加载项,使其不"连接"到您的程序(它没有连接到任何事件,持有任何资源锁,主程序在任何时候都不需要或调用它,并且没有主动运行任何代码)。
-
卸载包含加载项代码的程序集。
第一部分完全由你控制——如果你的插件订阅了一个事件,那么当你要求它关闭时,它必须取消订阅。如果你的程序为加载项创建了按钮和菜单项,那么它必须知道它们,并且能够在加载项关闭时删除它们。等
这取决于你来决定插件是否对此负责(在这种情况下,如果不正确清理,流氓插件可能会关闭整个应用程序),或者addin框架是否必须提供连接到主应用程序的机制,以便能够自动清理应用程序和addin之间的所有链接(即在更安全的"沙盒"中运行addin,在那里它不太可能对应用程序或其他addin的稳定性产生不利影响)。
一旦插件被关闭,它将完全休眠,然后卸载它将是安全的。(然而,除非你想在程序运行时更新插件dll,否则你可能会发现你甚至不需要卸载插件-简单地禁用它就可以满足你的需求)