#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
{
///
/// The StringLogObject-class serves as a helpclass to convert one or more
/// objects into one or more strings to log. Also provides format abilities.
///
public class StringLogObject : ILogObject
{
#region Fields
private object[] logObjects;
private string format;
private IFormatProvider provider;
#endregion
#region Construction
///
/// Constructor.
///
/// A number of objects to log.
[SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "objects")]
public StringLogObject(params object[] logObjects)
{
this.logObjects = logObjects;
}
///
/// Constructor.
///
/// A format-string to format the items of an array.
/// An IFormatProvider to format the items of an array.
/// An array of objects to log.
public StringLogObject(string format, IFormatProvider provider, Array array)
{
this.format = format;
this.provider = provider;
this.logObjects = new object[] { array };
}
///
/// Constructor.
///
/// A format-string to format the items of an array.
/// An IFormatProvider to format the items of an array.
/// A number of objects to log.
[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
///
/// Appends this object's logObjects to a StringBuilder-output.
///
/// The StringBuilder.
/// The LogWriter to write the logObject.
/// The indent to be used if many lines.
/// Is this the first line to log?
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
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
///
/// Appends an object to a StringBuilder-output.
///
/// The object to log.
/// The StringBuilder.
/// The LogWriter to write the logObject.
/// The indent to be used if many lines.
/// Is this the first line to log?
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
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);
}
///
/// Appends an object to a StringBuilder-output.
///
/// The object to log.
/// The StringBuilder.
/// The LogWriter to write the logObject.
/// The indent to be used if many lines.
/// Is this the first line to log?
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
/// A format-string to format the objects.
/// An IFormatProvider to format the objects.
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);
}
}
}
}
}
///
/// Appends a string to a StringBuilder-output.
///
/// The string to log.
/// The StringBuilder.
/// The LogWriter to write the logObject.
/// The indent to be used if many lines.
/// Is this the first line to log?
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
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");
}
}
///
/// Appends a string-array to a StringBuilder-output.
///
/// The array of strings.
/// The StringBuilder.
/// The logwriter to be used for logging.
/// The indent to be used if many lines.
/// Is this the first line to log?
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
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);
}
///
/// Appends the indent to a StringBuilder-output.
/// (After this call the 'indent' is defined.)
///
/// The indent to be used if many lines.
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
internal static void EnsureIndent(int indentLength, ref string indent)
{
if (indent == null)
indent = Strings.Indent(indentLength, true);
}
///
/// Appends the indent to a StringBuilder-output.
/// (After this call the 'indent' is defined.)
///
/// The StringBuilder.
/// The indent to be used if many lines.
/// A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.
internal static void AppendIndent(StringBuilder output, int indentLength, ref string indent)
{
EnsureIndent(indentLength, ref indent);
output.Append(indent);
}
#endregion
}
}