当我更换零件时如何让MEF重新组合?

我正在尝试让MEF重新组合它在更新导出的实例时所知道的所有部分。 基本上我想让MEF更新所有在更改时导入连接字符串配置值的部分。 一切看起来都很好,直到我想要更改实例。 如果我尝试使用更新的值ComposeParts,它似乎将第二个部分实例添加到容器中,然后我的导入更新,但为null。

谁能指出我哪里出错? 或者我应该尝试以这种方式使用MEF?

我正在使用MEF预览9和目标.net框架3.5和WPF。

using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Linq; using System.Text; using Shouldly; namespace ConsoleApplication4 { class Program { static void Main(string[] args) { MainClass main = new MainClass(); main.RunTest(); } } public class MainClass { [ImportMany] public IEnumerable Settings { get; set; } public void RunTest() { AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(typeof(Settings).Assembly)); CompositionContainer container = new CompositionContainer(catalog); container.SatisfyImportsOnce(this); Config cfg = new Config { Settings = new Settings { ConnectionString = "Value1" }, }; // result is returned with a null settings value UsesSettings result = container.GetExportedValue(); // this recomposes everything with the new value, result changes to have settings of Value1 container.ComposeParts(cfg); // this line results in my import many enumerable returning 2 parts the Value1 setting and null container.SatisfyImportsOnce(this); result.TheSettings.ConnectionString.ShouldBe("Value1"); cfg.Settings = new Settings { ConnectionString = "Value2" }; // how do I tell the container to recompose now I have changed the config object, // or how do I replace the part value with the new value? // this line causes the result.Settings to return null container.ComposeParts(cfg); // this updates the ImportMany to 3 values, Value1, Value2 and null container.SatisfyImportsOnce(this); } } public class Settings { public string ConnectionString = "default value"; } public class Config { [Export(typeof(Settings))] public Settings Settings { get; set; } } [Export(typeof(UsesSettings))] public class UsesSettings { [Import(typeof(Settings), AllowRecomposition = true)] public Settings TheSettings { get; set; } } } 

对于您要完成的方案,您有一些小的东西。

第一:如果要添加/删除/更改特定导出,则它必须不在目录本身中,因此您应该删除具有“导出设置”属性的Config类。 这是由CatalogExportProvider创建的,这也是您在集合中看到空值的原因。

请尝试以下方法:

 public class Program { [ImportMany(AllowRecomposition=true)] public IEnumerable Settings { get; set; } public void RunTest() { AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(typeof(Settings).Assembly)); CompositionContainer container = new CompositionContainer(catalog); // Settings should have 0 values. container.ComposeParts(this); Contract.Assert(this.Settings.Count() == 0); CompositionBatch batch = new CompositionBatch(); // Store the settingsPart for later removal... ComposablePart settingsPart = batch.AddExportedValue(new Settings { ConnectionString = "Value1" }); container.Compose(batch); // Settings should have "Value1" UsesSettings result = container.GetExportedValue(); Contract.Assert(result.TheSettings.ConnectionString == "Value1"); // Settings should have 1 value which is "Value1"; Contract.Assert(this.Settings.Count() == 1); Contract.Assert(this.Settings.First().ConnectionString == "Value1"); // Remove the old settings and replace it with a new one. batch = new CompositionBatch(); batch.RemovePart(settingsPart); batch.AddExportedValue(new Settings { ConnectionString = "Value2" }); container.Compose(batch); // result.Settings should have "Value2" now. Contract.Assert(result.TheSettings.ConnectionString == "Value2"); // Settings should have 1 value which is "Value2" Contract.Assert(this.Settings.Count() == 1); Contract.Assert(this.Settings.First().ConnectionString == "Value2"); } } public class Settings { public string ConnectionString = "default value"; } [Export(typeof(UsesSettings))] public class UsesSettings { [Import(typeof(Settings), AllowRecomposition = true)] public Settings TheSettings { get; set; } }