// Copyright 2009-2022 Josh Close // This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. // See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. // https://github.com/JoshClose/CsvHelper using CsvHelper.Configuration; using System; using System.Text; namespace CsvHelper { /// /// Represents errors that occur in CsvHelper. /// [Serializable] public class CsvHelperException : Exception { [NonSerialized] private readonly CsvContext context; /// /// Gets the context. /// public CsvContext Context => context; /// /// Initializes a new instance of the CsvHelperException class. /// internal protected CsvHelperException() : base() { } /// /// Initializes a new instance of the CsvHelperException class. /// /// The message that describes the error. internal protected CsvHelperException(string message) : base(message) { } /// /// Initializes a new instance of the CsvHelperException class. /// /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. internal protected CsvHelperException(string message, Exception innerException) : base(message, innerException) { } /// /// Initializes a new instance of the class. /// public CsvHelperException(CsvContext context) { this.context = context; } /// /// Initializes a new instance of the class /// with a specified error message. /// /// The context. /// The message that describes the error. public CsvHelperException(CsvContext context, string message) : base(AddDetails(message, context)) { this.context = context; } /// /// Initializes a new instance of the class /// with a specified error message and a reference to the inner exception that /// is the cause of this exception. /// /// The context. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. public CsvHelperException(CsvContext context, string message, Exception innerException) : base(AddDetails(message, context), innerException) { this.context = context; } private static string AddDetails(string message, CsvContext context) { var indent = new string(' ', 3); var details = new StringBuilder(); if (context.Reader != null) { details.AppendLine($"{nameof(IReader)} state:"); details.AppendLine($"{indent}{nameof(IReader.ColumnCount)}: {context.Reader.ColumnCount}"); details.AppendLine($"{indent}{nameof(IReader.CurrentIndex)}: {context.Reader.CurrentIndex}"); try { var record = new StringBuilder(); if (context.Reader.HeaderRecord != null) { record.Append("[\""); record.Append(string.Join("\",\"", context.Reader.HeaderRecord)); record.Append("\"]"); } details.AppendLine($"{indent}{nameof(IReader.HeaderRecord)}:{Environment.NewLine}{record}"); } catch { } } if (context.Parser != null) { details.AppendLine($"{nameof(IParser)} state:"); details.AppendLine($"{indent}{nameof(IParser.ByteCount)}: {context.Parser.ByteCount}"); details.AppendLine($"{indent}{nameof(IParser.CharCount)}: {context.Parser.CharCount}"); details.AppendLine($"{indent}{nameof(IParser.Row)}: {context.Parser.Row}"); details.AppendLine($"{indent}{nameof(IParser.RawRow)}: {context.Parser.RawRow}"); details.AppendLine($"{indent}{nameof(IParser.Count)}: {context.Parser.Count}"); try { var rawRecord = context.Configuration.ExceptionMessagesContainRawData ? context.Parser.RawRecord : $"Hidden because {nameof(IParserConfiguration.ExceptionMessagesContainRawData)} is false."; details.AppendLine($"{indent}{nameof(IParser.RawRecord)}:{Environment.NewLine}{rawRecord}"); } catch { } } if (context.Writer != null) { details.AppendLine($"{nameof(IWriter)} state:"); details.AppendLine($"{indent}{nameof(IWriter.Row)}: {context.Writer.Row}"); details.AppendLine($"{indent}{nameof(IWriter.Index)}: {context.Writer.Index}"); var record = new StringBuilder(); if (context.Writer.HeaderRecord != null) { record.Append("["); if (context.Writer.HeaderRecord.Length > 0) { record.Append("\""); record.Append(string.Join("\",\"", context.Writer.HeaderRecord)); record.Append("\""); } record.Append("]"); } details.AppendLine($"{indent}{nameof(IWriter.HeaderRecord)}:{Environment.NewLine}{context.Writer.Row}"); } return $"{message}{Environment.NewLine}{details}"; } } }