Zac
Zac

Reputation: 121

Generic Object Debugger

I'm trying to write a general function that i can pass an object to and it will print out all the properties and values in c#.

I've tried a lot of examples out there like this, and some others like

    public void PrintProperties(object obj)
    {
        PrintProperties(obj, 0);
    }
    public void PrintProperties(object obj, int indent)
    {
        if (obj == null) return;
        string indentString = new string(' ', indent);
        Type objType = obj.GetType();
        PropertyInfo[] properties = objType.GetProperties();
        foreach (PropertyInfo property in properties)
        {
            object propValue = property.GetValue(obj, null);
            if (property.PropertyType.Assembly == objType.Assembly)
            {
                Console.WriteLine("{0}{1}:", indentString, property.Name);
                PrintProperties(propValue, indent + 2);
            }
            else
            {
                Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
            }
        }
    }

and

    foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(obj))
        {
            string name = descriptor.Name;
            object value = descriptor.GetValue(obj);
            Console.WriteLine("{0}={1}", name, value);
        }

but some of the objects i want in my debug / log files contain string[] properties. all of these examples output these as

System.String[]

if i had an object like

class Thing
{
    public string Name { get; set; }

    public int Number { get; set; }

    public string[] Names { get; set; }
}

i would expect to see in the log like bellow with whatever values were set

Name: Test
Number: 3
Names[0]: Fred
Names[1]: John
Names[2]: Jimmy

Thank you for any help =]

This is the class i ended up using

class Descriptor
{
    public void PrintProperties(object obj)
    {
        PrintProperties(obj, 0);
    }
    public void PrintProperties(object obj, int indent)
    {
        if (obj == null) return;
        string indentString = new string(' ', indent);
        Type objType = obj.GetType();
        PropertyInfo[] properties = objType.GetProperties();
        foreach (PropertyInfo property in properties)
        {
            object propValue = property.GetValue(obj, null);

            if (propValue.GetType().IsArray)
            {
                object[] arrary = (object[]) propValue;
                foreach (string value in arrary)
                {
                    if (property.PropertyType.Assembly == objType.Assembly)
                    {
                        Console.WriteLine("{0}{1}:", indentString, property.Name);
                        PrintProperties(value, indent + 2);
                    }
                    else
                    {
                        Console.WriteLine("{0}{1}: {2}", indentString, property.Name, value);
                    }
                }
                continue;
            }

            if (property.PropertyType.Assembly == objType.Assembly)
            {
                Console.WriteLine("{0}{1}:", indentString, property.Name);
                PrintProperties(propValue, indent + 2);
            }
            else
            {
                Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
            }
        }
    }

}

Now I'm going to use Log4Net with this class and now throughout my mvc3 site i can call this with ViewModels being served and posted to get a comprehensive debug when switched on

Upvotes: 4

Views: 328

Answers (1)

siride
siride

Reputation: 209445

If you don't mind using Windows Forms, there's a control called a PropertyGrid that basically does what you want: http://msdn.microsoft.com/en-us/library/system.windows.forms.propertygrid(v=vs.90).aspx

Now, for your specific problem, the issue is that you aren't looking inside the array. What you should do is look at the type of each property. If it's an array type, then you need to cast the value to an object[] array and then iterate through each element, rather than simply printing the value's ToString() output. You will also need to create a recursive algorithm that looks inside each property and treats it like an object that has properties to be iterated over. If you need help with that, let me know.

Upvotes: 4

Related Questions