C#实现自动化Log日志

ゝ一世哀愁。 2023-07-17 06:24 96阅读 0赞

在开发项目的时候,我们不免要使用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记录日志;
方法结束后,再次记录日志,并统计执行时间和异常处理

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Practices.Unity.InterceptionExtension;
  6. using Microsoft.Practices.EnterpriseLibrary.Logging;
  7. using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
  8. using System.Diagnostics;
  9. using System.Reflection;
  10. namespace AutoLog {
  11. public class AutoLogCallHandler:ICallHandler {
  12. private LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance();
  13. public AutoLogCallHandler() { }
  14. public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
  15. StringBuilder sb = null;
  16. ParameterInfo pi = null;
  17. string methodName = input.MethodBase.Name;
  18. logWriter.Write(string.Format(“Enter method “ + methodName));
  19. if (input.Arguments != null && input.Arguments.Count > 0) {
  20. sb = new StringBuilder();
  21. for (int i = 0; i < input.Arguments.Count; i++) {
  22. pi = input.Arguments.GetParameterInfo(i);
  23. sb.Append(pi.Name).Append(“ : “).Append(input.Arguments[i]).AppendLine();
  24. }
  25. logWriter.Write(sb.ToString());
  26. }
  27. Stopwatch sw = new Stopwatch();
  28. sw.Start();
  29. IMethodReturn result = getNext()(input, getNext);
  30. //如果发生异常则,result.Exception != null
  31. if (result.Exception != null) {
  32. logWriter.Write(“Exception:” + result.Exception.Message);
  33. //必须将异常处理掉,否则无法继续执行
  34. result.Exception = null;
  35. }
  36. sw.Stop();
  37. logWriter.Write(string.Format(“Exit method {0}, use {1}.”,methodName, sw.Elapsed));
  38. return result;
  39. }
  40. public int Order { get; set; }
  41. }
  42. }

    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 {

    1. public class AutoLogCallHandler:ICallHandler {
    2. private LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    3. public AutoLogCallHandler() { }
    4. public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
    5. StringBuilder sb = null;
    6. ParameterInfo pi = null;
    7. string methodName = input.MethodBase.Name;
    8. logWriter.Write(string.Format("Enter method " + methodName));
  1. if (input.Arguments != null && input.Arguments.Count > 0) {
  2. sb = new StringBuilder();
  3. for (int i = 0; i < input.Arguments.Count; i++) {
  4. pi = input.Arguments.GetParameterInfo(i);
  5. sb.Append(pi.Name).Append(" : ").Append(input.Arguments[i]).AppendLine();
  6. }
  7. logWriter.Write(sb.ToString());
  8. }
  9. Stopwatch sw = new Stopwatch();
  10. sw.Start();
  11. IMethodReturn result = getNext()(input, getNext);
  12. //如果发生异常则,result.Exception != null
  13. if (result.Exception != null) {
  14. logWriter.Write("Exception:" + result.Exception.Message);
  15. //必须将异常处理掉,否则无法继续执行
  16. result.Exception = null;
  17. }
  18. sw.Stop();
  19. logWriter.Write(string.Format("Exit method {0}, use {1}.",methodName, sw.Elapsed));
  20. return result;
  21. }
  22. public int Order { get; set; }
  23. }
  24. }

4.要自动化日志就需要创建一个标记属性,指定方法能自动进行日志
这里就创建AutoLogCallHandlerAttribute标记属性

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Practices.Unity.InterceptionExtension;
  6. using Microsoft.Practices.EnterpriseLibrary.Logging;
  7. using System.Diagnostics;
  8. using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
  9. namespace AutoLog {
  10. public class AutoLogCallHandlerAttribute:HandlerAttribute {
  11. public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) {
  12. return new AutoLogCallHandler() { Order = this.Order };
  13. }
  14. }
  15. }

    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 {

    1. public class AutoLogCallHandlerAttribute:HandlerAttribute {
    2. public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container) {
    3. return new AutoLogCallHandler() { Order = this.Order };
    4. }
    5. }

    }

