4

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

Community
  • 1
  • 1
Zac
  • 121
  • 2
  • 3
  • 10

1 Answers1

4

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.

siride
  • 200,666
  • 4
  • 41
  • 62
  • Hey thanks for your quick reply. If you could give me a quick example that would be real nice. Thanks. – Zac May 17 '12 at 02:34
  • casting the value to an object array and then iterate through each element, rather than simply printing the value's ToString() output. create a recursive algorithm that looks inside each property and treats it like an object that has properties to be iterated over. – Zac May 17 '12 at 02:41
  • @Zac so when you iterate through all the objects and you find an object has a System.String[] property, you detecdt it, http://stackoverflow.com/questions/1782835/how-to-get-net-array-type-from-the-string-string then you cast that property to an Object[] and iterate over all the items in the array. – Jeremy Thompson May 17 '12 at 03:02