Logger.cs :  » Network-Clients » edtFTPnet » EnterpriseDT » Util » Debug » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Network Clients » edtFTPnet 
edtFTPnet » EnterpriseDT » Util » Debug » Logger.cs
// edtFTPnet
// 
// Copyright (C) 2004 Enterprise Distributed Technologies Ltd
// 
// www.enterprisedt.com
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Bug fixes, suggestions and comments should posted on 
// http://www.enterprisedt.com/forums/index.php
// 
// Change Log:
// 
// $Log: Logger.cs,v $
// Revision 1.30  2009-06-23 00:03:54  hans
// Prevent NRE when StackTrace is null.
//
// Revision 1.29  2009-04-02 04:10:38  bruceb
// CF defines
//
// Revision 1.28  2009-03-23 23:18:58  hans
// Fixed NRE in PrimaryLogFile.
//
// Revision 1.27  2008-12-04 01:36:33  bruceb
// catch errors reading config file
//
// Revision 1.26  2008-06-20 01:24:00  bruceb
// added ClearAppenders()
//
// Revision 1.25  2008-04-16 00:35:59  hans
// Added overload for Error that takes a variable argument-list.
//
// Revision 1.24  2008-04-14 00:10:38  bruceb
// synchronize iterations
//
// Revision 1.23  2007-06-26 01:25:04  bruceb
// CF changes
//
// Revision 1.22  2007-05-15 01:20:37  bruceb
// LogMessageReceived event and supporting code added
//
// Revision 1.21  2007/01/10 06:57:57  hans
// Added support for CustomLogLevelAppender
//
// Revision 1.20  2006/09/05 12:44:22  hans
// Improved exception logging.
//
// Revision 1.19  2006/08/15 10:12:24  hans
// Made Log(Level, string, Exception) more flexible.
//
// Revision 1.18  2006/08/14 11:10:28  hans
// Added Error(Exception) method.
//
// Revision 1.17  2006/07/13 07:44:16  hans
// Added logging.
//
// Revision 1.16  2006/07/07 10:21:02  hans
// Added LogObject
//
// Revision 1.15  2006/06/14 10:13:36  hans
// Fixed comments and added .NET 2.0 compatibility
//
// Revision 1.14  2006/05/03 06:38:30  bruceb
// log levels now can be enums or INFO etc
//
// Revision 1.13  2006/04/20 05:40:26  hans
// Fixed comment error.
//
// Revision 1.12  2006/03/16 22:19:24  hans
// Added simple properties to control logging.  These are used by FTPConnection, but also provide a really simple interface for the user.
//
// Revision 1.11  2006/02/16 20:19:41  hans
// Added RemoveAppender feature.
//
// Revision 1.10  2006/01/08 19:05:49  bruceb
// change msg about param not found to INFO
//
// Revision 1.9  2005/12/13 20:19:11  hans
// Added properties for controlling logging output format.
//
// Revision 1.8  2005/02/07 17:22:39  bruceb
// make sure Exception message included in log
//
// Revision 1.7  2004/12/22 22:58:17  bruceb
// fixed bad level problem
//
// Revision 1.6  2004/11/13 18:20:52  bruceb
// clear appenders/loggers in shutdown
//
// Revision 1.5  2004/11/06 11:15:24  bruceb
// namespace tidying up
//
// Revision 1.4  2004/10/29 09:42:30  bruceb
// removed /// from file headers
//
//
//

using System;
using System.Globalization;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Reflection;
using System.Text;
using System.ComponentModel;

namespace EnterpriseDT.Util.Debug{
    /// <summary>
    /// An instance of this class is supplied to the LogMessageReceived event
    /// </summary>
    public class LogMessageEventArgs : EventArgs
    {
        private string loggerName;
        private Level level;
        private string text;
        private Exception e;
        private object[] args;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="loggerName">name of logger</param>
        /// <param name="level">log level of message</param>
        /// <param name="text">message text</param>
        /// <param name="args">any additional args supplied</param>
        internal LogMessageEventArgs(
            string loggerName, Level level, string text, params object[] args)
        {
            this.loggerName = loggerName;
            this.level = level;
            this.text = text;
            this.args = args;
            if (args!=null && args.Length == 1 && args[0] is Exception)
                this.e = (Exception)args[0];
        }

