• 实例讲解PostSharp(一)


    PostSharp是基于.NET平台设计的比较强调易学易用的AOP框架,AOP的概念,优点请参见:
    http://www.cnblogs.com/wayfarer/category/35983.html
    这里只是简要的介绍几种使用PostSharp实现的场景供大家参考。
    一、日志
    一般我们写入业务方面的日志有两种方式,
    1、简单的记录业务方法的发生时间,触发用户,业务方法名等
    传统方案我们是这样记录的。

    public class Employee
    {
            
            
    public void Add(string employeeName, string employeePwd)
            {
                
                Console.WriteLine(
    "添加员工名:{0},密码:{1}",employeeName,employeePwd);
                LogManager.LogWrite(
    "Add");
        }
    }
    class LogManager
        {
            
    public static void LogWrite(string methodName)
            {
                GenericPrincipal gp 
    = (GenericPrincipal)Thread.GetData(
                  Thread.GetNamedDataSlot(
    "Principal"));
                Console.WriteLine(
    "用户名:{0},日志时间:{1},触发此日志的方法:{2}",
                    gp.Identity.Name, DateTime.Now.ToString(), methodName);
            }
        }
    //主程序:
    static void Main(string[] args)
            {
                GenericIdentity gi 
    = new GenericIdentity("lfm");
                GenericPrincipal gp 
    = new GenericPrincipal(gi, new string[] { "Admin" });
        
                LocalDataStoreSlot localSlot 
    = Thread.AllocateNamedDataSlot("Principal");
                Thread.SetData(localSlot, gp);
                Employee em 
    = new Employee();
            em.Add(
    "lfm","lfm");
    }

    (因为这里使用的控制台应用程序,为了便于测试我们使用了线程槽来存储用户,如果不理解这个部分可以暂时忽略用户信息。)传统方案的日志记录的问题是每个需要记录日志的方法都要依赖于LogManager类,也就是说所有的业务逻辑都要依赖于系统级的LogManager类,我们能不能让他们彻底的分离开呢,下面我们使用PostSharp提供的方式来解决这个问题。
    要使用PostSharp必须先下载(http://www.postsharp.org/)PostSharp,安装之后需要至少引入PostSharp.Laos,PostSharp.Public两个程序集。PostSharp是利用特性(Attribute)将业务类和系统类联系在一起的,所以我们需要首先定义SampleLogAttribute类如下:

    使用postSharp记录日志
    [Serializable]
        
    class SampleLogAttribute : OnMethodBoundaryAspect
        {
            
    public override void OnSuccess(MethodExecutionEventArgs eventArgs)
            {
                LogManager.LogWrite(eventArgs); 
            }
        }
    日志记录类:
    class LogManager
        {
            
    public static void LogWrite(MethodExecutionEventArgs eventArgs)
            {
                GenericPrincipal gp 
    = (GenericPrincipal)Thread.GetData(
                  Thread.GetNamedDataSlot(
    "Principal"));
                Console.WriteLine(
    "用户名:{0},日志时间:{1},触发此日志的方法:{2}",
                    gp.Identity.Name, DateTime.Now.ToString(),
                    eventArgs.Instance.ToString() 
    + "." + eventArgs.Method.Name);
            }
    }

    然后在需要记录日志的方法上标识SampleLogAttribute即可

    相应方法
    [SampleLog]
    public void Add(string employeeID, string pwd)
    {
         Console.WriteLine(
    "用户名:{0}密码:{1}", employeeID, pwd);
    }

    这时我们运行程序会得到如下结果:

    这里我们需要去了解一下OnMethodBoundaryAspect类,我们可以通过重写OnEntry,OnSuccess两个方法来截获方法的信息,OnEntry是在标识了相应特性的方法前触发,而OnSuccess是在标识了相应特性的方法后触发。
    2、我们可能需要记录方法的一些更详细的信息,比如说更新操作,我们需要记录更新前的信息
    日志的记录特性代码如下:

    复杂日志记录
    [Serializable]
        
    class UpdateLogAttribute : OnMethodBoundaryAspect
        {
            
    public override void OnEntry(MethodExecutionEventArgs eventArgs)
            {
                LogManager.LogWrite(eventArgs);
                
    foreach (var item in eventArgs.Instance.GetType().GetProperties())
                {
                    Console.WriteLine(
    "原属性名:{0},原值:{1}",item.Name,
                        item.GetValue(eventArgs.Instance,
    null));
                }
                Console.WriteLine();
            }
        }
    //业务类:
    class Employee
        {
            
    public Employee(string employeeID, string pwd)
            {
                
    this.EmployeeID = employeeID;
                
    this.Pwd = pwd;
            }

            [UpdateLog]
            
    public void Update(Employee em)
            {
                
    this.EmployeeID = em.EmployeeID;
                
    this.Pwd = em.Pwd;
                Console.WriteLine(
    "更新后:employeeID:{0},pwd:{1}",this.EmployeeID,this.Pwd);
            }
            
    public string EmployeeID { getset; }
            
    public string Pwd { getset; }
        }

    运行主程序结果如下:

    也许还有些情况日志记录会更复杂,但一般情况下我们都可以通过截获方法的参数,实例的属性等获得想要的信息。可能你会觉得这样一个一个写特性也挺麻烦,PostSharp提供了一种广播横切点的方式,我们可以在类上使用相关的特性然后设置其AttributeTargetMembers值,如:
     [SampleLog(AttributeTargetMembers = "Add*")]
    class Employee
    {
    }
    这样Employee类中所有使用Add开头的方法都将记录日志,也可以设定整个程序集,大家可以参考PostSharp提供的文档。

    源码下载

  • 相关阅读:
    BZOJ4401 块的计数
    poj2914 Minimum Cut 全局最小割模板题
    无向图求最小割集
    HDU3232 Crossing Rivers 数学期望问题
    poj1386 字符串类型的一笔画问题 欧拉回路
    HDU3018 几笔画(非1笔)
    欧拉路&&欧拉回路 概念及其练习
    欧拉回路基础 HDU1878 欧拉回路||并差集
    我的明天在何处
    哈夫曼树讲解
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/1620620.html
Copyright © 2020-2023  润新知