#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); } } }