2017-03-01 60 views
7

我想創建一些現有的代碼模塊(IMyDesiredType)加載MEF。模塊主要有一些我想提供給MEF的構造函數參數(ImportingConstructor)。到目前爲止,這工作正常。忽略構造函數異常與MEF沒有Visual Studio打破例外

現在出現了這個問題,因爲有時候主機應用程序中的依賴關係不可用(它們爲空)。這些模塊將按照慣例拋出ArgumentNullException,我不想改變這一點。不過,我希望MEF忽略這些對象(不包括它們在對象圖中)。

[Export(typeof(IMyDesiredType))] 
class MyModule : IMyDesiredType{ 
    [ImportingConstructor] 
    public MyModule(object aNecessaryDependency){ 
     if(aNecessaryDependency==null) throw new ArgumentNullException(nameof(aNecessaryDependency)) 
    } 
} 

爲了獲得這個,我讓MEF創建Lazy<IMyDesiredType>實例和一個初始化它們之一。

foreach(var myLazy in collectionOfMefExports){ 
    try{ 
     myLazy.Value // do something with the value, so the object gets composed 
    }catch(CompositionException){ 
     // Here I get the ArgumentNullException wrapped in a CompositionException 
     // and also can work around it. However because of the exception handling 
     // is on the first hand in MEF, VS will break always in the throwing 
     // constructor of the module 
     continue; // Go to the next module after logging etc. 
    } 
} 

這裏的問題是,我要趕CompositionException,而不是直接從Exception模塊的構造(主要是ArgumentNullException)。因此,由於Exception不是從用戶代碼捕獲的,所以Visual-Studio在每個模塊上都會中斷。明顯的解決辦法是,告訴視覺工作室不要打破ArgumentNullException -types,但這對我來說感覺非常「黑客」。而在其他任何地方,我都希望VS在ArgumentNullException之間突破。

是否有另一種模式,我可以讓MEF不向圖中添加組件,其中聲明瞭依賴關係([Export]),但它的值爲null,或者是否存在我可以覆蓋的MEF類的方法在派生類中,並抓住構造函數的例外呢?

請留下評論,如果問題不明確,我不是英語母語的人,因此也許這個問題是言辭混亂的。

+1

您是否已經試過'[DebuggerHidden]'和[DebuggerStepThrough]屬性作爲答案? http://stackoverflow.com/questions/1420390/dont-stop-debugger-at-that-exception-when-its-thrown-and-caught#3455100 – grek40

+0

非常感謝您的建議。可悲的是,它的工作方式是:我必須裝飾導出模塊的每個構造函數,但是它們不會在所有運行時環境中拋出這些異常,而且不僅僅是通過MEF將它們用作簡單插件的異常。 – HCL

+0

是防止「Visual-Studio在每個模塊上出現故障......」的問題? – Julian

回答

1

不幸的是,對你所要求的支持有所限制。

Visual Studio允許通過異常類型來配置調試器是否應該中斷。當您嘗試根據執行上下文顯示/隱藏相同類型的異常時,這並沒有真正的幫助。仍然可以派生自己的異常類型並在導入構造函數中使用它。這將允許您按異常類型配置中斷,但不會影響MEF組合和其他代碼之間的差異。

此外,方法可以被標記爲被調試器忽略。看到這個相關的答案Don't stop debugger at THAT exception when it's thrown and caught

無視[DebuggerStepThrough],因爲據報道是不可靠的,選項一是[DebuggerHidden]。我想添加另一個候選人:[DebuggerNonUserCode]。這與VS選項「僅啓用我的代碼」一起使用(請參閱http://blog.functionalfun.net/2008/05/debuggernonusercode-suppressing.html)。

因此,儘管[DebuggerHidden]絕不會在那裏被關上,在接下來的周圍用戶代碼,而不是報告它的構造異常突破,[DebuggerNonUserCode]可以讓你忽略或根據您的VS調試設置構造斷裂。只要設置「僅啓用我的代碼」,兩個屬性的行爲方式應該是相同的。

假設MEF初始化在調試器隱藏的代碼中完全處理,對於非MEF構造函數調用,調試器首次到達未標記爲隱藏的環境函數時將中斷。

+0

不是我所希望的,而是最接近問題的。謝謝。 – HCL

0

這聽起來像只有你知道哪些組件是重要的,哪些不是。 您可能想要做一些事情,比如將組件初始化封裝在try catch中,就像您已經通過配置查找一樣,並通過配置查找來決定此特定異常是否存在問題或不在代碼中。

基本上你需要自己建立規則,但無論哪種方式,一個失敗的組件加載是一個失敗,所以引發異常的組件不能被正確添加到圖中,我想。

普遍接受的方法似乎是刪除,則故障部件重新組合圖形...

How do I get MEF to recompose when I change a part?

...

這可能會幫助你,儘管在診斷如何/什麼下一步..

https://blogs.msdn.microsoft.com/dsplaisted/2010/07/13/how-to-debug-and-diagnose-mef-failures/

+0

THX,我會更深入瞭解它的明天。但我懷疑,它並不能幫助解決問題,我已經能夠沒有激活插件,這是不是我的問題(或待處理的問題)是,異常發生在模塊的構造函數中,因此Visual Studio將在每個構造函數中中斷,除非我禁用Visual中有關異常的中斷行爲Studio或[DebuggerHidden]/[DebuggerStepThroug] -attributes(thx grek40)。我認爲解決問題的唯一方法就是將MEF類繼承下來。 – HCL

+1

從這個描述中,它聽起來像你的問題是,你不想讓VS停在「一些例外」,當你把它附加到你的代碼? – War

+0

FYI有沒有辦法讓VS至「選擇性忽視一些特定的例外」,但你可以告訴它忽略類型的異常(如你暗示你似乎已經知道了) – War

0

我可前往錯DIRECTI對,但沒有處理的情況下默認實現抽象工廠有幫助嗎?

我用這個爲我的依賴與團結DI ...有趣的問題毫無疑問!

<Export(GetType(IComponent))> 
Public Class DependencyResolver 
    Implements IComponent 
    Public Sub SetUp(registerComponent As IRegisterComponent) Implements IComponent.SetUp 
     'General 
     registerComponent.RegisterType(Of IDataContextAsync, dbEcommEntities)() 

     'DomainLogic 
     registerComponent.RegisterType(Of IUserDomainLogic, MfrUserDomainLogic)() 

     'Services 
     registerComponent.RegisterType(Of ICompanyService, CompanyService)() 

    End Sub 

End Class 

注入構造 - 我有我在另一個類庫有自己的依賴解析器MEF出口。然後在每個Web應用程序中註冊新應用程序的組件。我從MEF導出依賴關係解析器接收到的每個部分都可以通過注入我的mvc控制器的構造函數來擴展。 在組件加載器中,我使用dll加載容器,並且可以通過在事實之後添加unity.config來擴展依賴關係。

Private Shared Sub RegisterDependencies(container As IUnityContainer) 
     'load services 
     ComponentLoader.LoadContainer(container, ".\\bin", "Service.dll") 

     'load config 
     'container.LoadConfiguration() 
    End Sub 
+0

感謝你好你的答案。我也想到了這一點,但是如果我想在調用方這一點,它只會推遲問題,如果我會在模塊網站上做到這一點,我將不得不爲每個模塊寫一個工廠(因爲不同的構造函數參數),這是不需要的。還是我誤解了你的主張? – HCL

0

的MEF中已經包括此爲自MEF 6預覽功能,這就是所謂的穩定的組成。即使未提供依賴關係,MEF也可以安全地啓動。

簡單地解決您的問題將是檢查值是否實際上創建之前訪問該值。

if(myLazy.IsValueCreated) 
    myLazy.Value // do something with the value, so the object gets composed 

您可以閱讀更多關於它here

注:如果您有可選的依賴和系統可以在沒有他們的工作,然後不要把參數空檢查在構造函數。它將在構圖期間使它們成爲必需的依賴關係。

正如您已經提到的,當參數爲null時,您不希望更改拋出異常的約定。那麼如果你知道這個系統在沒有這些依賴關係的情況下可以正常工作,那麼你可以避免爲這種依賴關係進行檢查。

+0

嗨,感謝您的回答。聽起來很有希望。但是我還沒有完全理解它:懶惰{T}使得模塊在以後加載。如果我會檢查IsValueCreated,這將永遠是假的,只要我沒有訪問的值(此看到我懶{}的唯一目的),也MEF不會嘗試實例懶惰的,因爲真正的對象【T}。如果我打電話給Value,我和以前一樣。但也許我錯過了這一點?你能進一步闡述一下嗎? – HCL

+0

至於答案的註釋部分:依賴關係不是可選的。這些模塊是現有的,它們需要構造函數參數。因此,ArgumentNullException。最好的情況是,如果我能告訴MEF不嘗試創建依賴項,如果導入構造函數需要可導出的依賴項,但其值現在爲空。但是我沒有找到這樣的可能性。 – HCL

+0

我想我寫得太快..你說得對懶惰不會做我期望的。我認爲我們需要用於診斷的mefx庫類。我會在週末更新我的答案,以包含更多細節。 – vendettamit