使用constructorinfo . invoke时的堆栈跟踪混淆
本文关键字:跟踪 堆栈 constructorinfo invoke 使用 | 更新日期: 2023-09-27 17:53:16
大家好,
在c#中处理。net反射时,我有一个关于异常处理的问题。
基本上,我通过使用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抛出时的StackTrace ?
抛出异常时,我看到的堆栈跟踪只包含constructor.Invoke()
之外的跟踪,而Utilities.Log("GetBaseException", baseEx.StackTrace);
显示了constructor.Invoke()
内部的完整跟踪。
通过使用@Knaģis的答案,这是我的问题的实际解决方案:
Exception baseEx = e.GetBaseException();
if (baseEx != null)
{
throw new Exception("CreateExport Exception", baseEx);
}
当您执行throw baseEx;
时,运行时将为抛出的异常分配一个新的堆栈跟踪。这与反射或您的特定用例无关。
如果您需要保留原始堆栈跟踪,请使用简单的throw;
(不带参数)—它会重新抛出您捕获的完全相同的异常,保留所有细节:
try
{
preset = constructor.Invoke(new object[] { package }) as IExportPreset;
}
catch (Exception e)
{
Exception baseEx = e.GetBaseException();
Utilities.Log("GetBaseException", baseEx.StackTrace);
throw;
}
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();
}
}
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;
}