zoukankan      html  css  js  c++  java
  • [转] C#实现自动化Log日志

    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:CodesEnterprise LibraryEnterprise Library DemosPIABDemoAutoLoginDebugAutoLog.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:CodesEnterprise LibraryEnterprise Library DemosPIABDemoAutoLoginDebugAutoLog.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:CodesEnterprise LibraryEnterprise Library DemosPIABDemoAutoLoginDebugAutoLog.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:CodesEnterprise LibraryEnterprise Library DemosPIABDemoAutoLoginDebugAutoLog.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:CodesEnterprise LibraryEnterprise Library DemosPIABDemoAutoLoginDebugAutoLog.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);  
                }  
            }  
        }  
    
  • 相关阅读:
    敏捷开发读后感
    软工第一次作业总结报告
    个人项目作业week5——敏捷开发方法读后感
    结对项目——电梯调度
    个人项目作业
    个人阅读作业3
    个人阅读作业2
    软件工程基础作业-个人项目代码复审
    电梯调度项目总结
    《移山之道》读后感
  • 原文地址:https://www.cnblogs.com/arxive/p/5848246.html
Copyright © 2011-2022 走看看