在我的Prism應用程序中,可以通過Container屬性從Bootstrapper類中獲取MEF容器。爲什麼MEF容器在模塊中不可用?
但它不是從類模塊(IModule)內。我只能通過IServiceLocator導入容器。
爲什麼?我認爲對混凝土技術使用通用接口是有道理的,但Prism 4.1指南要求我們不要使用IServiceLocator(在Considerations for Using IServiceLocator中)。
在我的Prism應用程序中,可以通過Container屬性從Bootstrapper類中獲取MEF容器。爲什麼MEF容器在模塊中不可用?
但它不是從類模塊(IModule)內。我只能通過IServiceLocator導入容器。
爲什麼?我認爲對混凝土技術使用通用接口是有道理的,但Prism 4.1指南要求我們不要使用IServiceLocator(在Considerations for Using IServiceLocator中)。
我認爲它不是對應於棱鏡或MEF,而是對應於一般的依賴注入原理和最佳實踐。 (是的,我認爲MEF不是DI容器,但在這裏它幾乎用作DI容器,所以我想在這裏使用相同的做法)。
在DI的最佳實踐(this書是非常酷,我強烈推薦),這是件好事,在DI「工作流」這樣的步驟:
理想情況下,您不應再使用DI容器。你的代碼不應該知道DI容器的存在(從這方面來說Unity是真正的DI容器,因爲你可以編寫不知道使用DI容器的代碼)。如果你的代碼知道它 - 它取決於DI容器,這是件壞事。
PS。如果你希望你的模塊中使用MEF容器無論如何(例如,因爲你不是很熟悉DI範式,或者你有一些非常具體的任務),你可以嘗試這樣的:
[ModuleExport(typeof(YourModule))]
public class YourModule : IModule
{
public static CompositionContainer CompositionContainer;
[ImportingConstructor]
public void YourModule(CompositionContainer container)
{
this.CompositionContainer = container;
}
}
不要忘記在您的Boostrapper中註冊您的MEF容器本身:
public class YourBootstrapper: MefBootstrapper
{
protected override CompositionContainer CreateContainer()
{
var container = base.CreateContainer();
container.ComposeExportedValue(container);
return container;
}
}
請注意,我使用的是Prism的舊版本,並且我將它與UnityContainer一起使用,但應遵循相同的原則。
定義您的Module類以在構造函數中獲取容器。
下面是使用統一的例子:
public class Module : IModule
{
public static IUnityContainer Container;
public Module(IUnityContainer container)
{
Container = container;
}
}
如果你定義一個構造函數,需要一個容器,它會被由ApplicationBootstrapper.Run()方法調用。
我測試了一個默認的無參數構造函數和一個重載構造函數,它接受容器並調用第二個構造函數。
我還檢查了只有默認的構造函數,它被調用。我建議你改變你的構造函數來添加一個容器參數。
在您的模塊類中有一個容器將允許您在Initialize方法中註冊類型。
至於ServiceLocator,這是一個稍微不同的模式,我建議您在出於某種原因無法獲取容器創建的依賴項的情況下使用它。
我試圖這樣做。 MEF使用CompositionContainer類型而不是Unity的IUnityContainer。但是我的構造函數的參數類型化CompositionContainer沒有執行。 –
@reito:你是否也有一個默認的構造函數,以及如何調用ApplicationBootstrapper運行方法? – Gilles
我沒有構造函數了,只有這個。 Bootstrapper Run方法在我的Application類的OnStartup方法中調用。 –
儘管我同意最佳實踐,但棱鏡文檔明確指出,您也可以使用方法的Initialize方法以及「使用應用程序的依賴注入容器註冊共享服務」。 http://msdn.microsoft.com/en-us/library/gg405479%28v=pandp.40%29.aspx – Console
如果我們不應該知道容器,那麼模塊如何註冊新的共享服務? – Benjamin
提到的'ComposeExportedValue'是'System.ComponentModel.Composition.AttributedModelServices'中的擴展方法 – jan