我正在尝试使用 MEF(内置单声道的版本)作为一个简单的插件系统来扩展我的应用程序。我遵循了各种教程,这些教程在 Windows 下运行良好的 Microsofts .NET 框架,但是(相同的代码)在 linux(内核 3.7.3 - gentoo)下使用 mono-2.10.9 失败。
我创建了一个接口,所有导出(我的扩展)都必须在外部程序集中引用:
namespace PlugInInterface {
[InheritedExport]
public interface IPlugIn {
void Execute();
}
}
然后我创建了一个 Hostapplication(一个 ConsoleApplication),它也引用了 PluginInterface:
namespace Host {
class MainClass {
private static PluginHost plugins;
public static void Main(string[] args) {
plugins = new PluginHost();
foreach(IPlugIn plugin in plugins.plugins) {
plugin.Execute();
}
}
}
class PluginHost{
[ImportMany(typeof(IPlugIn))]
public List<IPlugIn> plugins = new List<IPlugIn>();
public PluginHost() {
var catalog = new DirectoryCatalog("PlugIns");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}
以及一个在 Debug 目录的“PlugIns”子文件夹中编译的扩展,其中放置了主机应用程序:
namespace TestPlugin1 {
[Export(typeof(IPlugIn))]
public class TestPlugin1 : IPlugIn {
public void Execute() {
Console.WriteLine("Hello, my Name is TestPlugin_Implementation1");
}
}
}
DirectoryCatalog加载插件的文件(“./PlugIns/TestPlugin1.dll”),但它不将其识别为导出(“部件”),因此plugins
列表保持为空。如果我将 PluginFile 放在应用程序的工作目录中并将 DirectoryList 更改为:
var catalog = new DirectoryCatalog("");
如果我使用单声道运行从 .NET 编译器编译的编译版本,则插件会加载两次。
我尝试通过加载插件文件手动替换DirectoryCatalogSystem.Reflection.Assembly.LoadFile(...);
,然后使用AssemblyCatalogs加载所有找到的程序集:
class PluginHost{
[ImportMany(typeof(IPlugIn))]
public List<IPlugIn> plugins = new List<IPlugIn>();
public PluginHost() {
List<AssemblyCatalog> catalogs = new List<AssemblyCatalog>();
foreach(string plfile in Directory.GetFiles("PlugIns", "*.dll", SearchOption.AllDirectories)) {
catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.LoadFile(plfile)));
}
var container = new CompositionContainer(new AggregateCatalog(catalogs));
container.ComposeParts(this);
}
}
这可行,但与编译的 .NET 可执行文件相同:插件加载两次。
这是单声道的错误,它是 MEF 的实现,还是我做错了什么?