我试图用C#创建一个基于插件的应用程序。现在,插件正在使用MEF进行发现。我遇到了一个问题,即主机应用程序和插件正在使用不同版本的通用库。
从高层次上讲,我想要n + 1个目录,一个用于主机,一个用于插件,并将插件或主机需要的所有文件都放在自己的文件夹中。
我有两种解决方案,一种是MEF接口,共享库和插件主机。第二个是MEF接口,共享库和插件实现。
这是我的问题的简化视图,显示出该行为:
如果我在共享库项目中更改ShowMessage的功能签名,然后仅重建插件实现解决方案,则在调用PrintInfo时会出现异常。我需要一种方法让插件主机加载一个版本,使插件实现可能具有第二个版本。
MEF接口项目
using System.ComponentModel.Composition;
namespace TestProject
{
[InheritedExport(typeof(IPlugin))]
public interface IPlugin
{
string Name { get; }
void PrintInfo();
}
}
共享库
using System.Windows.Forms;
namespace TestProject
{
public class SharedLibrary
{
#if true
public static void ShowMessage(string message)
{
MessageBox.Show(message);
}
#else
public static void ShowMessage(string[] message)
{
string msg = String.Join("\n", message);
MessageBox.Show(msg);
}
#endif
}
}
插件主机
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.Windows.Forms;
namespace TestProject
{
public partial class Form1 : Form
{
[ImportMany(typeof(IPlugin), AllowRecomposition = true)]
List<IPlugin> allPlugins { get; set; }
SharedLibrary sl = new SharedLibrary();
public Form1()
{
InitializeComponent();
AggregateCatalog catalog = new AggregateCatalog();
DirectoryCatalog pluginDir = new DirectoryCatalog(@"..\..\..\Plugin\bin\Debug");
catalog.Catalogs.Add(pluginDir);
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
private void button1_Click(object sender, EventArgs e)
{
string ver = Assembly.GetAssembly(sl.GetType()).GetName().Version.ToString();
MessageBox.Show("Presenter version = " + ver);
foreach (var plugin in allPlugins)
{
SharedLibrary.ShowMessage("Starting Plugin: " + plugin.Name);
// this explodes when the shared library in the plugin directory doesn't match
plugin.PrintInfo();
}
}
}
}
插件实现
using System.Reflection;
using System.Windows.Forms;
namespace TestProject
{
public class Plugin : IPlugin
{
public string Name { get; } = "Test Plugin";
SharedLibrary sl = new SharedLibrary();
public void PrintInfo()
{
string ver = Assembly.GetAssembly(sl.GetType()).GetName().Version.ToString();
MessageBox.Show("Plugin version = " + ver);
#if true
SharedLibrary.ShowMessage("I am a plugin" + "\n" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
#else
SharedLibrary.ShowMessage(new string[] { "I am a plugin", Assembly.GetExecutingAssembly().GetName().Version.ToString() });
#endif
}
}
}