C#: ToString To Report all Properties Even Private Ones Via Reflection
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__abENT__#46;join
` of `__abENT__quot;, __abENT__quot;
`.
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!