以下Demo代码基于 .NET Core 演示了Postsharp的基本使用方法,稍作修改(反射部分有些许差异)也适用于.NET Framework。

更多高级使用方法详见官方文档。http://samples.postsharp.net/

代码(注意,这段代码编译后会有警告,解决方案见文末):

 using System;
using System.Linq;
using PostSharp.Aspects;
using PostSharp.Serialization; namespace NetCoreConsole
{
class Program
{
static void Main(string[] args)
{
var result = Calc(, );
Console.WriteLine($"计算结果:{result}");
Console.WriteLine(">>>>>>>>>>>>>>方法拦截测试完毕\r\n"); PropertyTest = -;
Console.WriteLine(">>>>>>>>>>>>>>属性拦截测试(setter)完毕\r\n"); var x = PropertyTest;
Console.WriteLine(">>>>>>>>>>>>>>属性拦截测试(getter)完毕\r\n"); Console.ReadKey();
} /// <summary>
/// 方法拦截测试 + 异常处理
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
[HowToUse, ExceptionHandle]
private static int Calc(int x, int y)
{
int a = ;
int b = ;
int c = a / b; return x + y;
} private static int _propertyTest; /// <summary>
/// 属性拦截测试
/// 注:可以标记在整个属性上,也可以分别单独标记在 【getter】 或者 【setter】 上
/// </summary>
[HowToUse, ExceptionHandle]
private static int PropertyTest
{ get
{
return _propertyTest;
} // [HowToUse]
set
{
if (value <= )
{
throw new ArgumentException($"属性值必须大于0");
} _propertyTest = value;
}
}
}
} /// <summary>
/// 方法拦截测试
/// </summary>
[PSerializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public class HowToUseAttribute : MethodInterceptionAspect
{
/// <summary>
/// 方法执行拦截
/// </summary>
/// <param name="args"></param>
public override void OnInvoke(MethodInterceptionArgs args)
{
var methodBase = args.Method; // 如果是 .NET Framework 这里的System.Reflection.MethodInfo 应该替换为 System.Reflection.RuntimeMethodInfo
var returnType = ((System.Reflection.MethodInfo)methodBase).ReturnType.FullName; // 方法形式参数列表字符
var paramListString = methodBase.GetParameters().Aggregate(string.Empty,
(current, parameter) => current + $"{parameter.ParameterType.FullName} {parameter.Name}, ").Trim(',', ' '); // 方法签名
// var signatures = $"{returnType} {methodBase.Name}({paramListString})";
var signatures = methodBase.ToString(); Console.WriteLine($"被拦截的方法签名:{signatures}"); // 方法实际参数列表字符
var argsString = args.Arguments
.Aggregate(string.Empty, (current, p) => current + $"{p.GetType().FullName} ---> 值:{p}, ").Trim(',', ' '); Console.WriteLine($"被拦截的方法输入参数:{argsString}"); // 处理(执行被拦截的方法)
args.Proceed(); // 异步执行
// args.ProceedAsync(); var returnValue = args.ReturnValue; Console.WriteLine($"方法返回值:{returnValue}");
}
} /// <summary>
/// 异常处理
/// </summary>
[PSerializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public class ExceptionHandleAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
// 设置流程行为(继续执行,不抛出)
args.FlowBehavior = FlowBehavior.Continue; Console.WriteLine($"发生异常:{args.Exception.GetType().FullName} ----> {args.Exception.Message}");
}
}

这段代码可以正常编译,但会有警告。警告内容类似下图:

            (图1)

大意就是说在我们的 Calc方法上存在冲突的切面。

为什么会产生这样的警告呢,因为我们使用了两个类型的Aspect,一个是异常处理,一个是方法拦截(属性也可以认为是Getter和Setter两个方法的结合)。

异常处理切面(Aspect)期望包装我们的目标方法,方法拦截切面(Aspect)也是如此,但是这两个切面并不是强排序的,它们的执行顺序并不确定,这就是冲突。解决方法很简单,请对比图2与图3中代码的区别:

              (图2)

               (图3)

没错,解决方法就是使用 [  AspectPriority  ]属性手动指定切面的优先顺序。属性值是Int类型,可以随意设置,值越小优先级越高,只要让引擎能从数字层面区分优先顺序即可。

另外,切面的优先顺序不一样,引擎最终编译出来的代码也是不一样的,具体可以反编译查看。不管谁先执行谁后执行,总的来说结果没什么变化的。我个人更喜欢将异常处理切面优先级提高些,这样更加符合平时手写代码的风格。

