以下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. Numpy 常用矩阵计算函数

    基本属性 在做一些数据分析的时候,我们通常会把数据存为矩阵的形式,然后python本身对于矩阵的操作是不够的,因此出现了numpy这样一个科学开发库来进行python在次上面的不足. Numpy's ...

  2. spring mvc 数据转换

    项目目录结构 User.java package org.mythsky.springmvcdemo.model; import org.springframework.format.annotati ...

  3. 公共技术点( Java 反射 Reflection)

    转载路径:http://p.codekk.com/blogs/detail/5596953ed6459ae7934997c5 本文为 Android 开源项目源码解析 公共技术点中的 Java 反射 ...

  4. Shell脚本 | 一键卸载安卓App

    在平时工作的过程中,很多重复性内容可以通过运行脚本文件来代替.一次编写,就能带来很大的效率提升. 今天跟大家分享一个简单的 Shell 脚本,只有区区 20 行左右的代码. 因为有时候我们测试某个应用 ...

  5. JavaServer Faces生命周期概述

    JavaServer Faces应用程序的生命周期在客户端为页面发出HTTP请求时开始,并在服务器响应该页面并转换为HTML时结束. 生命周期可以分为两个主要阶段:执行和渲染.执行阶段进一步分为子阶段 ...

  6. paxos协议

    两将军问题 有两支军队,它们分别有一位将军领导,现在准备攻击一座修筑了防御工事的城市. 这两支军队都驻扎在那座城市的附近,分占一座山头. 一道山谷把两座山分隔开来,并且两位将军唯一的通信方式就是派各自 ...

  7. mysql 查找在另一张表不存在的数据

    有两个表Phone_book, Call: Phone_book +----+------+--------------+ | id | name | phone_number | +----+--- ...

  8. JavaScript 视频教程 收藏

    001 JavaScript第1章 JavaScript概述 https://www.365yg.com/group/6410923214495940866/ 001 JavaScript第1章 Ja ...

  9. 记一次pm2的踩坑

    1.问题: 公司采用了自动发布平台,最近突然发现一个问题,上线完成后服务是能正常访问的,但是有一个节点访问的时候每两次中总是有一次404,通过nginx的access日志分析发现第一次正常访问有一次g ...

  10. 深入出不来nodejs源码-timer模块(C++篇)

    终于可以填上坑了. 简单回顾一下之前JS篇内容,每一次setTimeout的调用,会在一个对象中添加一个键值对,键为延迟时间,值为一个链表,将所有该时间对应的事件串起来,图如下: 而每一个延迟键值对的 ...