#region --------------- Copyright Dresser Wayne Pignone ------------- /* * $Log: /Wrk/WayneLibraries/Wrk/Log/StringLogObject.cs $ * * 5 08-02-13 9:30 Mattias.larsson * FxCop fixes. * * 4 07-03-19 17:12 roger.m�nsson * Allow null as LogObject. */ #endregion using System; using System.Text; using System.Diagnostics.CodeAnalysis; namespace Wayne.Lib.Log { /// <summary> /// The StringLogObject-class serves as a helpclass to convert one or more /// objects into one or more strings to log. Also provides format abilities. /// </summary> public class StringLogObject : ILogObject { #region Fields private object[] logObjects; private string format; private IFormatProvider provider; #endregion #region Construction /// <summary> /// Constructor. /// </summary> /// <param name="logObjects">A number of objects to log.</param> [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "objects")] public StringLogObject(params object[] logObjects) { this.logObjects = logObjects; } /// <summary> /// Constructor. /// </summary> /// <param name="format">A format-string to format the items of an array.</param> /// <param name="provider">An IFormatProvider to format the items of an array.</param> /// <param name="array">An array of objects to log.</param> public StringLogObject(string format, IFormatProvider provider, Array array) { this.format = format; this.provider = provider; this.logObjects = new object[] { array }; } /// <summary> /// Constructor. /// </summary> /// <param name="format">A format-string to format the items of an array.</param> /// <param name="provider">An IFormatProvider to format the items of an array.</param> /// <param name="logObjects">A number of objects to log.</param> [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "objects")] public StringLogObject(string format, IFormatProvider provider, params object[] logObjects) { this.format = format; this.provider = provider; this.logObjects = logObjects; } #endregion #region Properties bool ILogObject.UsesFormat { get { return true; } } string ILogObject.Format { get { return format; } set { format = value; } } IFormatProvider ILogObject.Provider { get { return provider; } set { provider = value; } } #endregion #region Methods /// <summary> /// Appends this object's logObjects to a StringBuilder-output. /// </summary> /// <param name="output">The StringBuilder.</param> /// <param name="logWriter">The LogWriter to write the logObject.</param> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="isFirstLine">Is this the first line to log?</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> void ILogObject.AppendToStringBuilder(LogWriter logWriter, StringBuilder output, int indentLength, ref bool isFirstLine, ref string indent) { foreach (object logObject in logObjects) AppendObjectToStringBuilder(logObject, output, logWriter, indentLength, ref isFirstLine, ref indent, format, provider); } #endregion #region Static Support Methods /// <summary> /// Appends an object to a StringBuilder-output. /// </summary> /// <param name="logObject">The object to log.</param> /// <param name="output">The StringBuilder.</param> /// <param name="logWriter">The LogWriter to write the logObject.</param> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="isFirstLine">Is this the first line to log?</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> internal static void AppendObjectToStringBuilder(object logObject, StringBuilder output, LogWriter logWriter, int indentLength, ref bool isFirstLine, ref string indent) { AppendObjectToStringBuilder(logObject, output, logWriter, indentLength, ref isFirstLine, ref indent, null, null); } /// <summary> /// Appends an object to a StringBuilder-output. /// </summary> /// <param name="logObject">The object to log.</param> /// <param name="output">The StringBuilder.</param> /// <param name="logWriter">The LogWriter to write the logObject.</param> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="isFirstLine">Is this the first line to log?</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> /// <param name="format">A format-string to format the objects.</param> /// <param name="provider">An IFormatProvider to format the objects.</param> private static void AppendObjectToStringBuilder(object logObject, StringBuilder output, LogWriter logWriter, int indentLength, ref bool isFirstLine, ref string indent, string format, IFormatProvider provider) { // Check if the logObject is an ILogObject. ILogObject iLogObject = logObject as ILogObject; if (iLogObject != null) { if (iLogObject.UsesFormat && (format != null) && (iLogObject.Format == null)) { // Copy my format to the stringLogObject. iLogObject.Format = format; iLogObject.Provider = provider; } iLogObject.AppendToStringBuilder(logWriter, output, indentLength, ref isFirstLine, ref indent); } else { string[] logLines = logObject as string[]; if (logLines != null) { // The logObject is an array of strings. AppendStringsToStringBuilder(logLines, output, logWriter, indentLength, ref isFirstLine, ref indent); } else { Array logObjectArray = logObject as Array; if (logObjectArray != null) { // This is an array. Was there a format provided? if (format != null) { // There is a format provided. In this case, write all the items in one string. StringBuilder arrayBuilder = new StringBuilder(); bool firstItem = true; foreach (object logObjectItem in logObjectArray) { // Append a separator character. if (firstItem) { firstItem = false; arrayBuilder.Append(" "); } else arrayBuilder.Append(", "); // try to format the object with the provided format and IFormatProvider. IFormattable formattableItem = logObjectItem as IFormattable; if (formattableItem != null) arrayBuilder.Append(formattableItem.ToString(format, provider)); else arrayBuilder.Append(logObjectItem.ToString()); } AppendStringToStringBuilder(arrayBuilder.ToString(), output, logWriter, indentLength, ref isFirstLine, ref indent); } else { // No format provided. Just write the objects one by one in a normal fashion. foreach (object arrayItem in logObjectArray) AppendObjectToStringBuilder(arrayItem, output, logWriter, indentLength, ref isFirstLine, ref indent); } } else { if (format != null) { IFormattable formattableItem = logObject as IFormattable; if (formattableItem != null) { // Format the logObject with the given format-string and IFormatProvider. try { AppendStringToStringBuilder(formattableItem.ToString(format, provider), output, logWriter, indentLength, ref isFirstLine, ref indent); } catch (FormatException) { // Simply convert the logObject to a string. AppendStringToStringBuilder(logObject.ToString(), output, logWriter, indentLength, ref isFirstLine, ref indent); } } else { // Simply convert the logObject to a string. AppendStringToStringBuilder(logObject.ToString(), output, logWriter, indentLength, ref isFirstLine, ref indent); } } else { // Simply convert the logObject to a string. if (logObject != null) AppendStringToStringBuilder(logObject.ToString(), output, logWriter, indentLength, ref isFirstLine, ref indent); else AppendStringToStringBuilder("null", output, logWriter, indentLength, ref isFirstLine, ref indent); } } } } } /// <summary> /// Appends a string to a StringBuilder-output. /// </summary> /// <param name="logString">The string to log.</param> /// <param name="output">The StringBuilder.</param> /// <param name="logWriter">The LogWriter to write the logObject.</param> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="isFirstLine">Is this the first line to log?</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> internal static void AppendStringToStringBuilder(string logString, StringBuilder output, LogWriter logWriter, int indentLength, ref bool isFirstLine, ref string indent) { // Check if the string contains new line-characters. if (logString.IndexOf("\r\n", StringComparison.Ordinal) > -1) { // Create an array of strings cutting after each new line-character. string[] logLines = logString.Replace("\r\n", "\uFFFF").Split('\uFFFF'); AppendStringsToStringBuilder(logLines, output, logWriter, indentLength, ref isFirstLine, ref indent); } else { if (isFirstLine) isFirstLine = false; else AppendIndent(output, indentLength, ref indent); output.Append(logString); // A normal single line string. output.Append("\r\n"); } } /// <summary> /// Appends a string-array to a StringBuilder-output. /// </summary> /// <param name="logLines">The array of strings.</param> /// <param name="output">The StringBuilder.</param> /// <param name="logWriter">The logwriter to be used for logging.</param> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="isFirstLine">Is this the first line to log?</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> internal static void AppendStringsToStringBuilder(string[] logLines, StringBuilder output, LogWriter logWriter, int indentLength, ref bool isFirstLine, ref string indent) { // Remove any empty lines at the end. int logLinesLength = logLines.Length; for (int i = logLines.Length - 1; i >= 0; i--) { if (string.IsNullOrEmpty(logLines[i])) logLinesLength--; else break; // The first non-empty line from the end is found. Stop. } // Log an array of strings. if (logLinesLength > 1) { for (int i = 0; i < logLinesLength; i++) AppendStringToStringBuilder(logLines[i], output, logWriter, indentLength, ref isFirstLine, ref indent); } else if (logLinesLength == 1) AppendStringToStringBuilder(logLines[0], output, logWriter, indentLength, ref isFirstLine, ref indent); } /// <summary> /// Appends the indent to a StringBuilder-output. /// (After this call the 'indent' is defined.) /// </summary> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> internal static void EnsureIndent(int indentLength, ref string indent) { if (indent == null) indent = Strings.Indent(indentLength, true); } /// <summary> /// Appends the indent to a StringBuilder-output. /// (After this call the 'indent' is defined.) /// </summary> /// <param name="output">The StringBuilder.</param> /// <param name="indentLength">The indent to be used if many lines.</param> /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param> internal static void AppendIndent(StringBuilder output, int indentLength, ref string indent) { EnsureIndent(indentLength, ref indent); output.Append(indent); } #endregion } }