using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text; namespace Swan { /// /// Provides methods to perform self-checks in library or application code. /// public static class SelfCheck { /// /// Creates and returns an exception telling that an internal self-check has failed. /// The returned exception will be of type ; its /// Message property will contain the specified /// , preceded by an indication of the assembly, source file, /// and line number of the failed check. /// /// The exception message. /// The path of the source file where this method is called. /// This parameter is automatically added by the compiler amd should never be provided explicitly. /// The line number in source where this method is called. /// This parameter is automatically added by the compiler amd should never be provided explicitly. /// /// A newly-created instance of . /// public static InternalErrorException Failure(string message, [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0) => new InternalErrorException(BuildMessage(message, filePath, lineNumber)); private static string BuildMessage(string message, string filePath, int lineNumber) { var frames = new StackTrace().GetFrames(); if (frames == null) return message; try { filePath = Path.GetFileName(filePath); } catch (ArgumentException) { } var frame = frames.FirstOrDefault(f => f.GetMethod().ReflectedType != typeof(SelfCheck)); var sb = new StringBuilder() .Append('[') .Append(frame?.GetType().Assembly.GetName().Name ?? ""); if (!string.IsNullOrEmpty(filePath)) { sb.Append(": ").Append(filePath); if (lineNumber > 0) sb.Append('(').Append(lineNumber).Append(')'); } return sb.Append("] ").Append(message).ToString(); } } }