Monday, December 29, 2014

Object Dumper


Overview :

Object Dumper is used on your object to dump the result to the console. Sometimes we can't show the desired result on the console or for logging. I have used the Employee class to represent the working behavior of the Object Dumper class. Have a look at the class structure and the implementation as shown below:


LINQ-with-Object-Dumper.jpg


When I run the preceding code segment it shows me the error displayed below:


run-LINQ-with-Object-Dumper.jpg


Note: The reason for showing the error above is the ObjEmp object has multiple values in a collection.Even in Immediate window we can't see all the values in ObjEmp





Or while hovering on the object we have to keep on expanding the nodes to see the values it will be hectic for bigger List object.





To resolve this issue we have the Object Dumper class: 


Object-Dumper-class.jpg 

 
The Object Dumper class gives you the desired result as shown here:



output-Object-Dumper-class.jpg 


To use this we have to include a "ObjectDumper.cs" file to our solution and call the " ObjectDumper.Write(z1);" method from our code and it will write the output to console. It's a good debugging approach that can be used in Linq that we use everyday to see the records that we fetch from DB.


Sample Program : Console Application 

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Collections;
namespace Program
{
    public class Employee
    {
        public string EmpID { get; set; }
        public string Name { get; set; }
        public int YearOfJoining { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("With List Collections");
            List ObjEmp = new List
            {
                new Employee{ EmpID = "E001", Name = "Sachin", YearOfJoining = 2006},
                new Employee { EmpID = "E002", Name = "Rohit", YearOfJoining = 2005 },
                new Employee { EmpID = "E003", Name = "Deepak", YearOfJoining = 2007 }

            };
            //Console.WriteLine("Employee ID = {0}, Name = {1}, YearOfJoining = {2}", ObjEmp.EmpID, ObjEmp.Name, ObjEmp.YearOfJoining);
            //Console.ReadLine();

            ObjectDumper.Write(ObjEmp, 2);
            Console.ReadLine();
            Console.WriteLine("With Xml to Array List");

            string xml = "12";
            ArrayList arrayList = new ArrayList();
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            XmlNodeList idNodes = doc.SelectNodes("Ids/id");
            foreach (XmlNode node in idNodes)
                arrayList.Add(node.InnerText);

            ObjectDumper.Write(arrayList, 2);
            Console.ReadLine();
            Console.WriteLine("With XML to List");

            string xmltoList = "12";
            XDocument docList = XDocument.Parse(xmltoList);

            List list = docList.Root.Elements("id")
                               .Select(element => element.Value)
                               .ToList();
            Console.WriteLine("simplest use");

            var z = new
            {
                A = "1",
                B = "2"
            };

            ObjectDumper.Write(z);
            Console.ReadLine();
            Console.WriteLine(" nested collections");

            var z1 = new
            {
                Aaa = "Hello",
                Bbb = "There",
                Ccc = new[] { 1, 2, 3 }
            };

            ObjectDumper.Write(z1);
            Console.ReadLine();
            Console.WriteLine("within nested collections");

            var z2 = new
            {
                Aaa = "Hello",
                Bbb = "There",
                Ccc = new[] { 1, 2, 3 }
            };
            ObjectDumper.Write(z2, 1);
            Console.ReadLine();
        }
    }
}

ObjectDumper.cs - Code

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

// See the ReadMe.html for additional information
public class ObjectDumper {

    public static void Write(object element)
    {
        Write(element, 0);
    }

    public static void Write(object element, int depth)
    {
        Write(element, depth, Console.Out);
    }

    public static void Write(object element, int depth, TextWriter log)
    {
        ObjectDumper dumper = new ObjectDumper(depth);
        dumper.writer = log;
        dumper.WriteObject(null, element);
    }

    TextWriter writer;
    int pos;
    int level;
    int depth;

    private ObjectDumper(int depth)
    {
        this.depth = depth;
    }

    private void Write(string s)
    {
        if (s != null) {
            writer.Write(s);
            pos += s.Length;
        }
    }

    private void WriteIndent()
    {
        for (int i = 0; i < level; i++) writer.Write("  ");
    }

    private void WriteLine()
    {
        writer.WriteLine();
        pos = 0;
    }

    private void WriteTab()
    {
        Write("  ");
        while (pos % 8 != 0) Write(" ");
    }

    private void WriteObject(string prefix, object element)
    {
        if (element == null || element is ValueType || element is string) {
            WriteIndent();
            Write(prefix);
            WriteValue(element);
            WriteLine();
        }
        else {
            IEnumerable enumerableElement = element as IEnumerable;
            if (enumerableElement != null) {
                foreach (object item in enumerableElement) {
                    if (item is IEnumerable && !(item is string)) {
                        WriteIndent();
                        Write(prefix);
                        Write("...");
                        WriteLine();
                        if (level < depth) {
                            level++;
                            WriteObject(prefix, item);
                            level--;
                        }
                    }
                    else {
                        WriteObject(prefix, item);
                    }
                }
            }
            else {
                MemberInfo[] members = element.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
                WriteIndent();
                Write(prefix);
                bool propWritten = false;
                foreach (MemberInfo m in members) {
                    FieldInfo f = m as FieldInfo;
                    PropertyInfo p = m as PropertyInfo;
                    if (f != null || p != null) {
                        if (propWritten) {
                            WriteTab();
                        }
                        else {
                            propWritten = true;
                        }
                        Write(m.Name);
                        Write("=");
                        Type t = f != null ? f.FieldType : p.PropertyType;
                        if (t.IsValueType || t == typeof(string)) {
                            WriteValue(f != null ? f.GetValue(element) : p.GetValue(element, null));
                        }
                        else {
                            if (typeof(IEnumerable).IsAssignableFrom(t)) {
                                Write("...");
                            }
                            else {
                                Write("{ }");
                            }
                        }
                    }
                }
                if (propWritten) WriteLine();
                if (level < depth) {
                    foreach (MemberInfo m in members) {
                        FieldInfo f = m as FieldInfo;
                        PropertyInfo p = m as PropertyInfo;
                        if (f != null || p != null) {
                            Type t = f != null ? f.FieldType : p.PropertyType;
                            if (!(t.IsValueType || t == typeof(string))) {
                                object value = f != null ? f.GetValue(element) : p.GetValue(element, null);
                                if (value != null) {
                                    level++;
                                    WriteObject(m.Name + ": ", value);
                                    level--;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private void WriteValue(object o)
    {
        if (o == null) {
            Write("null");
        }
        else if (o is DateTime) {
            Write(((DateTime)o).ToShortDateString());
        }
        else if (o is ValueType || o is string) {
            Write(o.ToString());
        }
        else if (o is IEnumerable) {
            Write("...");
        }
        else {
            Write("{ }");
        }
    }
}
 

Finally the Object Dumper is an .NET object and dumps the object into a TextWriter, string or file and dumps the elements of sequences (arrays, lists, dictionaries, etc.). It is mainly used for debugging purpose for complex type objects.


Amala N is a Junior Software Engineer at Span Technology Services

No comments:

Post a Comment