Control Exceptions: VB: Intercept Exceptions: Listing 1

The Data property of System.Exception lets you add key value pairs that contain additional information you think will be useful to your debugging and maintenance. The exception call stack will include the ExceptionFactory methods, but you can also make the stack report the location of a failure by assuming the exception is thrown outside the ExceptionFactory class and allowing helper functions to state explicitly how many stack frames to ignore. For example, CheckCast ignores itself by passing a value of 1.

Public NotInheritable Class ExceptionFactory
   Private Sub New()
   End Sub

   Public Shared Function CreateInvalidCastException( _
      ByVal guid As Guid, _
      ByVal id As ExceptionId, _
      ByVal skipFrames As Int32, _
      ByVal className As String, _
      ByVal variableName As String, _
      ByVal ParamArray dataItems() _
      As KeyValuePair(Of String, Object)) _
      As Exception
      Return CreateException( _
         Of System.InvalidCastException)( _
         guid, id, skipFrames, _
         New KeyValuePair(Of String, Object _
         )() {New KeyValuePair(Of String, Object)( _
         "ClassName", className)}, _
         New KeyValuePair(Of String, _
         Object)() {New KeyValuePair(Of String, _
         Object)("VariableName", variableName)}, _
   End Function

      ' Other exceptions as desired

   Private Shared Function CreateException _
       (Of T As {New, System.Exception}) _
       (ByVal guid As Guid, _
       ByVal id As ExceptionId, _
       ByVal skipFrames As Int32, _
       ByVal dataPairs As KeyValuePair( _
       Of String, Object)(), ByVal _ 
       ParamArray dataItems() As Object) _
       As Exception
      ' Exceptions happen to have a public constructor, 
      ' so we can use the new constraint.
      Dim ex As New T
      Dim methodBase = FindCallingMethod(skipFrames)
      ex.Data.Add("Class", methodBase.DeclaringType)
      ex.Data.Add("Method", methodBase.Name)
      ex.Data.Add("Correlation", guid)
      ex.Data.Add("MessageId", id)
      ex.Data.Add("MessageIdName", id.ToString)
      If dataPairs IsNot Nothing Then
         For Each dataPair In dataPairs
            ex.Data.Add(dataPair.Key, dataPair.Value)
      End If
      Return ex
   End Function

   Private Shared Function FindCallingMethod( _
      ByVal skipFrames As Int32) As Reflection.MethodBase
      Dim frames = New Diagnostics.StackTrace( _
      Dim framePosition = PositionFirstFrameNotInClass( _   
      Return frames(framePosition + _
   End Function

   Private Shared Function _
      PositionFirstFrameNotInClass( _
      ByVal frames As StackFrame()) As Int32
      Dim framePos As Int32 = 1 
      ' We know this frame is in the class 
      Do While True
         If frames(framePos).GetMethod.DeclaringType _
            IsNot GetType(ExceptionFactory) Then
            Return framePos
         End If
         framePos += 1
      Return -1
   End Function

End Class

Public Enum ExceptionId
End Enum
comments powered by Disqus
Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.