Reputation: 851
Hi all you clever guys,
I have a question regarding exception handling when dealing with .NET Reflection in C#.
Basically I call a constructor on a class through the use of ContructorInfo.Invoke(new object[] { ... })
.
I wrap it all in a try/catch like this:
try
{
preset = constructor.Invoke(new object[] { package }) as IExportPreset;
}
catch (Exception e)
{
Exception baseEx = e.GetBaseException();
Utilities.Log("GetBaseException", baseEx.StackTrace);
if (baseEx != null)
throw baseEx;
else
throw e;
}
My question is that why is baseEx.StackTrace not the stacktrace I see when the baseEx is thrown?
The stacktrace I see when throwing the exception does only contain a trace "outside of" constructor.Invoke()
whilst Utilities.Log("GetBaseException", baseEx.StackTrace);
shows me the full trace "inside of" constructor.Invoke()
.
EDIT:
By using the answer of @Knaģis, here is the actual solution to my problem:
Exception baseEx = e.GetBaseException();
if (baseEx != null)
{
throw new Exception("CreateExport Exception", baseEx);
}
Upvotes: 1
Views: 83
Reputation: 111
try this:
using System.Runtime.Serialization;
public static class ExceptionHelper
{
public static void PreserveStackTrace(this Exception e)
{
var streamingContext = new StreamingContext(StreamingContextStates.CrossAppDomain);
var objectManager = new ObjectManager(null, streamingContext);
var serializationInfo = new SerializationInfo(e.GetType(), new FormatterConverter());
e.GetObjectData(serializationInfo, streamingContext);
objectManager.RegisterObject(e, 1, serializationInfo);
objectManager.DoFixups();
}
}
and use before rethrow:
try
{
preset = constructor.Invoke(new object[] { package }) as IExportPreset;
}
catch (Exception e)
{
Exception baseEx = e.GetBaseException();
Utilities.Log("GetBaseException", baseEx.StackTrace);
baseEx.PreserveStackTrace();
if (baseEx != null)
throw baseEx;
else
throw e;
}
Upvotes: 0
Reputation: 21485
When you do throw baseEx;
the runtime will assign a new stack trace for the exception thrown. This has nothing to do with Reflection or your specific use case.
If you need to preserve the original stack trace, use a simple throw;
(without an argument) - it rethrows the exact same exception you caught, preserving all details:
try
{
preset = constructor.Invoke(new object[] { package }) as IExportPreset;
}
catch (Exception e)
{
Exception baseEx = e.GetBaseException();
Utilities.Log("GetBaseException", baseEx.StackTrace);
throw;
}
Upvotes: 2