我想了解什麼時候[ImportingConstructor]比使用[import]裝飾屬性更合適。這是個人偏好,還是允許其他DI容器構建類的東西,還是有[import]的優點?爲什麼使用ImportingConstructor
我想如果你不想公開財產,但MEF也會解決私人領域,那麼,利益又在哪裏呢?
我想了解什麼時候[ImportingConstructor]比使用[import]裝飾屬性更合適。這是個人偏好,還是允許其他DI容器構建類的東西,還是有[import]的優點?爲什麼使用ImportingConstructor
我想如果你不想公開財產,但MEF也會解決私人領域,那麼,利益又在哪裏呢?
使用[Import]
的問題在於它將對象的創建分爲兩個截然不同的可觀察階段:創建和初始化。其中[ImportingConstructor]
允許它像其他.Net對象一樣保持單一階段。
這種差異在許多方面
[Import]
變化的類型的邏輯合同變成可觀察的。但它不會改變公共或使用合同。這意味着即使對象依賴關係發生了變化(以爲單元測試),以前編譯的任何代碼都將繼續編譯。這需要編譯時錯誤,並使其成爲運行時錯誤。[Import]
代碼合同是不可用的。合同驗證引擎可以正確識別出所有字段都可以作爲null
值存在,並且在每次使用字段之前都需要進行檢查。readonly
來表示它。通過使用[ImportingConstructor]
,您允許一個用作導出的類導入其依賴項。這極大地簡化了體系結構,因爲您可以將具體對象的依賴關係與其實現分離開來。
通常情況下,您將使用[ImportingConstructor]
上的一種類型,它自身標記爲[Export]
。構造類型時,構造函數參數將由MEF提供。
這是爲了保證在導出解析爲導入之前所需的導入是可用的嗎? – ILovePaperTowels
@ILovePaperTowels是的,如果沒有這個,你必須在導入中構造對象,使其處於無效狀態,然後重新構造它以填充依賴關係,然後調用某種形式的初始化......這非常難看。 –
不要單純地從MEF的角度來思考,而應從更廣義的角度來看待您的課堂設計。通常,當你在設計一個類時,你有一組相關屬性,這些可能是服務,例如,
public class MyService
{
public ILogger Logger { get; set; }
public void SaySomething()
{
Logger.Log("Something");
}
}
現在,我會繼續前進,創造者的一個實例:
var service = new MyService();
而現在,如果我嘗試和使用方法:
service.SaySomething();
如果我不明確,我也必須初始化我Logger
財產知道:
var service = new MyService() { Logger = new ConsoleLogger() };
(或):
var service = new MyService();
service.Logger = new ConsoleLogger();
然後,錯誤不會直到運行時變得顯而易見。如果我們重新定義類:
public class MyService
{
private readonly ILogger _logger;
public MyService(ILogger logger)
{
if (logger == null) throw new ArgumentNullException("logger");
_logger = logger;
}
public void SaySomething()
{
_logger.Log("Something");
}
}
現在,如果你嘗試創建的MyService
一個實例,你必須明確提供的對象要正確初始化這個額外的服務()。這有助於通過多種方式:
你可以通過使用Code Contracts(如@JaredPar提到的)在編譯時進行靜態檢查來改進這個設計。
在MEF而言,你可以逃脫使用[Import]
代替[ImportingConstructor]
作爲MEF會拋出一個異常時,它不能滿足於一個類型的所有進口,都初始化後纔會返回類型([ImportingConstructor]
),然後[Import]
秒。
建築師注入通常是優選的。
構造函數參數也不支持重構。
+1#1現在看起來如此明顯。我不知道代碼合同問題。你能再解釋一下嗎? – ILovePaperTowels
@ILovePaperTowels關於#3,根據我的經驗,大部分時間你做一個'[Import]'這個字段一旦設置就永遠不會改變。在C#中,這是通過將字段'readonly'來表示的,但在'[Import]'情況下不起作用,因爲該字段在構造函數完成後被分配,這違反了'readonly'。這實際上(並且狡猾)將通過反射來工作,但是使其與非MEF組合的使用幾乎不可能 – JaredPar