[英]How do I get MEF to recompose when I change a part?
我试图让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> 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<UsesSettings>();
// 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> 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<UsesSettings>();
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; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.