You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-dev@logging.apache.org by ni...@apache.org on 2006/03/02 16:38:12 UTC

svn commit: r382413 - /logging/log4net/trunk/src/ObjectRenderer/DefaultRenderer.cs

Author: nicko
Date: Thu Mar  2 07:38:11 2006
New Revision: 382413

URL: http://svn.apache.org/viewcvs?rev=382413&view=rev
Log:
Fix for LOG4NET-56. Added support for rendering all IEnumerable types rather than just collections. Added spacial case for IDictionary to ensure that the enumerator returned will enumerate DisctionaryEntry objects even with .NET 2.0 generic collections.

Modified:
    logging/log4net/trunk/src/ObjectRenderer/DefaultRenderer.cs

Modified: logging/log4net/trunk/src/ObjectRenderer/DefaultRenderer.cs
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/src/ObjectRenderer/DefaultRenderer.cs?rev=382413&r1=382412&r2=382413&view=diff
==============================================================================
--- logging/log4net/trunk/src/ObjectRenderer/DefaultRenderer.cs (original)
+++ logging/log4net/trunk/src/ObjectRenderer/DefaultRenderer.cs Thu Mar  2 07:38:11 2006
@@ -1,6 +1,6 @@
 #region Copyright & License
 //
-// Copyright 2001-2005 The Apache Software Foundation
+// Copyright 2001-2006 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -96,8 +96,10 @@
 		///			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:
-		///			<c>int[] {1, 2, 3}</c>.
+		///			renderer), followed by a close brace. 
+		///			</para>
+		///			<para>
+		///			For example: <c>int[] {1, 2, 3}</c>.
 		///			</para>
 		///			<para>
 		///			If the array is not one dimensional the 
@@ -106,13 +108,19 @@
 		///			</description>
 		///		</item>
 		///		<item>
-		///			<term><see cref="ICollection"/></term>
+		///			<term><see cref="IEnumerable"/></term>
 		///			<description>
 		///			<para>
 		///			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:
-		///			<c>{a, b, c}</c>.
+		///			renderer), followed by a close brace.
+		///			</para>
+		///			<para>
+		///			For example: <c>{a, b, c}</c>.
+		///			</para>
+		///			<para>
+		///			All collection classes that implement <see cref="ICollection"/> its subclasses, 
+		///			or generic equivalents all implement the <see cref="IEnumerable"/> interface.
 		///			</para>
 		///			</description>
 		///		</item>		
@@ -121,7 +129,10 @@
 		///			<description>
 		///			<para>
 		///			Rendered as the key, an equals sign ('='), and the value (using the appropriate
-		///			renderer). For example: <c>key=value</c>.
+		///			renderer). 
+		///			</para>
+		///			<para>
+		///			For example: <c>key=value</c>.
 		///			</para>
 		///			</description>
 		///		</item>		
@@ -152,11 +163,33 @@
 				RenderArray(rendererMap, objArray, writer);
 				return;
 			}
-			
-			ICollection objCollection = obj as ICollection;
-			if (objCollection != null)
+
+			// Test if we are dealing with some form of collection object
+			IEnumerable objEnumerable = obj as IEnumerable;
+			if (objEnumerable != null)
 			{
-				RenderCollection(rendererMap, objCollection, writer);
+				// 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;
 			}
 			
@@ -216,10 +249,10 @@
 		}
 
 		/// <summary>
-		/// Render the collection argument into a string
+		/// Render the enumerator argument into a string
 		/// </summary>
 		/// <param name="rendererMap">The map used to lookup renderers</param>
-		/// <param name="collection">the collection to render</param>
+		/// <param name="enumerator">the enumerator to render</param>
 		/// <param name="writer">The writer to render to</param>
 		/// <remarks>
 		/// <para>
@@ -229,22 +262,18 @@
 		///	<c>{a, b, c}</c>.
 		///	</para>
 		/// </remarks>
-		private void RenderCollection(RendererMap rendererMap, ICollection collection, TextWriter writer)
+		private void RenderEnumerator(RendererMap rendererMap, IEnumerator enumerator, TextWriter writer)
 		{
 			writer.Write("{");
 
-			if (collection.Count > 0)
+			if (enumerator != null && enumerator.MoveNext())
 			{
-				IEnumerator enumerator = collection.GetEnumerator();
-				if (enumerator != null && enumerator.MoveNext())
+				rendererMap.FindAndRender(enumerator.Current, writer);
+
+				while (enumerator.MoveNext())
 				{
+					writer.Write(", ");
 					rendererMap.FindAndRender(enumerator.Current, writer);
-
-					while(enumerator.MoveNext())
-					{
-						writer.Write(", ");
-						rendererMap.FindAndRender(enumerator.Current, writer);
-					}
 				}
 			}