对于大名顶顶的Log4Net大家一定都很熟悉。在项目应用中,往往会对 Log4Net 进行二次包装以满足项目的特殊需求。 比如自动记录调用 Log 方法的调用方法名,类名。
利用 System.Diagnostics.StackTrace 来了解哪个方法调用了该方法(以及哪个方法调用了其调用者,等等)。从其名称可以看出,StackTrace 对象跟踪等待当前过程完成的所有悬挂过程。可以采用许多方式创建 StackTrace 对象。在其最简单方式中,不向其构造函数传递参数, 并取得作为一组 StackFrame 对象的完整堆栈映像, 可以按其索引进行列举。
Dim st As New StackTrace() ' Enumerate all the stack frame objects. ' The frame at index 0 corresponds to the current routine. For i As Integer = 0 To st.FrameCount - 1 ' Get the ith stack frame and print the method name. Dim sf As StackFrame = st.GetFrame(i) Console.WriteLine(sf.GetMethod().Name) Next于是自定义一个Log4Net的包装类, 利用 StackTrace 来获得Log4Net包装类的调用类名和调用方法名:
Imports log4net Imports System.Runtime.CompilerServices Imports System.Diagnostics Public Class Logger Class Logger Private Sub New()Sub New() End Sub Private Shared log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType) Shared Sub New()Sub New() LoggerConfig.Config() End Sub <MethodImpl(MethodImplOptions.NoInlining)> _ Private Shared Function FormatMessage()Function FormatMessage(ByVal message As String) Dim st As StackTrace = New StackTrace() Dim sf As StackFrame = st.GetFrame(2) Return String.Format("{0}.{1}: {2}", sf.GetMethod().DeclaringType.Name, _ sf.GetMethod().Name, message) End Function Public Shared Sub LogDebug()Sub LogDebug(ByVal message As String) If log.IsDebugEnabled Then log.Debug(FormatMessage(message)) End If End Sub Public Shared Sub LogInfo()Sub LogInfo(ByVal message As String) If log.IsInfoEnabled Then log.Info(FormatMessage(message)) End If End Sub Public Shared Sub LogWarn()Sub LogWarn(ByVal message As String) If log.IsWarnEnabled Then log.Warn(FormatMessage(message)) End If End Sub Public Shared Sub LogError()Sub LogError(ByVal message As String) If log.IsErrorEnabled Then log.Error(FormatMessage(message)) End If End Sub Public Shared Sub LogFatal()Sub LogFatal(ByVal message As String) If log.IsFatalEnabled Then log.Fatal(FormatMessage(message)) End If End SubEnd Class例子:
Public Class Form1 Class Form1 Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Logger.LogInfo("Entering") CallTest() Logger.LogInfo("Exiting") End Sub Private Sub CallTest()Sub CallTest() Logger.LogInfo("Entering") Logger.LogInfo("Exiting") End SubEnd Class打印日志如下:
2007-02-25 20:38:27,000 [5692] INFO - Form1.Button1_Click: Entering2007-02-25 20:38:27,015 [5692] INFO - Form1.CallTest: Entering2007-02-25 20:38:27,015 [5692] INFO - Form1.CallTest: Exiting2007-02-25 20:38:27,015 [5692] INFO - Form1.Button1_Click: Exiting
红色字体部分就是通过StackFrame增加的信息。通过这种机制,可以使得Logger使用更简单,信息更丰富。是不是很棒?