        /// <summary>
        /// Returns the level of this message
        /// </summary>
        public Level LogLevel
        {
            get { return level; }
        }

        /// <summary>
        /// Returns the name of the logger for this message
        /// </summary>
        public string LoggerName
        {
            get { return loggerName; }
        }

        /// <summary>
        /// The message text.
        /// </summary>
        /// <remarks>Normally this is a log message, but if additional arguments
        /// are supplied, this will be a Format string so the extra arguments can
        /// be displayed correctly.</remarks>
        public string Text
        {
            get
            {
                return text;
            }
        }

        /// <summary>
        /// The formatted message text, constructed from the arguments and using
        /// the Text as a formatting string.
        /// </summary>
        public string FormattedText
        {
            get 
            {
                if (args != null)
                    return string.Format(text, args); 
                return text; 
            }
        }

        /// <summary>
        /// An exception if it exists (passed in as the first in the
        /// argument list).
        /// </summary>
        public Exception Exception
        {
            get { return e; }
        }

        /// <summary>
        /// The array of variable arguments.
        /// </summary>
        public object[] Arguments
        {
            get { return args; }
        }
    }

    /// <summary>
    /// Delegate used for LogMessageReceived event
    /// </summary>
    public delegate void LogMessageHandler(object sender, LogMessageEventArgs e);

  /// <summary>  
  /// Logger class that mimics log4net Logger class
  /// </summary>
  /// <author>       Bruce Blackshaw
  /// </author>
  /// <version>      $Revision: 1.30 $
  /// </version>
  public class Logger
  {
    /// <summary> 
    /// Set all loggers to this level
    /// </summary>
    public static Level CurrentLevel
    {
      set
      {
        globalLevel = value;
      }  
            get
            {
                return globalLevel;
            }
        }

        /// <summary>If true then class-names will be shown in log.</summary>
        public static bool ShowClassNames
        {
            get
            {
                return showClassNames;
            }
            set
            {
                showClassNames = value;
            }
        }

    /// <summary>If true then timestamps will be shown in log.</summary>
    public static bool ShowTimestamp
    {
      get
      {
        return showTimestamp;
      }
      set
      {
        showTimestamp = value;
      }
    }

    /// <summary> 
    /// Is debug logging enabled?
    /// </summary>
    /// <returns> true if enabled
    /// </returns>
    virtual public bool DebugEnabled
    {
      get
      {
        return IsEnabledFor(Level.DEBUG);
      }
      
    }
    /// <summary> Is info logging enabled for the supplied level?
    /// 
    /// </summary>
    /// <returns> true if enabled
    /// </returns>
    virtual public bool InfoEnabled
    {
      get
      {
        return IsEnabledFor(Level.INFO);
      }
      
    }

    /// <summary>
    /// The primary log file is simply the first file appender
    /// that has been added to the logger.
    /// </summary>
    public static string PrimaryLogFile
    {
      get
      {
        return mainFileAppender!=null ? mainFileAppender.FileName : null;
      }
      set
      {
                string mainFileAppenderName = (mainFileAppender != null ? mainFileAppender.FileName : null);

                if (mainFileAppenderName != value)
                {
                    if (mainFileAppender != null)
                        RemoveAppender(mainFileAppender);
                    if (value != null)
                        AddAppender(new FileAppender(value));
                }
      }
    }

    /// <summary>
    /// If this property is <c>true</c> then logs will be written to the
    /// console.
    /// </summary>
    public static bool LogToConsole
    {
      get
      {
        return mainConsoleAppender!=null;
      }
      set
      {
        if (value==true)
        {
          if (mainConsoleAppender==null)
            AddAppender(new StandardOutputAppender());
        }
        else
        {
          if (mainConsoleAppender!=null)
            RemoveAppender(mainConsoleAppender);
        }
      }
    }

    /// <summary>
    /// If this property is <c>true</c> then logs will be written using
    /// <see cref="System.Diagnostics.Trace"/>.
    /// </summary>
    public static bool LogToTrace
    {
      get
      {
        return mainTraceAppender!=null;
      }
      set
      {
        if (value==true)
        {
          if (mainTraceAppender==null)
            AddAppender(new TraceAppender());
        }
        else
        {
          if (mainTraceAppender!=null)
            RemoveAppender(mainTraceAppender);
        }
      }
    }

