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

Gis*_*shu 4 .net c# mef

我有一个WPF应用程序正在运行,它需要影响UI的所有操作都在UI线程上.WPF还提供了一个Dispatcher类来处理这个 - 所以我把它提取到一个依赖项中.

public interface UIActionExecutor
    {
        void Do(Action action);
    }
Run Code Online (Sandbox Code Playgroud)

所以在我的生产代码中,我使用了一个委托给WPF Dispatcher的导出实现.我正在使用MEF进行DI.

现在问题是,在我的验收测试中,我需要替换容器中的部件/对象,该部件/对象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
Run Code Online (Sandbox Code Playgroud)

Wim*_*nen 7

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;
Run Code Online (Sandbox Code Playgroud)

(¹)从你的博客来看,我相信你已经知道了.但是其他人也会读到这个答案,所以我想清楚"单元测试"一词.