我正在试验MEF并创建了一个测试程序,用于调用实现某个给定接口的“插件”,该接口如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ProbeContract
{
public interface IProbe
{
int DoProbe(string what);
List<string> GetCapabilities();
}
}
我创建了一个示例控制台程序,它从自己的程序集加载“插件”,如果找到的话,从一个放置其他DLL的指令加载。无论plugins目录是否为空(只调用“本机”插件)或者它具有兼容的DLL,该程序都可以正常运行。但是......如果在循环迭代之间添加了一个新的DLL,则DirectoryCatalog的Refresh()方法会抛出一个ChangeRejectedException,这就解释了:
构图保持不变。该 变更被拒绝了因为 以下错误:组成 产生了单一的构图错误。 根本原因如下。 查看CompositionException.Errors 财产更详细 信息。
1)出口变化受阻 不可重组的进口 “MEFTest.Program.ProberSet (ContractName = “ProbeContract.IProbe”)” 部分'MEFTest.Program'。
程序如下,请按照我尝试添加的DLL的代码进行操作。我做错了什么?
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProbeContract;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MEFTest
{
class Program
{
[ImportMany]
IEnumerable<IProbe> ProberSet { get; set; }
CompositionContainer exportContainer;
DirectoryCatalog pluginCatalog;
AggregateCatalog catalog;
private void Run()
{
catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
string myExecName = Assembly.GetExecutingAssembly().Location;
string myPath = Path.GetDirectoryName(myExecName);
pluginCatalog = new DirectoryCatalog(myPath + "/Plugins");
catalog.Catalogs.Add(pluginCatalog);
exportContainer = new CompositionContainer(catalog);
CompositionBatch compBatch = new CompositionBatch();
compBatch.AddPart(this);
compBatch.AddPart(catalog);
exportContainer.Compose(compBatch);
for (; ; )
{
Console.Write("Press any key to run all probes: ");
Console.ReadKey(true);
Console.WriteLine();
pluginCatalog.Refresh();
foreach (var Prober in ProberSet)
{
Prober.DoProbe("gizmo");
}
}
}
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
}
}
插件。另外两个插件是相似的,唯一的区别是它们与主程序位于同一个程序集中:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using ProbeContract;
namespace OtherProbes
{
[Export(typeof(IProbe))]
public class SpankyNewProber : IProbe
{
public int DoProbe(string what)
{
Console.WriteLine("I'm Spanky and New and I'm probing [{0}]", what);
return 0;
}
public List<string> GetCapabilities()
{
List<string> retVal = new List<string>();
retVal.Add("spanky");
retVal.Add("new");
return retVal;
}
}
}
答案 0 :(得分:13)
我假设您正在使用MEF预览6,因为您看到拒绝例外。您看到更改被拒绝的原因是因为您的ProberSet不可重新组合。尝试将ProberSet导入更改为:
[ImportMany(AllowRecomposition=true)]
IEnumerable<IProbe> ProberSet { get; set; }
这样做将允许在已经组成导入后将新的IProbe导出引入目录/容器中。
这里的想法是,一旦你得到一个稳定的合成,我们拒绝任何可能使该合成失败的变化,在你的情况下,你声明你想要一组不可重组的IProbe对象,所以在初始设置之后添加新的IProbe会违反了这一要求。