I would like to create some existing code-modules (IMyDesiredType
) to load with MEF. The modules mostly have some constructor arguments which I want to provide with MEF (ImportingConstructor
). So far this works fine.
The problem now arises because sometimes the dependencies are not available (they are null) in the host application. The modules will throw by convention an ArgumentNullException
and I don’t want to change that. However I want MEF to overlook such objects (not include them in the object-graph).
[Export(typeof(IMyDesiredType))]
class MyModule : IMyDesiredType{
[ImportingConstructor]
public MyModule(object aNecessaryDependency){
if(aNecessaryDependency==null) throw new ArgumentNullException(nameof(aNecessaryDependency))
}
}
To acquire this, I let MEF create Lazy<IMyDesiredType>
instances and the initializing them one by one.
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.
}
}
The problem here is, that I have to catch CompositionException
and not directly the Exception
(mostly ArgumentNullException
) from the module's constructor. Therefore, Visual-Studio breaks on each module, because of the Exception is not catched from user-code. The obvious solution to this is, to tell visual studio not to break on ArgumentNullException
-types, but this feels very “hackish” to me. And in any other place, I want VS to break on ArgumentNullException
s.
Is there another pattern with which I can make MEF not to add components to the graph, where the dependency is declared ([Export]
), but it’s value is null, or is there a method of a MEF-class I can override in a derived class and catch the constructor-exception on the fore-hand?
Please leave a comment, if the question is not clear, I'm not a native english speaker and therefore maybe the quesion is verbalized a litte confusing.
When the debugger breaks, it shows you where the exception was thrown. You can also add or delete exceptions. With a solution open in Visual Studio, use Debug > Windows > Exception Settings to open the Exception Settings window.
On the dialog displayed, uncheck "Exception Settings -> Break when this exception type is user-unhandled". Then, Visual Studio will not stop on this exception.
Unfortunately, the support for what you ask for is somehow limited.
Visual Studio allows to configure by exception type, whether the debugger should break. This doesn't really help when you try to show/hide the same type of exception based on the execution context. Still you could derive your own exception type and use it in the importing constructors. This would allow you to configure breaks by exception type, but would not make a difference between MEF composition and other code.
Also, methods can be marked to be ignored by the debugger. See this related answer Don't stop debugger at THAT exception when it's thrown and caught.
Disregarding [DebuggerStepThrough]
since it is reported to be unreliable, option one is [DebuggerHidden]
. I want to add another candidate: [DebuggerNonUserCode]
. This plays with the VS option "Enable just my code" (see http://blog.functionalfun.net/2008/05/debuggernonusercode-suppressing.html).
So while [DebuggerHidden]
will never break for the exception in the constructor where it is thrown and will instead report it in the next surrounding user code, [DebuggerNonUserCode]
allows you to ignore or break in the constructor depending on your VS debugging settings. As long as "Enable just my code" is set, both attributes should behave the same way.
Supposed the MEF initialization is fully handled in debugger-hidden code, for non-MEF constructor calls, the debugger will break when it first reaches a surrounding function that is not marked as hidden.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With