将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; } } }