2009-07-15 47 views
8

我与MEF实验发现并创建了一个测试程序来调用实现某个给定的接口“插件”,它遵循新的DLL:调用刷新()在DirectoryCatalog抛出ChangeRejectedException如果目录

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。该程序工作确定插件目录是否为空(仅调用“本机”插件),或者它具有兼容的DLL开始。但是...如果在循环迭代之间添加新的DLL,则DirectoryCatalog的Refresh()方法抛出ChangeRejectedException,这将如此解释:

构图保持不变。 更改因以下错误 而被拒绝:组合错误 产生了单个组合错误。 根本原因如下。 查看CompositionException.Errors 属性获取更详细的 信息。

1)的出口通过更改 非recomposable进口 防止 '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; 
     } 
    } 
} 

回答

13

我假设你正在使用MEF预览6,因为你所看到的拒绝例外。您看到更改被拒绝的原因是因为您的ProberSet不可重新使用。尝试将您的ProberSet导入更改为:

[ImportMany(AllowRecomposition=true)]   
IEnumerable<IProbe> ProberSet { get; set; } 

这样做将允许在导入完成之后将新的IProbe导出引入目录/容器。

这里的想法是,一旦你得到一个稳定的组合,我们拒绝任何可能导致组合不稳定的变化,并且在你的情况下,你声明你想要一组不可重新组合的IProbe对象,以便在初始化后添加新的IProbe会违反这一要求。

相关问题