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

时间:2013-05-15 13:06:01

标签: c#-4.0 exception

我有System.AggregateException类型的例外:

Message = "One or more errors occurred."
Source = null
StackTrace = null

InnerExceptionSystem.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)

InnerExceptionApplicationException这个由我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.TargetInvocationExceptionexcpetionGlobalHost.HubPipeline.AddModule(new MyHubPipelineModule()); MyHubPipelineModule的{​​{1}}。 这怎么可能发生?

方案

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

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

<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" /> 应该是这样的:

{{1}}

注意:这应该使用SignalR 1.0.1完成。在1.1.0中,异常更简单(更小的链),因此它运行良好。确保您拥有此软件包版本:

{{1}}

3 个答案:

答案 0 :(得分:6)

根据MSDN GetBaseException应该表现得像

public Exception GetBaseException()
{ 
    Exception result = this; 
    while (result.InnerException != null) 
        result = result.InnerException; 
    return result; 
}

状态

  

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

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

根据MSDN AggregateException.GetBaseException

  

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

通过OP的声明(以及对源的检查),&#34;返回AggregateException&#34;可以违反,因为结果不是总是一个AggregateException。

坦率地说,我发现整个陈述都是不合理的,因为我会考虑“第一个”。 NON-AggregateException是&#34;此异常的根本原因&#34;只要能够识别单一(&#34;&#34;)根本原因。因为&#34;常规&#34;当一个人走向并行处理的根源时,异常只会被包含在AggregateExceptions中,并且会被淘汰。

我的最佳解释是AggregateException.GetBaseException旨在&#34;展开&#34;毫无意义的非并行嵌套AggregateExceptions,直到达到“扇出”的水平。实际发生。

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

答案 1 :(得分:3)

似乎问题与SignalR无关。它与AggregateExceptions

有关

我看着MSDN page of AggregateException.GetBaseException Method,我发现了这个:

  

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

所以我想只有在没有覆盖方法的情况下,Exception.GetBaseException Method的文档才有效。

答案 2 :(得分:1)

这是Mono源代码:

public override Exception GetBaseException() {
    Exception back = this;
    AggregateException backAsAggregate = this;
    while (backAsAggregate != null && backAsAggregate.InnerExceptions.Count == 1) {
        back = back.InnerException;
        backAsAggregate = back as AggregateException;
    }
    return back;
}

这意味着GetBaseException()只删除最顶层的普通的AggregateException包装。

我认为应该在进行例外报告之前始终应用该方法。