#region Apache License
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Text;
using System.IO;
using System.Collections;
using log4net.Util;
namespace log4net.ObjectRenderer
{
///
/// The default object Renderer.
///
///
///
/// The default renderer supports rendering objects and collections to strings.
///
///
/// See the method for details of the output.
///
///
/// Nicko Cadell
/// Gert Driesen
public sealed class DefaultRenderer : IObjectRenderer
{
#region Constructors
///
/// Default constructor
///
///
///
/// Default constructor
///
///
public DefaultRenderer()
{
}
#endregion
#region Implementation of IObjectRenderer
///
/// Render the object to a string
///
/// The map used to lookup renderers
/// The object to render
/// The writer to render to
///
///
/// Render the object to a string.
///
///
/// The parameter is
/// provided to lookup and render other objects. This is
/// very useful where contains
/// nested objects of unknown type. The
/// method can be used to render these objects.
///
///
/// The default renderer supports rendering objects to strings as follows:
///
///
///
/// Value
/// Rendered String
///
/// -
/// null
///
/// "(null)"
///
///
/// -
///
///
///
/// For a one dimensional array this is the
/// array type name, an open brace, followed by a comma
/// separated list of the elements (using the appropriate
/// renderer), followed by a close brace.
///
///
/// For example: int[] {1, 2, 3}.
///
///
/// If the array is not one dimensional the
/// Array.ToString() is returned.
///
///
///
/// -
/// , &
///
///
/// Rendered as an open brace, followed by a comma
/// separated list of the elements (using the appropriate
/// renderer), followed by a close brace.
///
///
/// For example: {a, b, c}.
///
///
/// All collection classes that implement its subclasses,
/// or generic equivalents all implement the interface.
///
///
///
/// -
///
///
///
/// Rendered as the key, an equals sign ('='), and the value (using the appropriate
/// renderer).
///
///
/// For example: key=value.
///
///
///
/// -
/// other
///
/// Object.ToString()
///
///
///
///
public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer)
{
if (rendererMap == null)
{
throw new ArgumentNullException("rendererMap");
}
if (obj == null)
{
writer.Write(SystemInfo.NullText);
return;
}
Array objArray = obj as Array;
if (objArray != null)
{
RenderArray(rendererMap, objArray, writer);
return;
}
// Test if we are dealing with some form of collection object
IEnumerable objEnumerable = obj as IEnumerable;
if (objEnumerable != null)
{
// Get a collection interface if we can as its .Count property may be more
// performant than getting the IEnumerator object and trying to advance it.
ICollection objCollection = obj as ICollection;
if (objCollection != null && objCollection.Count == 0)
{
writer.Write("{}");
return;
}
// This is a special check to allow us to get the enumerator from the IDictionary
// interface as this guarantees us DictionaryEntry objects. Note that in .NET 2.0
// the generic IDictionary<> interface enumerates KeyValuePair objects rather than
// DictionaryEntry ones. However the implementation of the plain IDictionary
// interface on the generic Dictionary<> still returns DictionaryEntry objects.
IDictionary objDictionary = obj as IDictionary;
if (objDictionary != null)
{
RenderEnumerator(rendererMap, objDictionary.GetEnumerator(), writer);
return;
}
RenderEnumerator(rendererMap, objEnumerable.GetEnumerator(), writer);
return;
}
IEnumerator objEnumerator = obj as IEnumerator;
if (objEnumerator != null)
{
RenderEnumerator(rendererMap, objEnumerator, writer);
return;
}
if (obj is DictionaryEntry)
{
RenderDictionaryEntry(rendererMap, (DictionaryEntry)obj, writer);
return;
}
string str = obj.ToString();
writer.Write( (str==null) ? SystemInfo.NullText : str );
}
#endregion
///
/// Render the array argument into a string
///
/// The map used to lookup renderers
/// the array to render
/// The writer to render to
///
///
/// For a one dimensional array this is the
/// array type name, an open brace, followed by a comma
/// separated list of the elements (using the appropriate
/// renderer), followed by a close brace. For example:
/// int[] {1, 2, 3}.
///
///
/// If the array is not one dimensional the
/// Array.ToString() is returned.
///
///
private void RenderArray(RendererMap rendererMap, Array array, TextWriter writer)
{
if (array.Rank != 1)
{
writer.Write(array.ToString());
}
else
{
writer.Write(array.GetType().Name + " {");
int len = array.Length;
if (len > 0)
{
rendererMap.FindAndRender(array.GetValue(0), writer);
for(int i=1; i
/// Render the enumerator argument into a string
///
/// The map used to lookup renderers
/// the enumerator to render
/// The writer to render to
///
///
/// Rendered as an open brace, followed by a comma
/// separated list of the elements (using the appropriate
/// renderer), followed by a close brace. For example:
/// {a, b, c}.
///
///
private void RenderEnumerator(RendererMap rendererMap, IEnumerator enumerator, TextWriter writer)
{
writer.Write("{");
if (enumerator != null && enumerator.MoveNext())
{
rendererMap.FindAndRender(enumerator.Current, writer);
while (enumerator.MoveNext())
{
writer.Write(", ");
rendererMap.FindAndRender(enumerator.Current, writer);
}
}
writer.Write("}");
}
///
/// Render the DictionaryEntry argument into a string
///
/// The map used to lookup renderers
/// the DictionaryEntry to render
/// The writer to render to
///
///
/// Render the key, an equals sign ('='), and the value (using the appropriate
/// renderer). For example: key=value.
///
///
private void RenderDictionaryEntry(RendererMap rendererMap, DictionaryEntry entry, TextWriter writer)
{
rendererMap.FindAndRender(entry.Key, writer);
writer.Write("=");
rendererMap.FindAndRender(entry.Value, writer);
}
}
}