簡體   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