Exception.GetBaseException()以非null InnerException返回异常

Die*_*ego 6 exception c#-4.0

我有这种类型的例外System.AggregateException:

Message = "One or more errors occurred."
Source = null
StackTrace = null
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

当我运行这个:

Exception excpetion = ex.GetBaseException();
Run Code Online (Sandbox Code Playgroud)

哪里exSystem.AggregateException我拿到System.Reflection.TargetInvocationExceptionexcpetion.怎么会发生这种情况?

脚本

我不知道如何在一个简单的项目中重现这一点.就我而言,我发现了一个SignalR项目.一些hub方法抛出异常,在global.asax处理错误:

GlobalHost.HubPipeline.AddModule(new MyHubPipelineModule());
Run Code Online (Sandbox Code Playgroud)

而且MyHubPipelineModule应该是这样的:

public class MyHubPipelineModule : HubPipelineModule
{
    protected override void OnIncomingError(Exception ex, IHubIncomingInvokerContext context)
    {
        Exception excpetion = ex.GetBaseException();
        context.Hub.Clients.Caller.ExceptionHandler(excpetion.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这应该使用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" />
Run Code Online (Sandbox Code Playgroud)

Die*_*ego 6

看来问题与 SignalR 无关。这与AggregateExceptions.

我正在查看AggregateException.GetBaseException 方法的 MSDN 页面,我发现了这个:

返回作为此异常的根本原因的 AggregateException

所以我猜想Exception.GetBaseException Method的文档仅在该方法未被重写时才有效。


Sen*_*ith 6

根据MSDN GetBaseException 应该表现得像

public Exception GetBaseException()
{ 
    Exception result = this; 
    while (result.InnerException != null) 
        result = result.InnerException; 
    return result; 
}
Run Code Online (Sandbox Code Playgroud)

和状态

对于一系列异常中的所有异常,GetBaseException方法必须返回相同的对象(基本异常).

这引出了一个问题,为什么这个方法是虚拟的?似乎任何覆盖只能匹配实现或违反合同.

根据MSDN AggregateException.GetBaseException

返回AggregateException,它是此异常的根本原因.

通过OP的声明(以及对源的检查),可以违反"返回AggregateException",因为结果并不总是 AggregateException.

坦率地说,我发现整个陈述都是不成功的,因为我认为"第一个"NON-AggregateException是"这个异常的根本原因",因为人们可以识别出一个单一的("the")根本原因.由于"常规"异常只会在并行处理"扇出"的根目录中移动时包含在AggregateExceptions中.

最好的解释是AggregateException.GetBaseException旨在"展开"无意义的非并行嵌套AggregateExceptions,直到达到实际发生'扇出'的级别.

这里的问题似乎是当没有'扇出'时会发生什么,即只有一个(非聚合)InnerException的AggregateException.在这种情况下,它返回(非聚合)异常.....具有不同的GetBaseException实现/解释.