2011-12-19 48 views
3

我剛在我的mef應用程序中追查到一個問題;問題是,我在IEnumerable<IFoo>屬性中有[Import]而不是[ImportMany]。我開始想知道爲什麼。 MEF認爲注入目標是一個「集合」,可以確定需要集合而不是單個元素。至少Ninject以這種方式工作。爲什麼MEF有[ImportMany]而不只是[Import]

有沒有人知道爲什麼[ImportMany]是必需的?我能想到的唯一原因是人們可能想要[Export(typeof(IEnumerable<IBar>)] public IEnumerable<Bar> { get; },但這真的是這種設計的原因嗎?我敢打賭,我不是唯一一個調試過這種錯誤的人。

回答

6

這是不一樣的;)

[Import]表示要根據合同進口一個單一的東西。在MEF中,合同只是一個字符串,當您導入一個類型(如IEnumerable<IBar>)時,您確實是根據合同導入的,該合同只是該類型的名稱

在MEF,基數是非常重要的,所以當你指出要導入的東西實例符合合同規定,只能有一個來源。如果找到多個導出,則由於基數不匹配而引發異常。

[Import]功能不包含特殊的邏輯來處理IEnumerable<T>,所以從它的角度來看,它是只是一個合同一樣。

然而,[ImportMany]屬性存在,特別是爲了彌補這一差距。它對所述合同的任意數量的出口接受零。這意味着您可以不用單個導出IEnumerable<IBar>,而是將許多分散在多個程序集中,並且永遠不會出現基數不匹配。

最後它是一個設計哲學。 MEF可能擁有關於IEnumerable<T>的特殊內置知識。 Autofac(顯然Ninject)會這樣做,並將其稱爲Relationship Type

但是,這樣的特殊外殼意味着某處執行的代碼違反了Liskov Substitution Principle,這又違反了POLA,所以在這種情況下,我傾向於支持MEF設計師。尋求更明確的API可能會降低可發現性,但可能會更安全一些。

+0

感謝您的澄清。在我的情況下,惱人的是'compositionContainer.ComposeParts(this);'沒有拋出異常,而是我的ImportMany導入是其中一個依賴關係。只有提示是關於拒絕導出的日誌輸出。這當然是由設計,幸運的是我找到了mefx工具來診斷問題。如果對象圖很大,這種錯誤可能很難追蹤。 – Ahe 2011-12-21 12:19:00

2

爲了簡化略上面的回答:如果有多個匹配的出口

  • [Import]會拋出異常。
  • [ImportMany]將加載多個匹配的導出而不會引發錯誤。

如果我有,我想導入IDataAccessLayer,應該永遠只能是一家出口可用 - 我永遠不會被同時寫入2個數據庫,所以我用[Import],以確保只有一個會存在。

如果我想裝載許多不同的BusinessObjects,我將使用[ImportMany],因爲我需要許多不同類型的BusinessObjects。

相關問題