        /// <summary>
        /// If this event is set then all logging events are directed to the
        /// event as well as the loggers.
        /// </summary>
        /// <remarks>If it is desired to only send logging to the log system subscribing
        /// to this event, the <see cref="CurrentLevel"/> should be set to <see cref="Level.OFF"/>.</remarks>
        public static event LogMessageHandler LogMessageReceived;
    
    /// <summary> Level of all loggers</summary>
    private static Level globalLevel;
    
    /// <summary>Date format</summary>
    private static readonly string format = "d MMM yyyy HH:mm:ss.fff";
        
        private static readonly string LEVEL_PARAM = "edtftp.log.level";
    
    /// <summary> Hash of all loggers that exist</summary>
    private static Hashtable loggers = Hashtable.Synchronized(new Hashtable(10));
    
    /// <summary> Vector of all appenders</summary>
    private static ArrayList appenders = ArrayList.Synchronized(new ArrayList(2));
        
    /// <summary> Timestamp</summary>
    private DateTime ts;
    
    /// <summary> Class name for this logger</summary>
    private string clazz;

    /// <summary>If true then class-names will be shown in log.</summary>
    private static bool showClassNames = true;

    /// <summary>If true then timestamps will be shown in log.</summary>
    private static bool showTimestamp = true;

    /// <summary>Main file appender</summary>
    private static FileAppender mainFileAppender = null;

    /// <summary>Main file appender</summary>
    private static StandardOutputAppender mainConsoleAppender = null;

    /// <summary>Main file appender</summary>
    private static TraceAppender mainTraceAppender = null;

    /// <summary> 
    /// Constructor
    /// </summary>
    /// <param name="clazz">    
    /// class this logger is for
    /// </param>
    private Logger(string clazz)
    {
      this.clazz = clazz;
    }
    
    
    /// <summary> Get a logger for the supplied class
    /// 
    /// </summary>
    /// <param name="clazz">   full class name
    /// </param>
    /// <returns>  logger for class
    /// </returns>
    public static Logger GetLogger(System.Type clazz)
    {
      return GetLogger(clazz.FullName);
    }
    
    /// <summary> 
    /// Get a logger for the supplied class
    /// </summary>
    /// <param name="clazz">   full class name
    /// </param>
    /// <returns>  logger for class
    /// </returns>
    public static Logger GetLogger(string clazz)
    {
      Logger logger = (Logger) loggers[clazz];
      if (logger == null)
      {
        logger = new Logger(clazz);
        loggers[clazz] = logger;
      }
      return logger;
    }
    
    /// <summary> 
    /// Add an appender to our list
    /// </summary>
    /// <param name="newAppender">
    /// new appender to add
    /// </param>
    public static void AddAppender(Appender newAppender)
    {
      appenders.Add(newAppender);
      if (newAppender is FileAppender && mainFileAppender==null)
        mainFileAppender = (FileAppender)newAppender;
      if (newAppender is StandardOutputAppender && mainConsoleAppender==null)
        mainConsoleAppender = (StandardOutputAppender)newAppender;
      if (newAppender is TraceAppender && mainTraceAppender==null)
        mainTraceAppender = (TraceAppender)newAppender;
    }

    /// <summary> 
    /// Remove an appender from our list
    /// </summary>
    /// <param name="appender">appender to remove</param>
    public static void RemoveAppender(Appender appender)
    {
      appenders.Remove(appender);
      if (appender==mainFileAppender)
        mainFileAppender = null;
      if (appender==mainConsoleAppender)
        mainConsoleAppender = null;
            if (appender==mainTraceAppender)
        mainTraceAppender = null;
    }

    /// <summary> Close and remove all appenders and loggers</summary>
    public static void Shutdown()
    {
            ClearAppenders();
            loggers.Clear();
    }

        /// <summary> Close and remove all appenders</summary>
        public static void ClearAppenders()
        {
            lock (appenders.SyncRoot)
            {
                for (int i = 0; i < appenders.Count; i++)
                {
                    Appender a = (Appender)appenders[i];
                    try
                    {
                        a.Close();
                    }
                    catch (Exception) { }
                }
            }
            appenders.Clear();
        }
    
