One further problem is that it's entirely possible to get nested TargetInvocationExeptions as the call stack unwinds - again masking what the real problem is. This was the precise situation I found myself in with my nicely crafted n-tier WCF-based system.
So to make life just a little easier on myself when dealing with the exceptions thrown whilst performing a dynamic invocation I put together the following extension methods - one that re-wraps an exception and one that un-wraps nested TargetInvocationExceptions.
To use it, we just catch and re-throw, except using the extension methods.
tryWhat you'll get is an exception throw of the same type as the actual fault, regardless of how many nested TargetInvocationExceptions it is wrapped in. Because we're nicely wrapping the exception we also maintain the call stacks to let you trace what's really going on.
{
// Do something dangerous with dynamic invocation
}
catch (TargetInvocationException ex)
{
throw ex.UnwrapTargetInvocationExceptions().ForRethrowing();
}
Finally, here's the source - use it at your own risk - I've found it handy!
public static class ExceptionExtensions
{
////// that's exception's INNER exception.
/// Returns an exception wrapping an exception, but of the same type a
///
///
/// This allows us to write code like
///throw ex.InnerException.ForRethrowing()
/// to re-throw an inner exception type without losing the stack trace.
///
public static T ForRethrowing(
this T innerException, Exception outerException)
where T: Exception
{
var actualType = innerException.GetType();
var ctorParams = new object[] {
innerException.Message, outerException
};
var result = (T)Activator.CreateInstance(actualType, ctorParams);
return result;
}
///
/// Unwraps an exception from any wrapping target invocation exceptions.
///
public static Exception UnwrapTargetInvocationExceptions(
this Exception exception)
{
var innerException = exception.InnerException;
// not a TargetInvocationException, or no inner exception? Then
// just return the exception itself
if ((innerException == null) ||
(!(exception is TargetInvocationException)))
{
return exception;
}
return innerException.UnwrapTargetInvocationExceptions();
}
}
No comments:
Post a Comment