[轉] C#實現自動化Log日誌

來源:互聯網
上載者:User

標籤:

qing2005原文地址 C#實現自動化Log日誌

在開發項目的時候,我們不免要使用Log記錄日誌,使用最多的是Log4Net和EntLib Log,在需要記錄日誌的代碼處加入log.Write(日誌資訊),假設我需要跟蹤業務方法,記錄方法的傳遞參數,執行時間,返回資料等;或者我需要查 看方法的調用關係,希望進入方法的時候自動記錄參數資訊,出方法時記錄結果和執行時間資訊。這時就是一個典型的AOP運用,Java在AOP方面是很容易 實現的,因為java有類載入器。但是.Net在AOP方面就不怎麼容易,嚴格意義上.Net沒有真正的AOP。這話並不代表.Net不能實現AOP,比 如:PostSharp和Enterprise library就能實現。

先介紹一下PostSharp,我們知道.net代碼將編譯成MSIL(微軟中繼語言),然後CPU將MSIL的exe檔案產生本地CPU的二進位檔案格式,PostSharp就是在編譯過程中加入IL代碼,因而完成AOP功能。
缺點:編譯器需要PostSharp組件,維護代碼困難,因為IL代碼不好識別;
優點:使用方便(PostSharp2是收費版,破解也比較方便,在此不介紹破解)

這裡我重點介紹如何使用Enterprise Library實現自動化Log。


1.首先我們需要下載Enterprise Library,最新為5.0版本;


2.建立一個控制台項目,並添加以下程式集
Microsoft.Practices.EnterpriseLibrary.Common
Microsoft.Practices.EnterpriseLibrary.Logging
Microsoft.Practices.EnterpriseLibrary.PolicyInjection
Microsoft.Practices.ServiceLocation
Microsoft.Practices.Unity
Microsoft.Practices.Unity.Interception


3.添加AutoLogCallHandler類,實現ICallHandler介面
這個類是執行調用目標方法,在調用目標方法前擷取方法的參數資訊,並用EntLib Log記錄日誌;
方法結束後,再次記錄日誌,並統計執行時間和異常處理

    using System;      using System.Collections.Generic;      using System.Linq;      using System.Text;      using Microsoft.Practices.Unity.InterceptionExtension;      using Microsoft.Practices.EnterpriseLibrary.Logging;      using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;      using System.Diagnostics;      using System.Reflection;            namespace AutoLog {          public class AutoLogCallHandler:ICallHandler {                    private LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();                    public AutoLogCallHandler() { }                    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {                  StringBuilder sb = null;                  ParameterInfo pi = null;                        string methodName = input.MethodBase.Name;                  logWriter.Write(string.Format("Enter method " + methodName));                              if (input.Arguments != null && input.Arguments.Count > 0) {                      sb = new StringBuilder();                      for (int i = 0; i < input.Arguments.Count; i++) {                          pi = input.Arguments.GetParameterInfo(i);                          sb.Append(pi.Name).Append(" : ").Append(input.Arguments[i]).AppendLine();                      }                      logWriter.Write(sb.ToString());                  }                                                 Stopwatch sw = new Stopwatch();                  sw.Start();                        IMethodReturn result = getNext()(input, getNext);                  //如果發生異常則,result.Exception != null                  if (result.Exception != null) {                      logWriter.Write("Exception:" + result.Exception.Message);                      //必須將異常處理掉,否則無法繼續執行                      result.Exception = null;                  }                        sw.Stop();                  logWriter.Write(string.Format("Exit method {0}, use {1}.",methodName, sw.Elapsed));                        return result;              }                    public int Order { get; set; }          }      }  

 

4.要自動化日誌就需要建立一個標記屬性,指定方法能自動進行日誌
這裡就建立AutoLogCallHandlerAttribute標記屬性

    using System;      using System.Collections.Generic;      using System.Linq;      using System.Text;      using Microsoft.Practices.Unity.InterceptionExtension;      using Microsoft.Practices.EnterpriseLibrary.Logging;      using System.Diagnostics;      using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;            namespace AutoLog {                public class AutoLogCallHandlerAttribute:HandlerAttribute {                    public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) {                  return new AutoLogCallHandler() { Order = this.Order };              }          }      }  

 5.建立實體類
注意:我在Work和ToString方法上方加上了AutoLogCallHandler屬性,它是AutoLogCallHandlerAttribute的簡寫形式。用以指示這兩個方法用AutoLogCallHandler的Invoke來處理。

    using System;      using System.Collections.Generic;      using System.Linq;      using System.Text;      using Microsoft.Practices.Unity;            namespace AutoLog {                public class Employee : MarshalByRefObject           {                            public Employee() {}                    public string Name { get; set; }                    [AutoLogCallHandler()]              public void Work() {                  Console.WriteLine("Now is {0},{1} is working hard!",DateTime.Now.ToShortTimeString(),Name);                  throw new Exception("Customer Exception");              }                    [AutoLogCallHandler()]              public override string ToString() {                  return string.Format("I‘m {0}.",Name);              }          }      }  

 6.測試代碼
注意:必須使用PolicyInjection.Create<Employee>()來建立對象,不然無法實現。

    using System;      using System.Collections.Generic;      using System.Linq;      using System.Text;      using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;      using Microsoft.Practices.Unity;      using Microsoft.Practices.EnterpriseLibrary.Logging;      using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;            namespace AutoLog {          class Program {                    private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();                    static void Main(string[] args) {                              Employee emp = PolicyInjection.Create<Employee>();                        emp.Name = "Lele";                        emp.Work();                  Console.WriteLine(emp);              }          }      }  

 7.還需要用EntLib的組態工具完成Log配置,將Log資訊寫入Trace.log檔案中

    <?xml version="1.0"?>      <configuration>          <configSections>              <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />          </configSections>          <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">              <listeners>                  <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"                      listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"                      fileName="trace.log" formatter="Text Formatter" />              </listeners>              <formatters>                  <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"                      template="Timestamp: {timestamp}{newline}      Message: {message}{newline}      Category: {category}{newline}      Priority: {priority}{newline}      EventId: {eventid}{newline}      Severity: {severity}{newline}      Title:{title}{newline}      Machine: {localMachine}{newline}      App Domain: {localAppDomain}{newline}      ProcessId: {localProcessId}{newline}      Process Name: {localProcessName}{newline}      Thread Name: {threadName}{newline}      Win32 ThreadId:{win32ThreadId}{newline}      Extended Properties: {dictionary({key} - {value}{newline})}"                      name="Text Formatter" />              </formatters>              <categorySources>                  <add switchValue="All" name="General">                      <listeners>                          <add name="Flat File Trace Listener" />                      </listeners>                  </add>              </categorySources>              <specialSources>                  <allEvents switchValue="All" name="All Events" />                  <notProcessed switchValue="All" name="Unprocessed Category" />                  <errors switchValue="All" name="Logging Errors & Warnings">                      <listeners>                          <add name="Flat File Trace Listener" />                      </listeners>                  </errors>              </specialSources>          </loggingConfiguration>          <startup>              <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>          </startup>      </configuration>  

 

好了,測試一下,控制台輸入:
Now is 14:03,Lele is working hard!
I‘m Lele.
再看看Trace.log檔案內容:

    ----------------------------------------      Timestamp: 2012/3/19 6:03:00            Message: Enter method Work            Category: General            Priority: -1            EventId: 1            Severity: Information            Title:            Machine: PC4            App Domain: AutoLog.exe            ProcessId: 4200            Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe            Thread Name:             Win32 ThreadId:4000            Extended Properties:       ----------------------------------------      ----------------------------------------      Timestamp: 2012/3/19 6:03:00            Message: Exception:Customer Exception            Category: General            Priority: -1            EventId: 1            Severity: Information            Title:            Machine: PC4            App Domain: AutoLog.exe            ProcessId: 4200            Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe            Thread Name:             Win32 ThreadId:4000            Extended Properties:       ----------------------------------------      ----------------------------------------      Timestamp: 2012/3/19 6:03:00            Message: Exit method Work, use 00:00:00.0024272.            Category: General            Priority: -1            EventId: 1            Severity: Information            Title:            Machine: PC4            App Domain: AutoLog.exe            ProcessId: 4200            Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe            Thread Name:             Win32 ThreadId:4000            Extended Properties:       ----------------------------------------      ----------------------------------------      Timestamp: 2012/3/19 6:03:00            Message: Enter method ToString            Category: General            Priority: -1            EventId: 1            Severity: Information            Title:            Machine: PC4            App Domain: AutoLog.exe            ProcessId: 4200            Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe            Thread Name:             Win32 ThreadId:4000            Extended Properties:       ----------------------------------------      ----------------------------------------      Timestamp: 2012/3/19 6:03:00            Message: Exit method ToString, use 00:00:00.0001410.            Category: General            Priority: -1            EventId: 1            Severity: Information            Title:            Machine: PC4            App Domain: AutoLog.exe            ProcessId: 4200            Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe            Thread Name:             Win32 ThreadId:4000            Extended Properties:       ----------------------------------------  
View Code

實現了自動化Log後,回過頭來再看第5步,Employee繼承了MarshalByRefObject,一般我們的業務類或資料訪問類都有基類,那麼我們就需要使用介面
這裡我添加一個IEmployee介面,裡面就Work方法(ToString是重寫Object的)。

    using System.Collections.Generic;      using System.Linq;      using System.Text;      using Microsoft.Practices.Unity;            namespace AutoLog {                public interface IEmployee {              void Work();          }                public class Employee : IEmployee           {                            public Employee() {                  //this.Name = "Lele";              }                    public string Name { get; set; }                    [AutoLogCallHandler()]              public void Work() {                  Console.WriteLine("Now is {0},{1} is working hard!",DateTime.Now.ToShortTimeString(),Name);                  throw new Exception("Customer Exception");              }                    [AutoLogCallHandler()]              public override string ToString() {                  return string.Format("I‘m {0}.",Name);              }          }      }  

 然後在測試類別改動一下

    using System;      using System.Collections.Generic;      using System.Linq;      using System.Text;      using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;      using Microsoft.Practices.Unity;      using Microsoft.Practices.EnterpriseLibrary.Logging;      using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;            namespace AutoLog {          class Program {                    private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();                    static void Main(string[] args) {                        IEmployee emp = PolicyInjection.Create<Employee, IEmployee>();                        emp.Work();                  Console.WriteLine(emp);              }          }      }  

 

[轉] C#實現自動化Log日誌

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.