5.创建实体类
注意:我在Work和ToString方法上方加上了AutoLogCallHandler属性,它是AutoLogCallHandlerAttribute的简写形式。用以指示这两个方法用AutoLogCallHandler的Invoke来处理。

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Practices.Unity;
  6. namespace AutoLog {
  7. public class Employee : MarshalByRefObject
  8. {
  9. public Employee() {}
  10. public string Name { get; set; }
  11. [AutoLogCallHandler()]
  12. public void Work() {
  13. Console.WriteLine(“Now is {0},{1} is working hard!”,DateTime.Now.ToShortTimeString(),Name);
  14. throw new Exception(“Customer Exception”);
  15. }
  16. [AutoLogCallHandler()]
  17. public override string ToString() {
  18. return string.Format(“I’m {0}.”,Name);
  19. }
  20. }
  21. }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Practices.Unity;

    namespace AutoLog {

    1. public class Employee : MarshalByRefObject
    2. {
    3. public Employee() {}
    4. public string Name { get; set; }
    5. [AutoLogCallHandler()]
    6. public void Work() {
    7. Console.WriteLine("Now is {0},{1} is working hard!",DateTime.Now.ToShortTimeString(),Name);
    8. throw new Exception("Customer Exception");
    9. }
    10. [AutoLogCallHandler()]
    11. public override string ToString() {
    12. return string.Format("I'm {0}.",Name);
    13. }
    14. }

    }

6.测试代码
注意:必须使用PolicyInjection.Create()来创建对象,不然无法实现。

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
  6. using Microsoft.Practices.Unity;
  7. using Microsoft.Practices.EnterpriseLibrary.Logging;
  8. using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
  9. namespace AutoLog {
  10. class Program {
  11. private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance();
  12. static void Main(string[] args) {
  13. Employee emp = PolicyInjection.Create();
  14. emp.Name = “Lele”;
  15. emp.Work();
  16. Console.WriteLine(emp);
  17. }
  18. }
  19. }

    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 {

    1. class Program {
    2. private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    3. static void Main(string[] args) {
  1. Employee emp = PolicyInjection.Create<Employee>();
  2. emp.Name = "Lele";
  3. emp.Work();
  4. Console.WriteLine(emp);
  5. }
  6. }
  7. }

7.还需要用EntLib的配置工具完成Log配置,将Log信息写入Trace.log文件中

[html] view plain copy print ?

  1. <?xml version=”1.0”?>
  2. <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”
  3. listenerDataType=”Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”
  4. fileName=”trace.log” formatter=”Text Formatter” />
  5. <add type=”Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”
  6. template=”Timestamp: {timestamp}{newline}
  7. Message: {message}{newline}
  8. Category: {category}{newline}
  9. Priority: {priority}{newline}
  10. EventId: {eventid}{newline}
  11. Severity: {severity}{newline}
  12. Title:{title}{newline}
  13. Machine: {localMachine}{newline}
  14. App Domain: {localAppDomain}{newline}
  15. ProcessId: {localProcessId}{newline}
  16. Process Name: {localProcessName}{newline}
  17. Thread Name: {threadName}{newline}
  18. Win32 ThreadId:{win32ThreadId}{newline}
  19. Extended Properties: {dictionary({key} - {value}{newline})}“
  20. name=”Text Formatter” />
  21. <?xml version=”1.0”?>
































好了,测试一下,控制台输入:
Now is 14:03,Lele is working hard!
I’m Lele.
再看看Trace.log文件内容:

[plain] view plain copy print ?

  1. -———————————————————-
  2. Timestamp: 2012/3/19 6:03:00
  3. Message: Enter method Work
  4. Category: General
  5. Priority: -1
  6. EventId: 1
  7. Severity: Information
  8. Title:
  9. Machine: PC4
  10. App Domain: AutoLog.exe
  11. ProcessId: 4200
  12. Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe
  13. Thread Name:
  14. Win32 ThreadId:4000
  15. Extended Properties:
  16. -———————————————————-
  17. -———————————————————-
  18. Timestamp: 2012/3/19 6:03:00
  19. Message: Exception:Customer Exception
  20. Category: General
  21. Priority: -1
  22. EventId: 1
  23. Severity: Information
  24. Title:
  25. Machine: PC4
  26. App Domain: AutoLog.exe
  27. ProcessId: 4200
  28. Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe
  29. Thread Name:
  30. Win32 ThreadId:4000
  31. Extended Properties:
  32. -———————————————————-
  33. -———————————————————-
  34. Timestamp: 2012/3/19 6:03:00
  35. Message: Exit method Work, use 00:00:00.0024272.
  36. Category: General
  37. Priority: -1
  38. EventId: 1
  39. Severity: Information
  40. Title:
  41. Machine: PC4
  42. App Domain: AutoLog.exe
  43. ProcessId: 4200
  44. Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe
  45. Thread Name:
  46. Win32 ThreadId:4000
  47. Extended Properties:
  48. -———————————————————-
  49. -———————————————————-
  50. Timestamp: 2012/3/19 6:03:00
  51. Message: Enter method ToString
  52. Category: General
  53. Priority: -1
  54. EventId: 1
  55. Severity: Information
  56. Title:
  57. Machine: PC4
  58. App Domain: AutoLog.exe
  59. ProcessId: 4200
  60. Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe
  61. Thread Name:
  62. Win32 ThreadId:4000
  63. Extended Properties:
  64. -———————————————————-
  65. -———————————————————-
  66. Timestamp: 2012/3/19 6:03:00
  67. Message: Exit method ToString, use 00:00:00.0001410.
  68. Category: General
  69. Priority: -1
  70. EventId: 1
  71. Severity: Information
  72. Title:
  73. Machine: PC4
  74. App Domain: AutoLog.exe
  75. ProcessId: 4200
  76. Process Name: D:\Codes\Enterprise Library\Enterprise Library Demos\PIAB\Demo\AutoLog\bin\Debug\AutoLog.exe
  77. Thread Name:
  78. Win32 ThreadId:4000
  79. Extended Properties:
  80. -———————————————————-


    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:

实现了自动化Log后,回过头来再看第5步,Employee继承了MarshalByRefObject,一般我们的业务类或数据访问类都有基类,那么我们就需要使用接口
这里我添加一个IEmployee接口,里面就Work方法(ToString是重写Object的)。

[csharp] view plain copy print ?

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Text;
  4. using Microsoft.Practices.Unity;
  5. namespace AutoLog {
  6. public interface IEmployee {
  7. void Work();
  8. }
  9. public class Employee : IEmployee
  10. {
  11. public Employee() {
  12. //this.Name = “Lele”;
  13. }
  14. public string Name { get; set; }
  15. [AutoLogCallHandler()]
  16. public void Work() {
  17. Console.WriteLine(“Now is {0},{1} is working hard!”,DateTime.Now.ToShortTimeString(),Name);
  18. throw new Exception(“Customer Exception”);
  19. }
  20. [AutoLogCallHandler()]
  21. public override string ToString() {
  22. return string.Format(“I’m {0}.”,Name);
  23. }
  24. }
  25. }

    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Practices.Unity;

    namespace AutoLog {

    1. public interface IEmployee {
    2. void Work();
    3. }
    4. public class Employee : IEmployee
    5. {
    6. public Employee() {
    7. //this.Name = "Lele";
    8. }
    9. public string Name { get; set; }
    10. [AutoLogCallHandler()]
    11. public void Work() {
    12. Console.WriteLine("Now is {0},{1} is working hard!",DateTime.Now.ToShortTimeString(),Name);
    13. throw new Exception("Customer Exception");
    14. }
    15. [AutoLogCallHandler()]
    16. public override string ToString() {
    17. return string.Format("I'm {0}.",Name);
    18. }
    19. }

    }

然后在测试类改动一下

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
  6. using Microsoft.Practices.Unity;
  7. using Microsoft.Practices.EnterpriseLibrary.Logging;
  8. using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
  9. namespace AutoLog {
  10. class Program {
  11. private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance();
  12. static void Main(string[] args) {
  13. IEmployee emp = PolicyInjection.Create();
  14. emp.Work();
  15. Console.WriteLine(emp);
  16. }
  17. }
  18. }

    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 {

    1. class Program {
    2. private static LogWriter logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    3. static void Main(string[] args) {
    4. IEmployee emp = PolicyInjection.Create<Employee, IEmployee>();
    5. emp.Work();
    6. Console.WriteLine(emp);
    7. }
    8. }

    }

此为大牛:http://blog.csdn.net/qing2005/article/details/7368738

发表评论

表情:
评论列表 (有 0 条评论,96人围观)

还没有评论,来说两句吧...

相关阅读

    相关 c# log4net 输出

    C\使用 log4net输出日志 到控制台和文件 1.安装Log4Net 程序包管理控制台搜索Log4Net安装 2.配置Log4Net 安装成功后,在项目根目录新建一

    相关 python log

    python 日志管理,可通过引入logging包,实现日志管理 一、配置文件 创建一个配置文件,如logging.conf [loggers] k