December 18, 2014
Hot Topics:

Dumping an Object's State with Reflection and Extension Methods

  • October 17, 2008
  • By Paul Kimmel
  • Send Email »
  • More Articles »

Defining an Object State Dumper with Extension Methods

A common theme in programming, especially during debugging, is to examine the state of objects. A good first attempt is to override the ToString method and manually write each property. This works, of course, but the problem is that one must do this for every class. Ultimately, every programmer realizes that overriding ToString and writing long property-state statements is time consuming and must be changed each time the class changes.

After a little time and pain, most programmers stumble upon reflection and write a more general-purpose algorithm that will dump the state of any object. There are several variations on this theme. Accept an object, reflect its properties, and write them to the Console, the Debug window, or a StringBuilder. Listing 2 has the variation I created that I like the best. Listing 2 accepts and uses extension methods, extends object—so any type can call Dump—and accepts a TextWriter. Accepting a TextWriter means that the caller can pass in the dump-target. For example, Console.Out is a TextWriter; passing in Console.Out means that the output goes to the Console.

Listing 2: Extension methods that dump the state of a collection of objects.

Imports System.Runtime.CompilerServices
Imports System.Reflection
Imports System.IO

Public Module Dumper

   <Extension()> _
   Public Sub Dump(ByVal obj As Object, ByVal writer As TextWriter)
      Dim properties As PropertyInfo() = _
         obj.GetType().GetProperties()
      For Each p As PropertyInfo In properties
         Try
            writer.WriteLine(String.Format("{0}: {1}", p.Name, _
            p.GetValue(obj, Nothing)))
         Catch
            writer.WriteLine(String.Format("{0}: {1}", p.Name, _
            "unk."))
         End Try
      Next
   End Sub

   <Extension()> _
   Public Sub Dump(Of T)(ByVal list As IEnumerable(Of T), _
      ByVal writer As TextWriter)
      For Each o As T In list
         o.Dump(writer)
      Next
   End Sub
End Module

Adding the ExtensionAttribute to a method means that for all intents and purposes the extension method is called like a member method. For example, customer.Dump(Console.Out) would call the first Dump method even though Dump isn't actually a member of the Customer class. With extension methods, the first argument defines the type being extended, so defining Dump as accepting an object means Dump extends everything.

The overloaded Dump extends IEnumerable(Of T), which means CustomerList.Dump(Console.Out)—assuming CustomerList is defined as List(Of Customer)—would call the second Dump method. The second Dump method iterates over every object and calls Dump on the object.

Tip: Add a Log property defined as a TextWriter type to all of your classes; that makes it easy to add trace-ability to any TextWriter target at any point during development.

The first Dump method simply uses reflection to get all of the public properties and writes the property name and value to the TextWriter argument.

Testing the Object State Dumper

The code in Listing 3 creates a List of Customer objects. A stopwatch is used to see how long it takes to dump the list of Customers. Look at the code and then I'll talk about the purpose for the stopwatch.

Listing 3: Code to test the object dumper.

Imports System.Reflection
Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Reflection.Emit

Module Module1

   Sub Main()

      ' Create customer list
      Dim customers As List(Of Customer) = New List(Of Customer)
      For i As Integer = 0 To 50
         customers.Add(New Customer(i.ToString()))
      Next

      ' Dump customer list with stopwatch
      Dim watch As Stopwatch = Stopwatch.StartNew
      customers.Dump(Console.Out)
      Console.WriteLine(watch.Elapsed)
      Console.ReadLine()

   End Sub

End Module

Notice how Dump is used: customers.Dump(Console.Out). The first argument is supplied by the member-of semantics. The object—a collection of Customer objects—is actually the first argument to Dump(ByVal list As IEnumerable(Of T), ByVal writer as TextWriter), and Console.Out is the TextWriter argument.





Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel