Tuesday, May 17, 2005

Make your .NET demos better with a TraceListener

Last night I was writing a sample application for one of my DevTeach sessions and I thought I'd share this little trick. If you've ever tried to fiqure out a speaker's sample code after the conference when you got home you'd appreciate this as well. Usually I just write copious amounts of comments in my code to help people but last night it dawned on me how I could add a very simple TraceListener to my application to easily display the application's sequence of events in a list box. This way the developer could see exactly what was going on at runtime without having to debug the code.

If you're unfamiliar with TraceListeners have a read here.

Trace listeners monitor the output of the Debug and Trace messages in an application. You can create custom listeners and then add them to the Debug or Trace Listeners collection on application startup quite easily:
Imports System.Diagnostics

Public Class Main
 ''' --------------------------------------------------------------
 ''' <summary>
 ''' Main enrty point for the application.
 ''' </summary>
 ''' <remarks>
 ''' </remarks>
 ''' <history>
 '''  [Beth] 5/16/2005 Created
 ''' </history>
 ''' --------------------------------------------------------------
 Shared Sub Main()
  '-- Registers a trace listener 
  Debug.Listeners.Add(New DemoAppTraceListener)

  Application.Run(New MainForm)
 End Sub
End Class
The idea for the DemoAppTraceListener class is very simple. I just want to globally broadcast the trace messages so that they could be displayed by the application anywhere. We can do this by declaring a Shared (static) event:
Imports System.Diagnostics

''' -----------------------------------------------------------------------------
''' Project  : DataCachingStrategies
''' Class  : DemoAppTraceListener
''' 
''' -----------------------------------------------------------------------------
''' <summary>
''' Globally broadcasts the trace messages in this demo which are displayed in the UI.
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
'''  [Beth] 5/16/2005 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Class DemoAppTraceListener
 Inherits TraceListener

 Public Shared Event MessageReceived(ByVal e As MessageEventArgs)

 Public Overloads Overrides Sub Write(ByVal message As String)
  RaiseEvent MessageReceived(New MessageEventArgs(message))
 End Sub

 Public Overloads Overrides Sub WriteLine(ByVal message As String)
  RaiseEvent MessageReceived(New MessageEventArgs(message))
 End Sub

End Class

''' -----------------------------------------------------------------------------
''' Project  : DataCachingStrategies
''' Class  : MessageEventArgs
''' 
''' -----------------------------------------------------------------------------
''' <summary>
''' This EventArg is used to broadcast messages from the DemoAppTraceListener.
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
'''  [Beth] 5/16/2005 Created
''' </history>
''' -----------------------------------------------------------------------------
Public Class MessageEventArgs
 Inherits EventArgs

 Private m_msg As String = String.Empty
 Public ReadOnly Property Message() As String
  Get
   Return m_msg
  End Get
 End Property

 Public Sub New(ByVal msg As String)
  m_msg = msg
 End Sub
End Class
Now all you have to do is handle the event and display the messages. Oh, yea you also have to actually put Trace messages in your code now too!
Public Sub Foo
        Trace.Write("Entering Foo method")
.
.
.
End Sub
To display the messages in my demo I created an MDI parent and put a simple list box on the bottom. Then I just added a handler to the DemoAppTraceListener.MessageReceived event. I added the handler in the constructor because this code is hidden in the form designer region and people won't be distracted away from the demo code.
#Region " Windows Form Designer generated code "

Public Sub New()
 MyBase.New()

 'This call is required by the Windows Form Designer.
 InitializeComponent()

 'Add any initialization after the InitializeComponent() call
 AddHandler DemoAppTraceListener.MessageReceived, AddressOf Me.DisplayMessage
End Sub
.
.
.
Finally I added the few lines of code to display the message in the list box and select the last message:
Private Sub DisplayMessage(ByVal e As MessageEventArgs)
 Me.lstMsgs.Items.Add(Me.lstMsgs.Items.Count.ToString + ". " + e.Message)
 Me.lstMsgs.SelectedIndex = Me.lstMsgs.Items.Count - 1
End Sub
Another cool thing about using a TraceListener is that the developer can still copy/paste the code in the demo into their own applications without having to remove the Trace messages if they don't want to.

Now if you come to my data caching session at DevTeach you'll get to see the TraceListener in action! ;-)

Saturday, May 14, 2005

A component walks into a bar....

The component asks the bartender via .NET remoting:
"Gimme a beer"
Bartender:
"What kind of beer?"
Component:
"Just give me all of them one by one and I'll drink the one I like."

The component asks the bartender via Web Services:
"Gimme a beer"
Bartender:
"What kind of beer?"
The component thinks a minute.
"I didn't know you'd have more than one. I just want a beer."
Bartender:
"What kind of beer?"
Component:
"A plain one."
Bartender:
"What's plain beer? How about a bud?"
Component:
"Umm.. ok."
The component tries to take the beer but it slips onto the floor and the glass breaks.
Bartender:
"What's wrong with you?"
Component:
"I got a slippery SoapException."

Thursday, May 05, 2005

Refactor, refactor, REFACTOR!

So much for hiding the word "refactor" from VB.NET developers... (oh how I love the fact that it's spelled with a big fat exclamation point!!!!)

Have you taken a look at this new VB 2005 refactoring? I think this refactoring interface blows doors off the C# one. Everything is context sensitive right at your fingertips and all inline with the code editor -- no modal dialogs! And it's just a whole heck of a lot smarter about what you would want to do with the selected code. Any developer will be able to pick this up in two minutes. Thank you Microsoft for making such an awesome deal with Developer Express to provide us all with this free tool. (I think there's a C# one you can buy for $99.)