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