Provides extended formatting serivces that can be applied to all reference and value types. This class merely analyzes object that should be formatted and then delegates formatting to the specific formatter most appropriate for the given type.
Inheritance: VerboseFormatInfoBase
        /// <summary>
        ///     Creates new instance of verbose formatter which can be applied to format multi-lined string without any decorations.
        ///     This format is applicable to objets of medium complexity. Indentation is performed using multiple whitespace characters.
        /// </summary>
        /// <returns>
        ///     New instance of verbose formatter which can be used to format multi-lined strings
        ///     in which indentation is performed using whitespace characters.
        /// </returns>
        public static VerboseFormatInfoBase CreateMultiLinedFormatter()
        {
            var vfi = new VerboseFormatInfo();

            vfi.FieldDelimiter     = Environment.NewLine;
            vfi.IsMultiLinedFormat = true;

            vfi.IndentationString      = vfi.RightMostIndentationString = vfi.LastIndentationString = vfi.LastRightMostIndentationString = "    ";
            vfi.MaximumFormattedLength = DefaultMaxFormattedLength;

            return(vfi);
        }
Example #2
0
 /// <summary>
 ///     Copy constructor. Used to copy common property values from another formatter of the same type,
 ///     which results in creating output string which is formatted in the same way.
 /// </summary>
 /// <param name="other">Instance from which contents is copied to new instance of this class.</param>
 public VerboseFormatInfo(VerboseFormatInfo other)
     : base(other)
 {
 }
		/// <summary>
		///     Copy constructor. Used to copy common property values from another formatter of the same type,
		///     which results in creating output string which is formatted in the same way.
		/// </summary>
		/// <param name="other">Instance from which contents is copied to new instance of this class.</param>
		public VerboseFormatInfo(VerboseFormatInfo other)
			: base(other) {}
        /// <summary>
        ///     Appends formatted string representing part of the array provided, starting from specific location within the array.
        /// </summary>
        /// <param name="sb">String builder to which formatted string will be appended.</param>
        /// <param name="arg">Array which should be formatted into string which is appended to <paramref name="sb" />.</param>
        /// <param name="indices">
        ///     List of index values for dimensions iterated this far. In every call, this method will continue
        ///     from location within the array indicated by this parameter.
        /// </param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to the formatter.
        ///     Single-lined formatting will fail (and return false) if this number of characters is breached.
        ///     Multi-lined formatters ignore this parameter. Negative value indicates
        ///     that formatter has unlimited space available. On output contains remaining number of characters available.
        /// </param>
        /// <returns>
        ///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
        ///     within given number of allowed characters; otherwise false.
        /// </returns>
        private bool RecursiveAppendDimension(StringBuilder sb, Array arg, List <int> indices, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            var dimension = arg.GetLength(indices.Count);

            if (dimension > 0)
            {
                for (var i = 0; i < dimension; i++)
                {
                    indices.Add(i);

                    IncIndentationLevel(i < dimension - 1);

                    success = success && FormatLinePrefix(sb, true, i == dimension - 1, false, 0, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, "Item[", success, ref maxLength);

                    var firstIndex = true;
                    foreach (var index in indices)
                    {
                        if (!firstIndex)
                        {
                            success = FormatInfoUtils.TryAppendString(this, sb, ", ", success, ref maxLength);
                        }
                        firstIndex = false;
                        success    = FormatInfoUtils.TryAppendString(this, sb, index.ToString("0"), success, ref maxLength);
                    }

                    success = FormatInfoUtils.TryAppendString(this, sb, "] ", success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

                    if (indices.Count < arg.Rank)
                    {
                        success = success && RecursiveAppendDimension(sb, arg, indices, ref maxLength);
                    }
                    else
                    {
                        var value = arg.GetValue(indices.ToArray());

                        var vfi = new VerboseFormatInfo(this);
                        vfi.MaximumFormattedLength =
                            FormatInfoUtils.CombineMaxFormattedLengths(
                                RawMaximumFormattedLength,
                                FormatInfoUtils.DefaultMaxFormattedLength);

                        success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
                        success = success && vfi.Format(sb, null, value, vfi, ref maxLength);
                    }

                    success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);

                    DecIndentationLevel();

                    indices.RemoveAt(indices.Count - 1);
                }
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
		/// <summary>
		///     Creates new instance of verbose formatter which can be applied to format multi-lined string without any decorations.
		///     This format is applicable to objets of medium complexity. Indentation is performed using multiple whitespace characters.
		/// </summary>
		/// <returns>
		///     New instance of verbose formatter which can be used to format multi-lined strings
		///     in which indentation is performed using whitespace characters.
		/// </returns>
		public static VerboseFormatInfoBase CreateMultiLinedFormatter()
		{
			var vfi = new VerboseFormatInfo();

			vfi.FieldDelimiter = Environment.NewLine;
			vfi.IsMultiLinedFormat = true;

			vfi.IndentationString = vfi.RightMostIndentationString = vfi.LastIndentationString = vfi.LastRightMostIndentationString = "    ";
			vfi.MaximumFormattedLength = DefaultMaxFormattedLength;

			return vfi;
		}
		/// <summary>
		///     Converts the value of a specified object to an equivalent string representation using
		///     specified format and culture-specific formatting information.
		/// </summary>
		/// <param name="sb">String builder to which formatted string will be appended.</param>
		/// <param name="format">Format string containing formatting specifications.</param>
		/// <param name="arg">An object to format.</param>
		/// <param name="formatProvider">An object that supplies format information about the current instance.</param>
		/// <param name="maxLength">
		///     Maximum number of characters allowed to the formatter. Formatting will fail (and return false)
		///     if this number of characters is breached. Multi-lined formatters will ignore this parameter.
		///     Negative value indicates that formatter has unlimited space available.
		///     On output contains remaining number of characters available.
		/// </param>
		/// <returns>
		///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
		///     within given number of allowed characters; otherwise false.
		/// </returns>
		internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength)
		{
			var success = true;
			var originalLength = sb.Length;

			if (PushCurrentObject(arg))
			{
				if (ShowDataType)
				{
					success = success && AppendInstanceTypeName(arg, sb, ref maxLength);
				}

				if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName))
				{
					success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
					success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);

					if (IsMultiLinedFormat)
					{
						success = FormatInfoUtils.TryAppendString(this, sb, " = ", success, ref maxLength);
					}
					else
					{
						success = FormatInfoUtils.TryAppendChar(this, sb, '=', success, ref maxLength);
					}
				}
				else
				{
					success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
				}

				if (arg == null)
				{
					success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength);
				}
				else
				{
					success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

					if (MaximumDepth > 0)
					{
						MaximumDepth--;

						var members = ExtractMembers(arg);

						var vfi = new VerboseFormatInfo(this);
						vfi.ShowDataType = true;
						vfi.ShowInstanceName = true;

						for (var i = 0; success && i < members.Length; i++)
						{
							IncIndentationLevel(i < members.Length - 1);
							vfi.IncIndentationLevel(i < members.Length - 1);

							success = success && FormatLinePrefix(sb, i == 0, i == members.Length - 1, false, 0, ref maxLength);
							vfi.InstanceDataType = members[i].DataType;
							vfi.InstanceName = members[i].Name;
							success = success && vfi.Format(sb, format, members[i].Value, vfi, ref maxLength);

							vfi.DecIndentationLevel();
							DecIndentationLevel();
						}

						MaximumDepth++;
					}

					success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
				}

				PopCurrentObject();
			}
			else
			{
				success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
			}

			if (!success)
			{
				sb.Length = originalLength;
			}

			return success;
		}
        /// <summary>
        ///     Converts the value of a specified object to an equivalent string representation using
        ///     specified format and culture-specific formatting information.
        /// </summary>
        /// <param name="sb">String builder to which formatted string will be appended.</param>
        /// <param name="format">Format string containing formatting specifications.</param>
        /// <param name="arg">An object to format.</param>
        /// <param name="formatProvider">An object that supplies format information about the current instance.</param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to the formatter. Formatting will fail (and return false)
        ///     if this number of characters is breached. Multi-lined formatters will ignore this parameter.
        ///     Negative value indicates that formatter has unlimited space available.
        ///     On output contains remaining number of characters available.
        /// </param>
        /// <returns>
        ///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
        ///     within given number of allowed characters; otherwise false.
        /// </returns>
        internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (PushCurrentObject(arg))
            {
                if (ShowDataType)
                {
                    success = success && AppendInstanceTypeName(arg, sb, ref maxLength);
                }

                if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName))
                {
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);

                    if (IsMultiLinedFormat)
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb, " = ", success, ref maxLength);
                    }
                    else
                    {
                        success = FormatInfoUtils.TryAppendChar(this, sb, '=', success, ref maxLength);
                    }
                }
                else
                {
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                }

                if (arg == null)
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength);
                }
                else
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

                    if (MaximumDepth > 0)
                    {
                        MaximumDepth--;

                        var members = ExtractMembers(arg);

                        var vfi = new VerboseFormatInfo(this);
                        vfi.ShowDataType     = true;
                        vfi.ShowInstanceName = true;

                        for (var i = 0; success && i < members.Length; i++)
                        {
                            IncIndentationLevel(i < members.Length - 1);
                            vfi.IncIndentationLevel(i < members.Length - 1);

                            success = success && FormatLinePrefix(sb, i == 0, i == members.Length - 1, false, 0, ref maxLength);
                            vfi.InstanceDataType = members[i].DataType;
                            vfi.InstanceName     = members[i].Name;
                            success = success && vfi.Format(sb, format, members[i].Value, vfi, ref maxLength);

                            vfi.DecIndentationLevel();
                            DecIndentationLevel();
                        }

                        MaximumDepth++;
                    }

                    success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
                }

                PopCurrentObject();
            }
            else
            {
                success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
Example #8
0
        /// <summary>
        ///     Converts the value of a specified object to an equivalent string representation using
        ///     specified format and culture-specific formatting information.
        /// </summary>
        /// <param name="sb">String builder to which formatted string should be appended.</param>
        /// <param name="format">A format string containing formatting specifications.</param>
        /// <param name="arg">An object to format.</param>
        /// <param name="formatProvider">An object that supplies format information about the current instance.</param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to the formatter. Formatting should fail (and return false)
        ///     if this number of characters is breached. Multi-lined formatters should ignore this parameter.
        ///     Negative value indicates that formatter has unlimited space available. On output contains remaining number of characters available.
        /// </param>
        /// <returns>
        ///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
        ///     within given number of allowed characters; otherwise false.
        /// </returns>
        internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (PushCurrentObject(arg))
            {
                if (ShowDataType && !_showValuesOnly)
                {
                    success = success && AppendInstanceTypeName(arg, sb, ref maxLength);
                }

                if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName) && !_showValuesOnly)
                {
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);
                }

                if (!_showValuesOnly)
                {
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);
                }

                Type enumeratedType = null;
                var  enumerator     = GetEnumerator(arg, ref enumeratedType);

                var itemFormatter = new VerboseFormatInfo(this);

                var value        = new object[2];
                var valueFetched = new bool[2];

                valueFetched[0] = GetNextValue(enumerator, ref value[0]);
                if (valueFetched[0])
                {
                    valueFetched[1] = GetNextValue(enumerator, ref value[1]);
                }

                var itemPos = 0;

                while (valueFetched[0])
                {
                    IncIndentationLevel(valueFetched[1]);
                    itemFormatter.IncIndentationLevel(valueFetched[1]);

                    var valueName = string.Format("Item[{0}]", itemPos++);

                    itemFormatter.InstanceDataType = enumeratedType;
                    itemFormatter.InstanceName     = valueName;

                    success = success && FormatLinePrefix(sb, itemPos == 0, !valueFetched[1], false, 0, ref maxLength);
                    success = success && itemFormatter.Format(sb, null, value[0], itemFormatter, ref maxLength);

                    valueFetched[0] = valueFetched[1];
                    value[0]        = value[1];

                    valueFetched[1] = GetNextValue(enumerator, ref value[1]);

                    itemFormatter.DecIndentationLevel();
                    DecIndentationLevel();
                }

                if (!_showValuesOnly)
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
                }

                PopCurrentObject();
            }
            else
            {
                success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
		/// <summary>
		///     Appends formatted string representing part of the array provided, starting from specific location within the array.
		/// </summary>
		/// <param name="sb">String builder to which formatted string will be appended.</param>
		/// <param name="arg">Array which should be formatted into string which is appended to <paramref name="sb" />.</param>
		/// <param name="indices">
		///     List of index values for dimensions iterated this far. In every call, this method will continue
		///     from location within the array indicated by this parameter.
		/// </param>
		/// <param name="maxLength">
		///     Maximum number of characters allowed to the formatter.
		///     Single-lined formatting will fail (and return false) if this number of characters is breached.
		///     Multi-lined formatters ignore this parameter. Negative value indicates
		///     that formatter has unlimited space available. On output contains remaining number of characters available.
		/// </param>
		/// <returns>
		///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
		///     within given number of allowed characters; otherwise false.
		/// </returns>
		private bool RecursiveAppendDimension(StringBuilder sb, Array arg, List<int> indices, ref int maxLength)
		{
			var success = true;
			var originalLength = sb.Length;

			var dimension = arg.GetLength(indices.Count);

			if (dimension > 0)
			{
				for (var i = 0; i < dimension; i++)
				{
					indices.Add(i);

					IncIndentationLevel(i < dimension - 1);

					success = success && FormatLinePrefix(sb, true, i == dimension - 1, false, 0, ref maxLength);
					success = FormatInfoUtils.TryAppendString(this, sb, "Item[", success, ref maxLength);

					var firstIndex = true;
					foreach (var index in indices)
					{
						if (!firstIndex)
						{
							success = FormatInfoUtils.TryAppendString(this, sb, ", ", success, ref maxLength);
						}
						firstIndex = false;
						success = FormatInfoUtils.TryAppendString(this, sb, index.ToString("0"), success, ref maxLength);
					}

					success = FormatInfoUtils.TryAppendString(this, sb, "] ", success, ref maxLength);
					success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

					if (indices.Count < arg.Rank)
					{
						success = success && RecursiveAppendDimension(sb, arg, indices, ref maxLength);
					}
					else
					{
						var value = arg.GetValue(indices.ToArray());

						var vfi = new VerboseFormatInfo(this);
						vfi.MaximumFormattedLength =
							FormatInfoUtils.CombineMaxFormattedLengths(
																	   RawMaximumFormattedLength,
																	   FormatInfoUtils.DefaultMaxFormattedLength);

						success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
						success = success && vfi.Format(sb, null, value, vfi, ref maxLength);
					}

					success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);

					DecIndentationLevel();

					indices.RemoveAt(indices.Count - 1);
				}
			}

			if (!success)
			{
				sb.Length = originalLength;
			}

			return success;
		}
		/// <summary>
		///     Converts the value of a specified object to an equivalent string representation using
		///     specified format and culture-specific formatting information.
		/// </summary>
		/// <param name="sb">String builder to which formatted string should be appended.</param>
		/// <param name="format">A format string containing formatting specifications.</param>
		/// <param name="arg">An object to format.</param>
		/// <param name="formatProvider">An object that supplies format information about the current instance.</param>
		/// <param name="maxLength">
		///     Maximum number of characters allowed to the formatter. Formatting should fail (and return false)
		///     if this number of characters is breached. Multi-lined formatters should ignore this parameter.
		///     Negative value indicates that formatter has unlimited space available. On output contains remaining number of characters available.
		/// </param>
		/// <returns>
		///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
		///     within given number of allowed characters; otherwise false.
		/// </returns>
		internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength)
		{
			var success = true;
			var originalLength = sb.Length;

			if (PushCurrentObject(arg))
			{
				if (arg == null)
				{
					success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength);
				}
				else
				{
					var keys = GetKeysCollection(arg);
					var keyType = GetDeclaredKeyValueType(arg, true);
					var valueType = GetDeclaredKeyValueType(arg, false);

					var sfi = new ScalarFormatInfo(this);
					success = success && sfi.AppendInstanceTypeName(arg, sb, ref maxLength);
					// Using scalar format info to append type name ensures that scalar types will be
					// represented with their short forms rather than CTS names which are less readable

					if (!string.IsNullOrEmpty(InstanceName))
					{
						success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
						success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);
					}

					if (IsMultiLinedFormat)
					{
						success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
						success = FormatInfoUtils.TryAppendString(this, sb, "= ", success, ref maxLength);
					}
					else
					{
						success = FormatInfoUtils.TryAppendChar(this, sb, '=', success, ref maxLength);
					}

					success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

					if (MaximumDepth > 0)
					{
						MaximumDepth--;

						var enumerator = keys.GetEnumerator();

						var isFirstValue = true;

						var key = new object[2];
						var keyFetched = new bool[2];

						keyFetched[0] = enumerator.MoveNext();
						if (keyFetched[0])
						{
							key[0] = enumerator.Current;
							keyFetched[1] = enumerator.MoveNext();
							if (keyFetched[1])
							{
								key[1] = enumerator.Current;
							}
						}

						VerboseFormatInfoBase containedItemsFormat = new VerboseFormatInfo(this);

						var itemPos = 0;

						while (keyFetched[0])
						{
							IncIndentationLevel(keyFetched[1]);
							containedItemsFormat.IncIndentationLevel(keyFetched[1]);

							success = success && FormatLinePrefix(sb, isFirstValue, !keyFetched[1], false, 0, ref maxLength);
							isFirstValue = false;

							success = FormatInfoUtils.TryAppendString(this, sb, "Item[", success, ref maxLength);
							success = FormatInfoUtils.TryAppendString(this, sb, itemPos.ToString("0"), success, ref maxLength);
							itemPos++;
							success = FormatInfoUtils.TryAppendString(this, sb, "] = ", success, ref maxLength);
							success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

							containedItemsFormat.IncIndentationLevel(true);
							IncIndentationLevel(true);

							success = success && FormatLinePrefix(sb, true, false, false, 0, ref maxLength);
							containedItemsFormat.InstanceDataType = keyType;
							containedItemsFormat.InstanceName = "Key";
							success = success && containedItemsFormat.Format(sb, null, key[0], containedItemsFormat, ref maxLength);

							DecIndentationLevel();
							containedItemsFormat.DecIndentationLevel();

							containedItemsFormat.IncIndentationLevel(false);
							IncIndentationLevel(false);

							var value = GetValue(arg, key[0]);

							success = success && FormatLinePrefix(sb, false, true, false, 0, ref maxLength);
							containedItemsFormat.InstanceDataType = valueType;
							containedItemsFormat.InstanceName = "Value";
							success = success && containedItemsFormat.Format(sb, null, value, containedItemsFormat, ref maxLength);

							DecIndentationLevel();
							containedItemsFormat.DecIndentationLevel();

							success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);

							key[0] = key[1];
							keyFetched[0] = keyFetched[1];

							if (keyFetched[0])
							{
								keyFetched[1] = enumerator.MoveNext();
								if (keyFetched[1])
								{
									key[1] = enumerator.Current;
								}
							}

							containedItemsFormat.DecIndentationLevel();
							DecIndentationLevel();
						}

						MaximumDepth++;
					} // if (MaximumDepth > 0)

					success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
				}

				PopCurrentObject();
			}
			else
			{
				success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
			}

			if (!success)
			{
				sb.Length = originalLength;
			}

			return success;
		}
