Dynamic override of ToString() using Reflection
This works for me:
public class TestingClass
{
public string Prop1 { get; set; }//properties
public string Prop2 { get; set; }
public void Method1(string a) { }//method
public TestingClass() { }//const
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (System.Reflection.PropertyInfo property in this.GetType().GetProperties())
{
sb.Append(property.Name);
sb.Append(": ");
if (property.GetIndexParameters().Length > 0)
{
sb.Append("Indexed Property cannot be used");
}
else
{
sb.Append(property.GetValue(this, null));
}
sb.Append(System.Environment.NewLine);
}
return sb.ToString();
}
}
To make it available everywhere you can create an Extension.
It's not possible to override methods in an Extension, but still it should simplify your life.
public static class MyExtensions
{
public static string ToStringExtension(this object obj)
{
StringBuilder sb = new StringBuilder();
foreach (System.Reflection.PropertyInfo property in obj.GetType().GetProperties())
{
sb.Append(property.Name);
sb.Append(": ");
if (property.GetIndexParameters().Length > 0)
{
sb.Append("Indexed Property cannot be used");
}
else
{
sb.Append(property.GetValue(obj, null));
}
sb.Append(System.Environment.NewLine);
}
return sb.ToString();
}
}
You can then call ToStringExtension()
on every object.
Downside is, it doesn't work perfectly for lists etc., example:
var list = new List<string>();
// (filling list ommitted)
list.ToStringExtension();
// output:
// Capacity: 16
// Count: 11
// Item: Indexed Property cannot be used
Here is an extension which will report the standard types such as string, int and Datetime but will also report string lists (shown below in AccessPoints
which the above answer could not handle). Note that the output is aligned such as:
Name : Omegaman
ID : 1
Role : Admin
AccessPoints : Alpha, Beta, Gamma
WeekDays : Mon, Tue
StartDate : 3/18/2014 12:16:07 PM
Below is the extension which takes in any type as long as its a class. It then reflects off of the public and private properties and if they are not null reports them.
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(Int32), typeof(String), typeof(bool), 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
myInstance.ReportAllProperties()
Note that this is based off my blog article C#: ToString To Report all Properties Even Private Ones Via Reflection which provides a more robust explanation of what is going on.