我有一个派生自AggregateException的自定义异常类.它如下所示.

正如您所看到的,我做的一件事是构建一个定制的Message,其中我截断内部异常以保持简短.

问题是,如果我在某个地方捕捉到这个异常,然后将ex.Message记录到控制台,它将包括我的消息,以及附加到我的消息中的每个内部异常的完整堆栈跟踪.问题是,这种聚合异常有时会包装绝对数量的内部异常,因为它处理的是一个长期运行的 Big Data 作业(job).应用程序性能很好,但它绝对是我们的日志(log)记录的destroying.

也就是说,消息最终显示为MyMessage + TonsOfExtraCrapGeneratedByDotNet.

为什么它会覆盖我的消息?指定一个定制消息来给我控制权的意义不是吗?我希望它被覆盖--而不是附加.

下面是一个可运行的.NET Fidel,它重现了这个问题:https://dotnetfiddle.net/0x4aD6

public class MyDerivedAggregateException : AggregateException
{
    // ... non-relevant code omitted

    public MyDerivedAggregateException (
        string message, 
        IEnumerable<Exception> innerExceptions,
        bool isEarlyTermination
    ) : base(BuildMessage(message, innerExceptions.ToList(), isEarlyTermination), innerExceptions) 
    {
    }
    
    private static string BuildMessage(string message, List<Exception> innerExs)
    {
        var sb = new StringBuilder();
        sb.AppendLine(message);
  
        int numToShow = Math.Min(5, innerExs.Count);
        int numNotShown = innerExs.Count - numToShow;
            
        for (int i = 0; i < numToShow; i++)
            sb.AppendLine($"Exception {i + 1}: {innerExs[i].Message}");

        if (numNotShown > 0)
            sb.AppendLine($"({numNotShown} more exceptions not shown...)");

        return sb.ToString();
    }
}

我甚至通过将下面的ToString()重写添加到我的异常中来测试它,这恰好是.NET认为该属性的值:

        public override string ToString()
        {
            File.WriteAllText("C:/Tests/exmessage.txt", Message);
            File.WriteAllText("C:/Tests/basemessage.txt", base.Message);
            File.WriteAllText("C:/Tests/basetostring.txt", base.ToString());

            return "Screw you .NET";
        }

在我的测试中,所有3个文件的内容都是相同的--它们包含所有多余的内容,而不仅仅是我提供给base()的基于AggregateException的值.

推荐答案

您可以将消息自定义存储在一个字段中,并通过重写Message属性来返回该消息.

public class MyDerivedAggregateException : AggregateException
{
    private readonly string _message;

    public MyDerivedAggregateException(
        string message,
        IEnumerable<Exception> innerExceptions,
        bool isEarlyTermination
        ) : base(string.Empty, innerExceptions)
    {
        _message = BuildMessage(message, innerExceptions.ToList());
    }

    public override string Message => _message;

    private static string BuildMessage(string message, List<Exception> innerExs)
    {
        var sb = new StringBuilder();
        sb.AppendLine(message);

        // Other message adjustments go here.

        return sb.ToString();
    }
}

Csharp相关问答推荐

Blazor:用参数创建根路径

O(N)测试失败

什么是通过反射创建类的泛型接口方法的正确方法?

如何在C#中将对象[*,*]直接转换为字符串[*,*]?

有没有办法在WPF文本框中添加复制事件的处理程序?

Quartz调度程序不调用作业(job)类

Thad.Sept()vs Task.Delay().Wait()

Blazorise折线图仅绘制数据集的一部分

为什么在使用动态obj+类obj时会调用串联?

我想在文本框悬停时在其底部显示一条线

Azure函数中实体框架核心的依赖注入

在C#中反序列化/序列化具有混合元素顺序的XML时出现问题

DateTime ToString()未以指定格式打印

RabbitMQ群集的MassTransit配置问题

MSTest--将消息直接写入StdOut和使用TestContext有什么不同?

如何返回具有泛型的类?

.NET8Blazor-为什么Rapzor渲染在for循环之后显示?

删除MudRadio时,MudRadioGroup未 Select 正确的MudRadio

WPF:如何从DatagridHeader的内容模板绑定到词典项

客户端/服务器RPC如何处理全局变量?