我有一个 System.AggregateException
类型的异常:
Message = "One or more errors occurred."
Source = null
StackTrace = null
这是
InnerException
是这个System.Reflection.TargetInvocationException
:Message = "Exception has been thrown by the target of an invocation."
Source = "mscorlib"
StackTrace =
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.Incoming(IHubIncomingInvokerContext context)
InnerException
是我创建的从 ApplicationException
扩展的异常:Message = "Some error writen by me at the hub"
Source = "Chat"
StackTrace =
at Chat.Hubs.ChatHub.SendMessage(String text, String clientConnId) in d:\...Chat\Chat\Hubs\ChatHub.cs:line 48
当我运行这个:
Exception excpetion = ex.GetBaseException();
其中
ex
是 System.AggregateException
我在 System.Reflection.TargetInvocationException
得到 excpetion
。 这怎么会发生? 场景
我不知道如何在一个简单的项目中重现这个。就我而言,我在 SignalR 项目中发现了这一点。一些集线器方法抛出异常并在 global.asax 中处理错误:
GlobalHost.HubPipeline.AddModule(new MyHubPipelineModule());
MyHubPipelineModule
应该是这样的:public class MyHubPipelineModule : HubPipelineModule
{
protected override void OnIncomingError(Exception ex, IHubIncomingInvokerContext context)
{
Exception excpetion = ex.GetBaseException();
context.Hub.Clients.Caller.ExceptionHandler(excpetion.Message);
}
}
注意:这应该在 SignalR 1.0.1 中完成。在 1.1.0 中,异常更简单(链更小),因此运行良好。确保你有这个包版本:
<package id="Microsoft.AspNet.SignalR" version="1.0.1" targetFramework="net40" />
<package id="Microsoft.AspNet.SignalR.Core" version="1.0.1" targetFramework="net40" />
<package id="Microsoft.AspNet.SignalR.JS" version="1.0.1" targetFramework="net40" />
<package id="Microsoft.AspNet.SignalR.Owin" version="1.0.1" targetFramework="net40" />
<package id="Microsoft.AspNet.SignalR.SystemWeb" version="1.0.1" targetFramework="net40" />
最佳答案
根据 MSDN GetBaseException 应该表现得像
public Exception GetBaseException()
{
Exception result = this;
while (result.InnerException != null)
result = result.InnerException;
return result;
}
并州
这就引出了一个问题,为什么这种方法是虚拟的?似乎任何覆盖都只能匹配实现或违反契约(Contract)。
根据 MSDN AggregateException.GetBaseException
根据 OP 的声明(以及对源代码的检查),可能会违反“返回 AggregateException”,因为结果并不总是 AggregateException。
坦率地说,我发现整个陈述是不合逻辑的,因为我认为“第一个”非聚合异常是“此异常的根本原因”,因为人们可以确定一个单一的(“该”)根本原因。由于“常规”异常只是在朝着并行处理“扇出”的根移动时被包裹在 AggregateExceptions 中。
我最好的解释是 AggregateException.GetBaseException 旨在“解开”毫无意义的非并行嵌套 AggregateExceptions,直到达到“扇出”实际发生的水平。
这里的错误(稍后修复)似乎是当没有“扇出”时会发生什么,即只有一个(非聚合)InnerException 的 AggregateException。在这种情况下,它返回那个(非聚合)异常。 .... 它有不同的 GetBaseException 实现/解释。
编辑 2020: 在中间几年的某个时刻,AggregateException.GetBaseException's implementation 被修复以符合上述解释。 @Jan-Slodicka 的回答表明它至少早在 2016 年就在 Mono 中得到了修复。