.NET 添加了可能符合要求的“托管插件框架”。它具有以下特点:
-
隔离。如果需要,插件在自己的 AppDomain 中运行,如果您需要这种级别的隔离,甚至可以在自己的自己的进程中运行。
-
合同沟通。您设置合同,这是您分发给插件作者的唯一内容。他们不需要知道您的应用程序的任何其他方面。
-
发现。具有用于从装满程序集的文件夹中嗅出插件的内置机制。
-
安全。加载插件时会自动应用 CASPOL 集。有一些内置选项可以让这变得简单(请参阅AddInSecurityLevel Enum)。
大多数隔离方法也限制了通信和 UI 集成。 MAF 试图绕过这些限制。它要求您设置合同通信管道,但会执行您通常必须自己完成的大部分工作。
例如,将在两个独立进程中运行的 UI 片段拼接在一起(这很神奇),或者能够跨 AppDomain 或进程引发事件。这些事情并非微不足道,但 MAF 在这方面有很大帮助。
示例
这是一个简单的例子。作为“Shell”作者,您将向您的插件作者提供合同。这是一个典型的合约(它只是一个抽象类):
public abstract class Calculator
{
public abstract double Add(double a, double b);
public abstract double Subtract(double a, double b);
public abstract double Multiply(double a, double b);
public abstract double Divide(double a, double b);
}
如果插件作者想写一个插件,他们可以简单地继承这个合约并添加“Addin”属性:
[AddIn("Sample Calculator AddIn", Version="1.0.0.0")]
public class SampleCalculatorAddIn : Calculator
{
public override double Add(double a, double b)
{
return a + b;
}
public override double Subtract(double a, double b)
{
return a-b;
}
public override double Multiply(double a, double b)
{
return a * b;
}
public override double Divide(double a, double b)
{
return a / b;
}
}
以下是加载这些插件并与它们交互的方式:
// In this sample we expect the AddIns and components to
// be installed in the current directory
String addInRoot = Environment.CurrentDirectory;
// Check to see if new AddIns have been installed
AddInStore.Rebuild(addInRoot);
// Look for Calculator AddIns in our root directory and
// store the results
Collection<AddInToken> tokens =
AddInStore.FindAddIns(typeof(Calculator), addInRoot);
// Ask the user which AddIn they would like to use
AddInToken calcToken = ChooseCalculator(tokens);
// Activate the selected AddInToken in a new AppDomain set sandboxed
// in the internet zone. You can find out what this gives access
// to by running "mscorcfg.msc", but essentially this will limit
// any access to the filesystem and other obvious OS services.
// Use of reflection is also very limited in this zone.
Calculator calculator =
calcToken.Activate<Calculator>(AddInSecurityLevel.Internet);
// Run the read-eval-print loop
RunCalculator(calculator);
这就是要点。显然不止这些,但你明白了。
进一步阅读
很好的介绍文章
https://web-beta.archive.org/web/20140820145919/http://msdn.microsoft.com/en-us/magazine/cc163476.aspx
MSDN 上的概述
http://msdn.microsoft.com/en-us/library/bb384200.aspx
Codeplex 上的 System.Addin(大量样本)
http://www.codeplex.com/clraddins
工具
Pipeline Builder(帮助在 shell 和插件之间生成通信管道)
http://clraddins.codeplex.com/wikipage?title=Pipeline%20Builder&referringTitle=Home
System.Addin 的 Fx-Cop 规则
http://clraddins.codeplex.com/wikipage?title=Add-in%20FxCop%20Rules&referringTitle=Home