1
#region Copyright & License
3
// Copyright 2001-2006 The Apache Software Foundation
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
9
// http://www.apache.org/licenses/LICENSE-2.0
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
22
using System.Collections;
26
namespace log4net.ObjectRenderer
29
/// The default object Renderer.
33
/// The default renderer supports rendering objects and collections to strings.
36
/// See the <see cref="RenderObject"/> method for details of the output.
39
/// <author>Nicko Cadell</author>
40
/// <author>Gert Driesen</author>
41
public sealed class DefaultRenderer : IObjectRenderer
46
/// Default constructor
50
/// Default constructor
53
public DefaultRenderer()
59
#region Implementation of IObjectRenderer
62
/// Render the object <paramref name="obj"/> to a string
64
/// <param name="rendererMap">The map used to lookup renderers</param>
65
/// <param name="obj">The object to render</param>
66
/// <param name="writer">The writer to render to</param>
69
/// Render the object <paramref name="obj"/> to a string.
72
/// The <paramref name="rendererMap"/> parameter is
73
/// provided to lookup and render other objects. This is
74
/// very useful where <paramref name="obj"/> contains
75
/// nested objects of unknown type. The <see cref="RendererMap.FindAndRender(object)"/>
76
/// method can be used to render these objects.
79
/// The default renderer supports rendering objects to strings as follows:
81
/// <list type="table">
83
/// <term>Value</term>
84
/// <description>Rendered String</description>
87
/// <term><c>null</c></term>
89
/// <para>"(null)"</para>
93
/// <term><see cref="Array"/></term>
96
/// For a one dimensional array this is the
97
/// array type name, an open brace, followed by a comma
98
/// separated list of the elements (using the appropriate
99
/// renderer), followed by a close brace.
102
/// For example: <c>int[] {1, 2, 3}</c>.
105
/// If the array is not one dimensional the
106
/// <c>Array.ToString()</c> is returned.
111
/// <term><see cref="IEnumerable"/>, <see cref="ICollection"/> & <see cref="IEnumerator"/></term>
114
/// Rendered as an open brace, followed by a comma
115
/// separated list of the elements (using the appropriate
116
/// renderer), followed by a close brace.
119
/// For example: <c>{a, b, c}</c>.
122
/// All collection classes that implement <see cref="ICollection"/> its subclasses,
123
/// or generic equivalents all implement the <see cref="IEnumerable"/> interface.
128
/// <term><see cref="DictionaryEntry"/></term>
131
/// Rendered as the key, an equals sign ('='), and the value (using the appropriate
135
/// For example: <c>key=value</c>.
140
/// <term>other</term>
142
/// <para><c>Object.ToString()</c></para>
147
public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer)
149
if (rendererMap == null)
151
throw new ArgumentNullException("rendererMap");
156
writer.Write(SystemInfo.NullText);
160
Array objArray = obj as Array;
161
if (objArray != null)
163
RenderArray(rendererMap, objArray, writer);
167
// Test if we are dealing with some form of collection object
168
IEnumerable objEnumerable = obj as IEnumerable;
169
if (objEnumerable != null)
171
// Get a collection interface if we can as its .Count property may be more
172
// performant than getting the IEnumerator object and trying to advance it.
173
ICollection objCollection = obj as ICollection;
174
if (objCollection != null && objCollection.Count == 0)
180
// This is a special check to allow us to get the enumerator from the IDictionary
181
// interface as this guarantees us DictionaryEntry objects. Note that in .NET 2.0
182
// the generic IDictionary<> interface enumerates KeyValuePair objects rather than
183
// DictionaryEntry ones. However the implementation of the plain IDictionary
184
// interface on the generic Dictionary<> still returns DictionaryEntry objects.
185
IDictionary objDictionary = obj as IDictionary;
186
if (objDictionary != null)
188
RenderEnumerator(rendererMap, objDictionary.GetEnumerator(), writer);
192
RenderEnumerator(rendererMap, objEnumerable.GetEnumerator(), writer);
196
IEnumerator objEnumerator = obj as IEnumerator;
197
if (objEnumerator != null)
199
RenderEnumerator(rendererMap, objEnumerator, writer);
203
if (obj is DictionaryEntry)
205
RenderDictionaryEntry(rendererMap, (DictionaryEntry)obj, writer);
209
string str = obj.ToString();
210
writer.Write( (str==null) ? SystemInfo.NullText : str );
216
/// Render the array argument into a string
218
/// <param name="rendererMap">The map used to lookup renderers</param>
219
/// <param name="array">the array to render</param>
220
/// <param name="writer">The writer to render to</param>
223
/// For a one dimensional array this is the
224
/// array type name, an open brace, followed by a comma
225
/// separated list of the elements (using the appropriate
226
/// renderer), followed by a close brace. For example:
227
/// <c>int[] {1, 2, 3}</c>.
230
/// If the array is not one dimensional the
231
/// <c>Array.ToString()</c> is returned.
234
private void RenderArray(RendererMap rendererMap, Array array, TextWriter writer)
238
writer.Write(array.ToString());
242
writer.Write(array.GetType().Name + " {");
243
int len = array.Length;
247
rendererMap.FindAndRender(array.GetValue(0), writer);
248
for(int i=1; i<len; i++)
251
rendererMap.FindAndRender(array.GetValue(i), writer);
259
/// Render the enumerator argument into a string
261
/// <param name="rendererMap">The map used to lookup renderers</param>
262
/// <param name="enumerator">the enumerator to render</param>
263
/// <param name="writer">The writer to render to</param>
266
/// Rendered as an open brace, followed by a comma
267
/// separated list of the elements (using the appropriate
268
/// renderer), followed by a close brace. For example:
269
/// <c>{a, b, c}</c>.
272
private void RenderEnumerator(RendererMap rendererMap, IEnumerator enumerator, TextWriter writer)
276
if (enumerator != null && enumerator.MoveNext())
278
rendererMap.FindAndRender(enumerator.Current, writer);
280
while (enumerator.MoveNext())
283
rendererMap.FindAndRender(enumerator.Current, writer);
291
/// Render the DictionaryEntry argument into a string
293
/// <param name="rendererMap">The map used to lookup renderers</param>
294
/// <param name="entry">the DictionaryEntry to render</param>
295
/// <param name="writer">The writer to render to</param>
298
/// Render the key, an equals sign ('='), and the value (using the appropriate
299
/// renderer). For example: <c>key=value</c>.
302
private void RenderDictionaryEntry(RendererMap rendererMap, DictionaryEntry entry, TextWriter writer)
304
rendererMap.FindAndRender(entry.Key, writer);
306
rendererMap.FindAndRender(entry.Value, writer);