大家都很聪明,
在C#中处理.NET Reflection时,我有一个关于异常处理的问题。
基本上我通过使用ContructorInfo.Invoke(new object[] { ... })
来调用类的构造函数。
我将它全部包装在try / catch中,如下所示:
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;
}
我的问题是,为什么baseEx.StackTrace不是我抛出baseEx时看到的堆栈跟踪?
我在抛出异常时看到的堆栈跟踪仅包含“constructor.Invoke()
之外的跟踪”,Utilities.Log("GetBaseException", baseEx.StackTrace);
向我显示“constructor.Invoke()
内部的完整跟踪。”
修改
通过使用@Knaģis的答案,这是我问题的实际解决方案:
Exception baseEx = e.GetBaseException();
if (baseEx != null)
{
throw new Exception("CreateExport Exception", baseEx);
}
答案 0 :(得分:2)
执行throw baseEx;
时,运行时将为抛出的异常分配新的堆栈跟踪。这与Reflection或您的特定用例无关。
如果您需要保留原始堆栈跟踪,请使用简单的throw;
(不带参数) - 它会重新捕获您捕获的完全相同的异常,并保留所有详细信息:
try
{
preset = constructor.Invoke(new object[] { package }) as IExportPreset;
}
catch (Exception e)
{
Exception baseEx = e.GetBaseException();
Utilities.Log("GetBaseException", baseEx.StackTrace);
throw;
}
答案 1 :(得分:0)
试试这个:
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();
}
}
并在重新抛出之前使用:
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;
}