1

我正在尝试使用 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 的实现,还是我做错了什么?

4

1 回答 1

1

如果我使用单声道运行从 .NET 编译器编译的编译版本,则插件会加载两次。

发生这种情况是因为尽管您已经IPlugIn用. 目录将匹配这两个,因此导出两次。您只需要这两种方法中的一种。要么保留并且不使用 装饰任何实现,或者使用 装饰所有实现并从接口中删除。InheritedExportAttributeExportAttributeInheritedExportAttributeExportAttributeExportAttributeInheritedExportAttribute

我还没弄清楚为什么DirectoryCatalog不能在 Mono 上加载插件程序集。正如您所提到的,在 CLR 上可以正常工作。

于 2013-02-12T00:06:44.160 回答