实例讲解PostSharp(一)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

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 {  get set ; }
        
public   string  Pwd {  get set ; }
    }
复制代码

 

运行主程序结果如下:

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

源码下载


本文转自 你听海是不是在笑 博客园博客,原文链接:  http://www.cnblogs.com/nuaalfm/archive/2009/02/23/1396415.html ,如需转载请自行联系原作者

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
5月前
|
Java 测试技术 Android开发
Android项目架构设计问题之使用反射调用类的私有方法如何解决
Android项目架构设计问题之使用反射调用类的私有方法如何解决
61 0
|
5月前
|
设计模式 存储 安全
18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)
18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)
132 0
|
6月前
|
Java 数据库 Spring
Java编程问题之在测试中使用CGLIB创建代理类如何解决
Java编程问题之在测试中使用CGLIB创建代理类如何解决
|
8月前
|
Java
【Java开发指南 | 第九篇】访问实例变量和方法、继承、接口
【Java开发指南 | 第九篇】访问实例变量和方法、继承、接口
64 4
|
编译器 调度
FreeRTOS任务的创建(动态方法和静态方法)
FreeRTOS任务的创建(动态方法和静态方法)
992 0
|
Java
java接口(实例运用)
java接口(实例运用)
50 0
|
SQL 缓存 安全
Java枚举单例模式比DCL和静态单例要好?———反编译分析单例枚举类
枚举单例模式比DCL和静态单例模式要好?为什么好呢?本文带你一探究竟!
121 0
Java枚举单例模式比DCL和静态单例要好?———反编译分析单例枚举类
|
Java Spring 容器
Spring框架:第三章:对象的生命周期及单例bean生命周期的11个步骤
Spring框架:第三章:对象的生命周期及单例bean生命周期的11个步骤
127 0
|
Java Spring 容器
SpringBoot (走读源码)静态方法中调用spring注入的对象,注入对象为null?
SpringBoot (走读源码)静态方法中调用spring注入的对象,注入对象为null?
461 0
SpringBoot (走读源码)静态方法中调用spring注入的对象,注入对象为null?
|
Java Spring

热门文章

最新文章