Overriding ToString() on your objects using reflection

Just a very quick one, more as a reminder to myself on something I’d setup, though as per, would love any feedback.

On a current project we’re using exception driven development, and upon an exception, we’re throwing our own custom business exceptions, and building up the Exception.Data collection with the properties in the objects as they were at the point of exception.

We have a lot of DTO objects down at the dal layer, some with a lot of properties, and we didn’t want to keep having to do:

UserNotFoundException ex = new UserNotFoundException();
ex.Data.Add(“Username”, userDto.Username);
ex.Data.Add(“UserId”, userDto.UserId);
ex.Data.Add(“AccountStatus”, userDto.AccountStatus);
...

With that in mind, I started working on what reflection could bring to the table and perhaps giving our Dto objects a base type to derive from.

Here’s the initial stab at what I’ve arrived at:

public class BaseDto
{ public override string ToString()
{
PropertyInfo[] propertyInfos = this.GetType().GetProperties();

Array.Sort(propertyInfos, (propertyInfo1, propertyInfo2) => propertyInfo1.Name.CompareTo(propertyInfo2.Name));

StringBuilder output = new StringBuilder();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
output.AppendFormat("{0}: {1}\n", propertyInfo.Name, propertyInfo.GetValue(this, null));
}

return output.ToString();
}
}

Jobs a good ‘un.  I can now just use:

UserNotFoundException ex = new UserNotFoundException();
ex.Data.Add(“userDto”, userDto.ToString());

and all properties will be enumerated and documented in that one property of the .Data dictionary.

<meerkat>simples!</meerkat>

I hasten to add, this seems to work a treat in testing – I’ve got more rigorous investigation to do to make sure it presents a way forward for us, but thought I’d post it anyway in case anyone found it useful.

  • Hi Tez,

    I like it, used to do something similar when logging exceptions on an old system, it didn’t use reflection but the Model classes all had a DataTable property that meant I could go through columns in the DataTable and spit out the state of the object in exactly the same way. I know from your previous post you were bothered about performance, does reflection have much of a hit on what your doing?

    Thanks

    Tim

  • admin

    hey mate,

    I only ran it through single passes of generation as opposed to the 10k/100k repetations I’d done previously, and it seemed to make bugger all difference (>0.1ms).

    My hope is with these, they’re only really called when something has gone wrong (system exceptions as opposed to business exceptions) so they should hopefully only be hit ~100-200 times per day (on a 70k visitor count).

    We’re in the process of setting up a dev environment that we can simulate hits on, so I’ll hopefully blog about the outcomes of that with the new infrastructure soon!

    Cheers 🙂

  • Hi Terry,

    I’m not sure I see why you are creating a base class when the exception appears to be specifically for the user business object (unless I have read this wrong).

    Is there any reason why you couldn’t just keep things simpler by passing the user object to the exception object and have the exception parse the user object and populate the Data of the exception?

    This would reduce complexity and remove the need for reflection.

    Ryan

  • admin

    hey Ryan,

    Thanks for the reply! I’ve base classed it and used reflection so that it can cover more than one object. It works on User, but I also have Transactions (purchases), + a lot of other Dto objects.

    So long as all of my Dto objects inherit from this BaseDto, I have a ToString method that will enumerate through all of the properties.

    You’re absolutely right – if I’d just been dealing with one object (User) then coming up with something specific would have been more elegant, faster, and avoided the use of reflection, though I needed something generic that could handle pretty much any of my Dto objects (I have about 30) and output it in a useful format, hence the reflection and the base classing.

    Hope that helps.

    Cheers,
    Terry