Postsharp基本用法——方法、属性拦截与异常处理的更多相关文章

  1. python_way,day8 面向对象【多态、成员--字段 方法 属性、成员修饰符、特殊成员、异常处理、设计模式之单例模式、模块:isinstance、issubclass】

    python_way day8 一.面向对象三大特性: 多态 二.面向对象中的成员 字段.方法属性 三.成员修饰符 四.特殊成员 __init__.__doc__.__call__.__setitem ...

  2. AOP - C# Fody中的方法和属性拦截

    很久很久以前用过postsharp来做AOP, 大家知道的,现在那东东需要付费,于是尝试了一下Fody,但是发现Fody跟新太快了,所以大家在安装fody的时候尽力安装老的版本:packages.co ...

  3. python7 静态方法、类方法、属性方法 ;反射;异常处理

      #-*- coding:utf8 -*- # 静态方法@staticmethod # 静态方法(当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了.) clas ...

  4. 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理

    委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...

  5. Touch 方法&属性 映射工具

    Touch 方法&属性 映射工具(0.5 版本) 标签 : github 线上后门与接口调试: 原先需要测试一个接口(如Dubbo.DAO), 或为线上留后门, 需要写大量的Web层(Api. ...

  6. Delphi maskedit控件的掩码含义及用法方法

    Delphi maskedit控件的掩码含义及用法方法   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2 ...

  7. (转)C# Aop简单扫盲及ORM实体类属性拦截示例

    转自: http://www.cnblogs.com/cyq1162/archive/2012/05/30/2526573.html 先说下场景,C#中为什么要使用Aop,而我又是在哪里使用Aop? ...

  8. 【Spring开发】—— AOP之方法级拦截

    前言: 前面介绍了Spring的核心模块以及相关的依赖注入等概念.这篇讲解一下spring的另一个重点,AOP面向切面编程. 说道AOP不得不提到几个概念: 切面:也就是我们自己的一些业务方法. 通知 ...

  9. jquery.validate.min.js 用法方法示例

    页面html 代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

随机推荐

  1. Hadoop(三)搭建Hadoop全分布式集群

    原文地址:http://www.cnblogs.com/zhangyinhua/p/7652686.html 阅读目录(Content) 一.搭建Hadoop全分布式集群前提 1.1.网络 1.2.安 ...

  2. nginx服务器搭建以及配置

    2019年第一篇博客,在新的一年祝大家新年快乐,技术更上一层楼. 今天在公司搞了好长时间的nginx服务器搭建,以及遇到的问题,总结一下,方便查询 这里使用的是百度云的服务器,CentOS7系统的 N ...

  3. JDK8简化if-else

    简化if-else 1234567891011 User user = ...if (user != null) { String userName = user.getUserName(); if ...

  4. Lambda 遍历

    遍历列表元素 using System; using System.Collections.Generic; using System.Linq; using System.Text; using S ...

  5. Linux的僵尸进程及其解决方法

    1. 产生原因: 在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程.通过ps命令查看其带有defunct的标志.僵尸进程是一个 ...

  6. 【Vue】v-if与v-show的区别

    相同点:v-if与v-show都可以动态控制dom元素显示隐藏 不同点:v-if显示隐藏是将dom元素整个添加或删除,而v-show隐藏则是为该元素添加css--display:none,dom元素还 ...

  7. 【LeetCode题解】844_比较含退格的字符串(Backspace-String-Compare)

    目录 描述 解法一:字符串比较 思路 Java 实现 Python 实现 复杂度分析 解法二:双指针(推荐) 思路 Java 实现 Python 实现 复杂度分析 更多 LeetCode 题解笔记可以 ...

  8. 基于C++ Qt实现的红色警戒3修改器

    前言 这部修改器制作有一段时间了,但是一直没出教程.今天利用周末空闲写篇教程,给后来者指路的同时也加深自己对游戏修改器的理解,大佬就随便看看吧 浏览了一下网络,形形色色的单机游戏修改器教程,但是基本只 ...

  9. jQuery 各类判断函数汇总

    欢迎访问我的github:huanshen,有我的源码解析 常用的判断函数有type,isEmptyObject,isFunction,isWindow,isPlainObject,isArrayli ...

  10. MVC应用程序实现上传文件(续)

    前几天,有练习了<MVC应用程序实现上传文件>http://www.cnblogs.com/insus/p/3590907.html 那只是把文档上传至MVC应用程序下的某一目录之中. 其 ...