[英]How to replace an exported part / object in a MEF container?
我有一个WPF应用程序正在运行,它需要影响UI的所有操作都在UI线程上。 WPF还提供了一个Dispatcher类来处理这个 - 所以我把它提取到一个依赖项中。
public interface UIActionExecutor
{
void Do(Action action);
}
因此,在我的生产代码中,我使用了一个委托给WPF Dispatcher的导出实现。 我正在使用MEF进行DI。
现在问题是,在我的验收测试中,我需要替换容器中的部件/对象,该部件/对象由Mock响应UIActionExecutor
。 所以我需要从容器中删除ExecutorUsingWpfDispatcher
并在其位置添加MockUIActionExecutor
。 这听起来很简单(如果我没有使用MEF)......但我的搜索技巧并没有帮助我找到关于如何使用MEF容器做到这一点的答案?
更新:如果有人想知道解决方案为何如何/如何运作 - 请阅读Glenn Block的博客文章#2 。 这就是我最终使用的
var defaultExportProvider = new CatalogExportProvider(__defaultCatalog);
var catalogOfMocks = new AssemblyCatalog(assemblyExportingMocks);
// order of params important (precedence left to right)
__container = new CompositionContainer(catalogOfMocks, defaultExportProvider);
defaultExportProvider.SourceProvider = __container
DI容器负责将所有部件连接在一起。
单元测试负责单独测试单个代码单元。 模拟用于替换依赖项。 所以原则上DI容器不应该用于单元测试。 它与“单元测试”的定义相矛盾。(¹)
但是,我当然可以理解,除了单元测试之外,您可能还希望进行自动集成测试,并且您可能希望在此类测试中使用MEF但更换某些MEF部件。 你可以这样做:
// first set up the main export provider
var mainCatalog = new AggregateCatalog(...);
var mainExportProvider = new CatalogExportProvider(mainCatalog);
// now set up a container with mocks
var mockContainer = new CompositionContainer();
mockContainer.ComposeExportedValue<IFoo>(fooMock);
mockContainer.ComposeExportedValue<IBar>(barMock);
// use this testContainer, it will give precedence to mocks when available
var testContainer = new CompositionContainer(mockContainer, mainExportProvider);
// link back to the testContainer so mainExportProvider picks up the mocks
mainExportProvider.SourceProvider = testContainer;
(¹) 从你的博客来看,我相信你已经知道了。 但是其他人也会读到这个答案,所以我想清楚“单元测试”一词。
无法获得已接受的解决方案。 下面的代码应该工作,优先级在AggregateExportProvider
的文档中描述。
var mainContainer = new CompostionContainer();
mainContainer.ComposeExportedValue<IFoo>(new Foo() {Test = 1});
var mockContainer = new CompositionContainer();
mockContainer.ComposeExportedValue<IFoo>(new Foo() {Test = 2});
var aggregateExportProvider = new AggregateExportProvider(
mockContainer, // IFoo in this container takes precedence
mainContainer);
IFoo foo = aggregateExportProvider.GetExportedValue<IFoo>();
Console.WriteLine(foo.Test); // Outputs: 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.