        /// <summary>
        /// Log a message using the given level.
        /// </summary>
        /// <param name="level">Log level.</param>
        /// <param name="message">Message to log.</param>
        /// <param name="args">Either an Exception or arguments substituted into message.</param>
        public virtual void Log(Level level, string message, params object[] args)
    {
            // direct logging 
            if (LogMessageReceived != null)
            {
                LogMessageReceived(this, new LogMessageEventArgs(clazz, level, message, args));
            }

            if (IsEnabledFor(level))
            {
                if (args!=null && args.Length == 1 && args[0] is Exception)
                    OurLog(level, message, (Exception)args[0]);
                else if (args!=null)
                    OurLog(level, string.Format(message, args), null);
                else
                    OurLog(level, message, null);
            }
    }
    
    /// <summary> 
    /// Log a message to our logging system
    /// </summary>
    /// <param name="level">log level</param>
    /// <param name="message">message to log</param>
    /// <param name="t">throwable object</param>
    private void OurLog(Level level, string message, Exception t)
    {
            ts = DateTime.Now;
      string stamp = ts.ToString(format, CultureInfo.CurrentCulture.DateTimeFormat);
      System.Text.StringBuilder buf = new System.Text.StringBuilder(level.ToString());
      if (showClassNames)
      {
        buf.Append(" [");
        buf.Append(clazz);
        buf.Append("]");
      }
      if (showTimestamp)
      {
        buf.Append(" ");
        buf.Append(stamp);
      }
      buf.Append(" : ");
            string prefix = buf.ToString();
      buf.Append(message);
      if (t != null)
                buf.Append(" : ").Append(t.GetType().FullName).Append(": ").Append(t.Message);
      if (appenders.Count == 0)
      {
        // by default to stdout
                System.Console.Out.WriteLine(buf.ToString());
                if (t != null)
        {
                    if (t.StackTrace!=null)
                        foreach (string line in t.StackTrace.Replace("\r", "").Split('\n'))
                            OurLog(level, prefix + line, null);
          if (t.InnerException!=null)
          {
            System.Console.Out.WriteLine(
              string.Format("{0}CAUSED BY - {1}: {2}", 
                            prefix,
              t.InnerException.GetType().FullName, 
              t.InnerException.Message));
                        if (t.InnerException.StackTrace != null)
                            foreach (string line in t.InnerException.StackTrace.Replace("\r", "").Split('\n'))
                                OurLog(level, prefix + line, null);
                    }
        }
      }
      else
      {
                bool appendToAll = globalLevel.IsGreaterOrEqual(level);
                lock (appenders.SyncRoot)
                {
                    for (int i = 0; i < appenders.Count; i++)
                    {
                        Appender a = (Appender)appenders[i];
                        bool appendToCustom = false;
                        if (a is CustomLogLevelAppender)
                        {
                            CustomLogLevelAppender appender = (CustomLogLevelAppender)a;
                            appendToCustom = appender.CurrentLevel.IsGreaterOrEqual(level);
                        }
                        if (appendToAll || appendToCustom)
                        {
                            a.Log(prefix + message);
                            if (t != null)
                            {
                                a.Log(prefix + t.GetType().FullName + ": " + t.Message);
                                if (t.StackTrace!=null)
                                    foreach (string line in t.StackTrace.Replace("\r", "").Split('\n'))
                                        a.Log(prefix + line);
                                if (t.InnerException != null)
                                {
                                    a.Log(prefix + "CAUSED BY - " + t.InnerException.GetType().FullName + ": " + t.Message);
                                    if (t.InnerException.StackTrace != null)
                                        foreach (string line in t.InnerException.StackTrace.Replace("\r", "").Split('\n'))
                                            a.Log(prefix + line);
                                }
                            }
                        }
                    }
                }
      }
    }
    
    /// <summary> Log an info level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    public virtual void Info(string message)
    {
      Log(Level.INFO, message, null);
    }
    
    /// <summary> Log an info level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    /// <param name="t">        throwable object
    /// </param>
    public virtual void Info(string message, Exception t)
    {
      Log(Level.INFO, message, t);
    }
        
    /// <summary> Log an info level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
        /// <param name="args">arguments references in the message.
        /// </param>
        public virtual void Info(string message, params object[] args)
    {
      if (IsEnabledFor(Level.INFO))
        Log(Level.INFO, string.Format(message, args), null);
    }

