繁体   English   中英

如何替换MEF容器中的导出部件/对象?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM