Join 34,000+ subscribers and receive articles from our blog about software quality, testing, QA and security.
 

Some Custom Overloaded Methods for Session


#1

Hi Tobias,

Here are a couple of overloaded methods that I created for a class that inherits from the Gurock.SmartInspect.Session class. They simply display the current Method name for the EnterMethod and LeaveMethod functions.

Reflection is used to get the fully-qualified name of the current method where the statement was invoked from. Note that this could only be used by the .NET version - I don’t think it will work for Delphi or Java based clients.

Sample Output:

C3Api.Connection.GetConnectionInfo

    ''' --------------------------------------------------------------------------------
    ''' <summary>
    ''' Returns the fully-qualified method name that invoked this method.
    ''' </summary>
    ''' 
    ''' <param name="StackLevel">
    ''' 	The .NET CLR Stack Frame level to query.
    ''' </param>
    ''' 
    ''' <returns>
    '''		The fully-qualified method name in the form of Assembly.Class.Method.
    ''' </returns>
    ''' 
    ''' <remarks>
    ''' Reflection is used to determine the fully-qualified method name that called 
    ''' this method.  If method info could not be queried, "<Unknown>" is returned.
    ''' 
    ''' <para>
    ''' No exception will be thrown by this method.
    ''' </para>
    ''' </remarks>
    ''' --------------------------------------------------------------------------------
    Public Shared Function GetMethodInfo(Optional ByVal StackLevel As Integer = 1) As String

        Dim oStackTrace As StackTrace
        Dim oStackFrame As StackFrame
        Dim oMethod As System.Reflection.MethodBase
        Dim sbMethodName As StringBuilder

        Try

            ' get .NET CLR call stack data.
            oStackTrace = New StackTrace
            oStackFrame = oStackTrace.GetFrame(StackLevel)
            oMethod = oStackFrame.GetMethod()

            ' formulate fully-qualified method name, including class - will look
            ' something like "Test.Module1.Main".
            sbMethodName = New StringBuilder(oMethod.ReflectedType.FullName)
            sbMethodName.Append(".")

            If oMethod.IsConstructor Then
                sbMethodName.Append("New")
            Else
                sbMethodName.Append(oMethod.Name)
            End If

            ' return to caller.
            Return sbMethodName.ToString

        Catch ex As Exception

            ' handle exceptions.
            Return "<Unknown>"

        Finally

            ' free resources.
            oStackTrace = Nothing
            oStackFrame = Nothing
            sbMethodName = Nothing

        End Try

    End Function


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Enters a method by using the default log level - reflection is used to retrieve
    ''' the current method's name.
    ''' </summary>
    ''' 
    ''' <remarks>
    ''' The fully-qualified method name is logged in the form of Assembly.Class.Method.
    ''' </remarks>
    ''' -----------------------------------------------------------------------------
    Public Overloads Sub EnterMethod()
        If Me.IsOn() Then
            Me.EnterMethod(Me.GetMethodInfo(2))
        End If
    End Sub


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Enters a method by using the specified log level - reflection is used to retrieve
    ''' the current method's name.
    ''' </summary>
    ''' 
    ''' <param name="level">
    ''' 	The log level of this method call.
    ''' </param>
    ''' 
    ''' <remarks>
    ''' The fully-qualified method name is logged in the form of Assembly.Class.Method.
    ''' </remarks>
    ''' -----------------------------------------------------------------------------
    Public Overloads Sub EnterMethod(ByVal level As Gurock.SmartInspect.Level)
        If Me.IsOn() Then
            Me.EnterMethod(level, Me.GetMethodInfo(2))
        End If
    End Sub


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Leaves a method by using the default log level - reflection is used to retrieve
    ''' the current method's name.
    ''' </summary>
    ''' 
    ''' <remarks>
    ''' The fully-qualified method name is logged in the form of Assembly.Class.Method.
    ''' </remarks>
    ''' -----------------------------------------------------------------------------
    Public Overloads Sub LeaveMethod()
        If Me.IsOn Then
            Me.LeaveMethod(Me.GetMethodInfo(2))
        End If
    End Sub


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Leaves a method by using the default log level - reflection is used to retrieve
    ''' the current method's name.
    ''' </summary>
    ''' 
    ''' <param name="level">
    ''' 	The log level of this method call.
    ''' </param>
    ''' 
    ''' <remarks>
    ''' The fully-qualified method name is logged in the form of Assembly.Class.Method.
    ''' </remarks>
    ''' -----------------------------------------------------------------------------
    Public Overloads Sub LeaveMethod(ByVal level As Gurock.SmartInspect.Level)
        If Me.IsOn Then
            Me.LeaveMethod(level, Me.GetMethodInfo(2))
        End If
    End Sub

#2

Hello Todd,

Thanks! I’m sure a lot of our forum users appreciate your posting and find these methods helpful. We thought about adding these methods to the libraries ourselves in the past but rejected it back then due to performance concerns (unfortunately, reflection is a lot slower when compared with manually specifying the method name). We will probably reinvestigate the performance impacts and consider adding it directly to the libraries as additional overloads. Regarding Java and Delphi, I think with Java reflection something similar should be possible as well. Delphi is more difficult, but should also be possible to some extent.

One code suggestion: you could pass the log level parameter to the IsOn method to exit your methods immediately if the passed log level is not sufficient.

Again, thanks again for your work and for publishing the results on this forum.