    /// <summary> Log a warning level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    public virtual void  Warn(string message)
    {
      Log(Level.WARN, message, null);
    }
    
    /// <summary> Log a warning level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    /// <param name="t">        throwable object
    /// </param>
    public virtual void  Warn(string message, Exception t)
    {
      Log(Level.WARN, message, t);
    }
    
    /// <summary> Log an error level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    public virtual void Error(string message)
    {
      Log(Level.ERROR, message, null);
    }
    
    /// <summary> Log an error level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    /// <param name="t">        throwable object
    /// </param>
    public virtual void Error(string message, Exception t)
    {
      Log(Level.ERROR, message, t);
    }

        /// <summary>Log an error level message</summary>
        /// <param name="message">message to log</param>
        /// <param name="t">throwable object</param>
        /// <param name="args">arguments references in the message.</param>
        public virtual void Error(string message, Exception t, params object[] args)
        {
            Log(Level.ERROR, string.Format(message, args), t);
        }

        /// <summary> Log an error level message
        /// 
        /// </summary>
        /// <param name="t">        throwable object
        /// </param>
        public virtual void Error(Exception t)
        {
            Log(Level.ERROR, t.Message, t);
        }
    
    /// <summary> Log a fatal level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    public virtual void Fatal(string message)
    {
      Log(Level.FATAL, message, null);
    }
    
    /// <summary> Log a fatal level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    /// <param name="t">        throwable object
    /// </param>
    public virtual void Fatal(string message, Exception t)
    {
      Log(Level.FATAL, message, t);
    }
    
    /// <summary> Log a debug level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    public virtual void Debug(string message)
    {
      Log(Level.DEBUG, message, null);
    }
    
    /// <summary>Log a debug level message</summary>
    /// <param name="message">message to log</param>
        /// <param name="args">arguments references in the message.</param>
    public virtual void Debug(string message, params object[] args)
    {
      if (IsEnabledFor(Level.DEBUG))
        Log(Level.DEBUG, string.Format(message, args), null);
    }
    
    
    /// <summary> Log a debug level message
    /// 
    /// </summary>
    /// <param name="message">  message to log
    /// </param>
    /// <param name="t">        throwable object
    /// </param>
    public virtual void Debug(string message, Exception t)
    {
      Log(Level.DEBUG, message, t);
    }
    
    /// <summary> Is logging enabled for the supplied level?
    /// 
    /// </summary>
    /// <param name="level">  level to test for
    /// </param>
    /// <returns> true   if enabled
    /// </returns>
    public virtual bool IsEnabledFor(Level level)
    {
      if (globalLevel.IsGreaterOrEqual(level))
        return true;
            lock (appenders.SyncRoot)
            {
                foreach (Appender a in appenders)
                    if (a is CustomLogLevelAppender)
                    {
                        CustomLogLevelAppender appender = (CustomLogLevelAppender)a;
                        if (appender.CurrentLevel.IsGreaterOrEqual(level))
                            return true;
                    }
            }
      return false;
    }
        
    /// <summary> Determine the logging level</summary>
    static Logger()
    {
      {
                globalLevel = null;
                string level = null;
                try
                {
#if NET20
               
                    level = ConfigurationManager.AppSettings[LEVEL_PARAM];
                
#else
            level = ConfigurationSettings.AppSettings[LEVEL_PARAM];
#endif
                }
                catch (Exception ex)
                {
                    System.Console.WriteLine("WARN: Failure reading configuration file: " + ex.Message);
                }
                if (level != null)
                {
                    // first try with the strings INFO etc
            globalLevel = Level.GetLevel(level);
                    if (globalLevel == null)
                    {
                        try
                        {
                            // now try from the enum
                            LogLevel logLevel = (LogLevel)Enum.Parse(typeof(LogLevel), level, true);
                            globalLevel = Level.GetLevel(logLevel);
                        }
                        catch (Exception)
                        {
                        }
                    }
                }
                
                // if no level set, switch off
                if (globalLevel == null)
                {
                    globalLevel = Level.OFF;
                    if (level != null) 
                    {
                        System.Console.Out.WriteLine("WARN: '" + LEVEL_PARAM + "' configuration property invalid. Unable to parse '" + level + "' - logging switched off");
                    }
                }
      }
    }

