将MEF与C#一起使用,如何从插件中调用主机上的方法?

我正在尝试使用Managed Extensibility Framework(MEF)框架向我的C#应用​​程序添加插件可扩展性,到目前为止它还可以; 我有我的主/主机应用程序从定义的文件夹加载插件,并可以从主应用程序调用他们的方法等。 宿主应用程序和插件都引用了一个单独的dll程序集,其中包含所有项目通用的接口。

这工作正常,我可以调用/与主应用程序的插件交互。 但是,我也希望能够插件中与宿主应用程序进行交互,但似乎无法了解这是如何完成的。

我希望能够从我的插件中获取/设置/执行主应用程序中的导出属性和方法。 目前我只能从主应用程序“发言”到插件,而不是相反。

我的代码到目前为止:

接口DLL

namespace MefContracts { [InheritedExport] public interface IPlugin { String DoWork(); } public class Class1 { public IPlugin plugin { get; set; } } } 

主要/主机应用程序

 namespace MyMEF { class clsMEF { private CompositionContainer _container; [Import(typeof(MefContracts.IPlugin))] public MefContracts.IPlugin plugin; public clsMEF() { Compose(); } void Compose() { var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new DirectoryCatalog("..\\..\\Extensions")); _container = new CompositionContainer(catalog); try { this._container.ComposeParts(this); } catch (CompositionException compositionException) { Console.WriteLine(compositionException.ToString()); } } } void Main() { clsMEF myMef = new clsMEF(); MessageBox.Show(myMef.plugin.DoWork()); } } 

插入

 namespace MefPlugin { [Export] public class Class1 : MefContracts.IPlugin { public String DoWork() { return "Plugin called"; } } } 

您可以在合同程序集中添加主机接口。 例如:

 [InheritedExport] public interface IHost { string Version { get; } } 

然后将类型为IHost的属性添加到IPlugin接口:

 [InheritedExport] public interface IPlugin { IHost Host { get; } String DoWork(); } 

最后,每个插件都需要使用MEF的ImportAttribute来装饰Host属性:

 [Import(typeof(IHost))] public IHost Host { get; } 

经过多次播放和反复试验,我发现我遇到的问题是我没有将当前正在执行的程序集( System.Reflection.Assembly.GetExecutingAssembly() )与插件的程序集一起添加到主机的程序集目录中。

非常感谢@PanosRontogiannis让我走上了正确的路线 – 一旦正确添加了assembly,这个答案就会非常出色。

以下是其他有需要的工作代码:

接口DLL

 using System.ComponentModel.Composition; namespace MefContracts { [InheritedExport] public interface IPlugin { String Work(String input); } [InheritedExport] public interface IHost { string Version { get; } } } 

主机应用程序

 using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; namespace MyMEF { [Export] public class Class1 : MefContracts.IHost { public String Version { get { return "v1.00"; } } } class clsMEF { private CompositionContainer _container; [Import(typeof(MefContracts.IPlugin))] public MefContracts.IPlugin plugin; public clsMEF() { Compose(); } void Compose() { var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new DirectoryCatalog("..\\..\\Extensions")); catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); // <-- THIS WAS THE MISSING PIECE _container = new CompositionContainer(catalog); try { this._container.ComposeParts(this); } catch (CompositionException compositionException) { Console.WriteLine(compositionException.ToString()); } } } static class Program { static void Main() { clsMEF myMef = new clsMEF(); MessageBox.Show(myMef.plugin.Work("My Input")); } } } 

插入

 using System.ComponentModel.Composition; namespace MefPlugin { [Export] public class Class2 : MefContracts.IPlugin { [Import(typeof(MefContracts.IHost))] public MefContracts.IHost Host; public String Work(String input) { return "Plugin Called (Input: " + input + "). Host Application Version: " + input + Host.Version; } } }