At some point one needs to view all the properties of an instance outside of a debugger such as for a unit test reporting the results or possibly a console application informing its status to the output. To achieve the results one overrides ToString() and by hand writes the information of the instance’s properties and their values to the output string. This can become cumbersome if the class instance is changing or when one realizes that the time ratio of creating such a reporting operation verses the size of what is being reported can lead to valuable time taken away from the developer.

This article demonstrates a C# extension which will take any class instance and report any non null properties as well as any string lists. The goal of the report is to provide information on the standard properties (string, int, datetime, etc) as well as string lists and ignores any  complex objects. Also provided is the ability to show the non-public properties.

For the resulting visual list, the code lines up the output report in key value pairs where the largest character count key name (the property name reported) will be spaced out along with all other names.

Here is an example result of a class instance with differing properties. Note that MemberOfAsList is a List<string> property which internally splits out the property MemberOf string (by its comma) into a list. This extension shows the list as a string.join of ", ".

DistinguishedName : CN=Write Frank,OU=Test,OU=Acme Industries,DC=amce-co,DC=acme,DC=net
CommonName        : Write Frank Lloyd
MemberOf          : CN=2042_Identity,CN=UserIdentities,CN=AlphaVision,DC=acme-co,DC=acme,DC=net
MemberOfAsList    : CN=2042_Identity, CN=UserIdentities, CN=AlphaVision, DC=acme-co, DC=acme, DC=net
otherTelephone    : 303-555-555
Name              : Wright Frank
WhenChanged       : 3/17/2014 9:04:06 PM
LogonCount        : 0

Extension Method

The following is an extension method whose goal is to reflect the type being passed in, determine the sizing of the data for output and then reports the properties each on a different line. String lists values are specified by a , (comma and space) separator between each value.

public static string ReportAllProperties<T>(this T instance) where T : class
{

    if (instance == null)
        return string.Empty;

    var strListType = typeof(List<string>);
    var strArrType  = typeof(string[]);

    var arrayTypes   = new[] { strListType, strArrType };
    var handledTypes = new[] { typeof(bool), typeof(Int32), typeof(String), typeof(DateTime), typeof(double), typeof(decimal), strListType, strArrType };

    var validProperties = instance.GetType()
                                  .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                  .Where(prop => handledTypes.Contains(prop.PropertyType))
                                  .Where(prop => prop.GetValue(instance, null) != null)
                                  .ToList();

    var format = string.Format("{{0,-{0}}} : {{1}}", validProperties.Max(prp => prp.Name.Length));

    return string.Join(
             Environment.NewLine,
             validProperties.Select(prop => string.Format(format, 
                                                          prop.Name,
                                                          (arrayTypes.Contains(prop.PropertyType) ? string.Join(", ", (IEnumerable<string>)prop.GetValue(instance, null))
                                                                                                  : prop.GetValue(instance, null)))));
}

Usage

public override string ToString()
{
    return ( this.ReportAllProperties() );
}

Test & Results

var test = new MyClass("Admin") { Name = "Omegaman", 
                                  ID = 1,  
                                  StartDate = DateTime.Now,
                                  AccessPoints = new List<string> { "Alpha", "Beta", "Gamma" },
                                  WeekDays = new string[]{ "Mon", "Tue" }
                                 };

 Console.WriteLine (test.ToString());

/*
Name         : Omegaman
ID           : 1
Role         : Admin
AccessPoints : Alpha, Beta, Gamma
WeekDays     : Mon, Tue
StartDate    : 3/18/2014 12:16:07 PM
*/

....

public class MyClass
{
    public string Name               { get; set; }
    public int ID                    { get; set; }
    private string Role              { get; set; }
    public List<string> AccessPoints { get; set; }
    public string[] WeekDays         { get; set; }    
    public DateTime StartDate        { get; set; }

    public MyClass(string role)
    {
        Role = role;
    }

    public override string ToString()
    {
       return ( this.ReportAllProperties() );
    }

}

Done!

Share

Tags: , , , ,