        /// <summary>
        /// Logs the public properties of an object.
        /// </summary>
        /// <param name="level">Logging level to use.</param>
        /// <param name="prefix">Text to prepend to the properties.</param>
        /// <param name="obj">Object whose properties are to be logged.</param>
        public void LogObject(Level level, string prefix, object obj)
        {
            if (IsEnabledFor(level))
            {
                if (obj == null)
                    Log(level, prefix + "(null)", null);
                Type objType = obj.GetType();
                bool useShortFormat = true;
                PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
                foreach (PropertyInfo p in properties)
                {
                    if (RequiresLongFormat(p, obj))
                    {
                        useShortFormat = false;
                        break;
                    }
                }
                StringBuilder s = new StringBuilder();
                foreach (PropertyInfo p in properties)
                {
                    object v = p.GetValue(obj, null);
                    if (s.Length>0)
                        s.Append(useShortFormat ? ", " : "\n  ");
                    s.Append(p.Name).Append("=");
                    DumpValue(v, s, "    ");
                }
                Log(level, prefix + s, null);
            }
        }

        private ArrayList GetAllProperties(Type t)
        {
            ArrayList fields = new ArrayList();
            while (t != typeof(object))
            {
                fields.AddRange(t.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public));
                t = t.BaseType;
            }
            return fields;
        }

        private bool RequiresLongFormat(PropertyInfo p, object obj)
        {
            object value = p.GetValue(obj, null);
            if (value == null
                || value is string
                || value.GetType().IsPrimitive)
                return false;
            if (value.GetType().IsArray && value.GetType().GetElementType().IsPrimitive)
                return ((Array)value).Length > 16;
            if (value is StringDictionary)
                return ((StringDictionary)value).Count > 1;
            if (value is ICollection)
                return ((ICollection)value).Count > 1;
            return typeof(IEnumerable).IsAssignableFrom(p.PropertyType);
        }

        private void DumpValue(object value, StringBuilder valueStr, string indent)
        {
            if (value == null)
                valueStr.Append("(null)");
            else if (value.GetType().IsArray && value.GetType().GetElementType().IsPrimitive)
            {
                int count = 0;
                Array arr = (Array)value;
                if (arr.Length > 16)
                    valueStr.Append("(")
                        .Append(arr.Length)
                        .Append(" items)")
                        .Append("\n")
                        .Append(indent)
                        .Append("  ");
                foreach (object o in arr)
                {
                    if (o is byte)
                        valueStr.Append(((byte)o).ToString("X2"));
                    else
                        valueStr.Append(o);
                    count++;
                    if (count % 16 != 0)
                        valueStr.Append(" ");
                    else
                        valueStr.Append("\n").Append(indent).Append("  ");
                }
            }
            else if (value is IDictionary)
            {
                IDictionary dict = (IDictionary)value;
                bool useLongFormat = dict.Count > 1;
                if (useLongFormat)
                    valueStr.Append("(").Append(dict.Count).Append(" items)");
                foreach (object key in dict.Keys)
                {
                    if (useLongFormat)
                        valueStr.Append("\n").Append(indent);
                    valueStr.Append(key).Append("=");
                    DumpValue(dict[key], valueStr, indent + "  ");
                }
            }
            else if (value is StringDictionary)
            {
                StringDictionary dict = (StringDictionary)value;
                bool useLongFormat = dict.Count > 1;
                if (useLongFormat)
                    valueStr.Append("(").Append(dict.Count).Append(" items)");
                foreach (string key in dict.Keys)
                {
                    if (useLongFormat)
                        valueStr.Append("\n").Append(indent);
                    valueStr.Append(key).Append("=");
                    DumpValue(dict[key], valueStr, indent + "  ");
                }
            }
            else if (!(value is string) && value is IEnumerable)
            {
                bool useLongFormat = true;
                if (value is ICollection)
                {
                    ICollection col = (ICollection)value;
                    useLongFormat = col.Count > 1;
                    if (useLongFormat)
                        valueStr.Append("(").Append(col.Count).Append(" items)");
                }
                foreach (object i in (IEnumerable)value)
                {
                    if (useLongFormat)
                        valueStr.Append("\n").Append(indent);
                    DumpValue(i, valueStr, indent + "  ");
                }
            }
            else
                valueStr.Append(value.ToString());
        }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.