[英]Using MEF with C#, how do I call methods on the host, from the plugin?
I am trying to add plugin extensibility to my C# application using the Managed Extensibility Framework (MEF) framework, and so far it is going ok; 我正在尝试使用Managed Extensibility Framework(MEF)框架向我的C#应用程序添加插件可扩展性,到目前为止它还可以; I have my main/host application loading plugins from a defined folder, and can call their methods etc. from the main application. 我有我的主/主机应用程序从定义的文件夹加载插件,并可以从主应用程序调用他们的方法等。 Both the host application and the plugins reference a seperate dll assembly which contains the interfaces common to all projects. 宿主应用程序和插件都引用了一个单独的dll程序集,其中包含所有项目通用的接口。
This is working fine and I can call/interact with the plugins from the main application. 这工作正常,我可以从主应用程序调用/与插件交互。 However, I also would like to be able to interact with the host application from the plugins, but can't seem to find out how this is done. 但是,我也希望能够从插件中与主机应用程序进行交互,但似乎无法了解如何完成此操作。
I would like to be able to get/set/execute exported properties and methods in the main app from my plugins. 我希望能够从我的插件中获取/设置/执行主应用程序中的导出属性和方法。 Currently I am only able to 'speak' to the plugins from the main app, not the other way around as well. 目前我只能从主应用程序“说出”插件,而不是相反。
My code thus far: 我的代码到目前为止:
Interface DLL 接口DLL
namespace MefContracts
{
[InheritedExport]
public interface IPlugin
{
String DoWork();
}
public class Class1
{
public IPlugin plugin { get; set; }
}
}
Main/Host Application 主要/主机应用程序
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());
}
}
Plugin 插入
namespace MefPlugin
{
[Export]
public class Class1 : MefContracts.IPlugin
{
public String DoWork()
{
return "Plugin called";
}
}
}
You could add a host interface in the contracts assembly. 您可以在合同程序集中添加主机接口。 For example: 例如:
[InheritedExport]
public interface IHost
{
string Version { get; }
}
Then add a property of type IHost to the IPlugin interface: 然后将类型为IHost的属性添加到IPlugin接口:
[InheritedExport]
public interface IPlugin
{
IHost Host { get; }
String DoWork();
}
Finally each plug-in will need to decorate the Host property with MEF's ImportAttribute: 最后,每个插件都需要使用MEF的ImportAttribute来装饰Host属性:
[Import(typeof(IHost))]
public IHost Host { get; }
After much playing and trial and error, I found the issue I was having was I had not added the current executing assembly ( System.Reflection.Assembly.GetExecutingAssembly()
) to the host's assembly catalogue along with the plugin's assemblies. 经过多次播放和反复试验,我发现我遇到的问题是我没有将当前正在执行的程序集( System.Reflection.Assembly.GetExecutingAssembly()
)与插件的程序集一起添加到主机的程序集目录中。
Many thanks to @PanosRontogiannis who got me on the right lines - that answer worked brilliantly once the assembly was properly added. 非常感谢@PanosRontogiannis让我走上了正确的路线 - 一旦正确添加了组件,这个答案就会非常出色。
Here is the working code for others in need: 以下是其他有需要的工作代码:
Interface DLL 接口DLL
using System.ComponentModel.Composition;
namespace MefContracts
{
[InheritedExport]
public interface IPlugin
{
String Work(String input);
}
[InheritedExport]
public interface IHost
{
string Version { get; }
}
}
Host Application 主机应用程序
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"));
}
}
}
Plugin 插入
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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.