Example #11
0
        /// <summary>
        ///     Converts the value of a specified object to an equivalent string representation using
        ///     specified format and culture-specific formatting information.
        /// </summary>
        /// <param name="sb">String builder to which formatted string should be appended.</param>
        /// <param name="format">A format string containing formatting specifications.</param>
        /// <param name="arg">An object to format.</param>
        /// <param name="formatProvider">An object that supplies format information about the current instance.</param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to the formatter. Formatting should fail (and return false)
        ///     if this number of characters is breached. Multi-lined formatters should ignore this parameter.
        ///     Negative value indicates that formatter has unlimited space available. On output contains remaining number of characters available.
        /// </param>
        /// <returns>
        ///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
        ///     within given number of allowed characters; otherwise false.
        /// </returns>
        internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (PushCurrentObject(arg))
            {
                if (arg == null)
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength);
                }
                else
                {
                    var keys      = GetKeysCollection(arg);
                    var keyType   = GetDeclaredKeyValueType(arg, true);
                    var valueType = GetDeclaredKeyValueType(arg, false);

                    var sfi = new ScalarFormatInfo(this);
                    success = success && sfi.AppendInstanceTypeName(arg, sb, ref maxLength);
                    // Using scalar format info to append type name ensures that scalar types will be
                    // represented with their short forms rather than CTS names which are less readable

                    if (!string.IsNullOrEmpty(InstanceName))
                    {
                        success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                        success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);
                    }

                    if (IsMultiLinedFormat)
                    {
                        success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                        success = FormatInfoUtils.TryAppendString(this, sb, "= ", success, ref maxLength);
                    }
                    else
                    {
                        success = FormatInfoUtils.TryAppendChar(this, sb, '=', success, ref maxLength);
                    }

                    success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

                    if (MaximumDepth > 0)
                    {
                        MaximumDepth--;

                        var enumerator = keys.GetEnumerator();

                        var isFirstValue = true;

                        var key        = new object[2];
                        var keyFetched = new bool[2];

                        keyFetched[0] = enumerator.MoveNext();
                        if (keyFetched[0])
                        {
                            key[0]        = enumerator.Current;
                            keyFetched[1] = enumerator.MoveNext();
                            if (keyFetched[1])
                            {
                                key[1] = enumerator.Current;
                            }
                        }

                        VerboseFormatInfoBase containedItemsFormat = new VerboseFormatInfo(this);

                        var itemPos = 0;

                        while (keyFetched[0])
                        {
                            IncIndentationLevel(keyFetched[1]);
                            containedItemsFormat.IncIndentationLevel(keyFetched[1]);

                            success      = success && FormatLinePrefix(sb, isFirstValue, !keyFetched[1], false, 0, ref maxLength);
                            isFirstValue = false;

                            success = FormatInfoUtils.TryAppendString(this, sb, "Item[", success, ref maxLength);
                            success = FormatInfoUtils.TryAppendString(this, sb, itemPos.ToString("0"), success, ref maxLength);
                            itemPos++;
                            success = FormatInfoUtils.TryAppendString(this, sb, "] = ", success, ref maxLength);
                            success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

                            containedItemsFormat.IncIndentationLevel(true);
                            IncIndentationLevel(true);

                            success = success && FormatLinePrefix(sb, true, false, false, 0, ref maxLength);
                            containedItemsFormat.InstanceDataType = keyType;
                            containedItemsFormat.InstanceName     = "Key";
                            success = success && containedItemsFormat.Format(sb, null, key[0], containedItemsFormat, ref maxLength);

                            DecIndentationLevel();
                            containedItemsFormat.DecIndentationLevel();

                            containedItemsFormat.IncIndentationLevel(false);
                            IncIndentationLevel(false);

                            var value = GetValue(arg, key[0]);

                            success = success && FormatLinePrefix(sb, false, true, false, 0, ref maxLength);
                            containedItemsFormat.InstanceDataType = valueType;
                            containedItemsFormat.InstanceName     = "Value";
                            success = success && containedItemsFormat.Format(sb, null, value, containedItemsFormat, ref maxLength);

                            DecIndentationLevel();
                            containedItemsFormat.DecIndentationLevel();

                            success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);

                            key[0]        = key[1];
                            keyFetched[0] = keyFetched[1];

                            if (keyFetched[0])
                            {
                                keyFetched[1] = enumerator.MoveNext();
                                if (keyFetched[1])
                                {
                                    key[1] = enumerator.Current;
                                }
                            }

                            containedItemsFormat.DecIndentationLevel();
                            DecIndentationLevel();
                        }

                        MaximumDepth++;
                    }                     // if (MaximumDepth > 0)

                    success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
                }

                PopCurrentObject();
            }
            else
            {
                success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
		/// <summary>
		///     Converts the value of a specified object to an equivalent string representation using
		///     specified format and culture-specific formatting information.
		/// </summary>
		/// <param name="sb">String builder to which formatted string should be appended.</param>
		/// <param name="format">A format string containing formatting specifications.</param>
		/// <param name="arg">An object to format.</param>
		/// <param name="formatProvider">An object that supplies format information about the current instance.</param>
		/// <param name="maxLength">
		///     Maximum number of characters allowed to the formatter. Formatting should fail (and return false)
		///     if this number of characters is breached. Multi-lined formatters should ignore this parameter.
		///     Negative value indicates that formatter has unlimited space available. On output contains remaining number of characters available.
		/// </param>
		/// <returns>
		///     true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" />
		///     within given number of allowed characters; otherwise false.
		/// </returns>
		internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength)
		{
			var success = true;
			var originalLength = sb.Length;

			if (PushCurrentObject(arg))
			{
				if (ShowDataType && !_showValuesOnly)
				{
					success = success && AppendInstanceTypeName(arg, sb, ref maxLength);
				}

				if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName) && !_showValuesOnly)
				{
					success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
					success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);
				}

				if (!_showValuesOnly)
				{
					success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
					success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);
				}

				Type enumeratedType = null;
				var enumerator = GetEnumerator(arg, ref enumeratedType);

				var itemFormatter = new VerboseFormatInfo(this);

				var value = new object[2];
				var valueFetched = new bool[2];

				valueFetched[0] = GetNextValue(enumerator, ref value[0]);
				if (valueFetched[0])
				{
					valueFetched[1] = GetNextValue(enumerator, ref value[1]);
				}

				var itemPos = 0;

				while (valueFetched[0])
				{
					IncIndentationLevel(valueFetched[1]);
					itemFormatter.IncIndentationLevel(valueFetched[1]);

					var valueName = string.Format("Item[{0}]", itemPos++);

					itemFormatter.InstanceDataType = enumeratedType;
					itemFormatter.InstanceName = valueName;

					success = success && FormatLinePrefix(sb, itemPos == 0, !valueFetched[1], false, 0, ref maxLength);
					success = success && itemFormatter.Format(sb, null, value[0], itemFormatter, ref maxLength);

					valueFetched[0] = valueFetched[1];
					value[0] = value[1];

					valueFetched[1] = GetNextValue(enumerator, ref value[1]);

					itemFormatter.DecIndentationLevel();
					DecIndentationLevel();
				}

				if (!_showValuesOnly)
				{
					success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
				}

				PopCurrentObject();
			}
			else
			{
				success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
			}

			if (!success)
			{
				sb.Length = originalLength;
			}

			return success;
		}