Postsharp基本用法——方法、属性拦截与异常处理
以下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基本用法——方法、属性拦截与异常处理的更多相关文章
- python_way,day8 面向对象【多态、成员--字段 方法 属性、成员修饰符、特殊成员、异常处理、设计模式之单例模式、模块:isinstance、issubclass】
python_way day8 一.面向对象三大特性: 多态 二.面向对象中的成员 字段.方法属性 三.成员修饰符 四.特殊成员 __init__.__doc__.__call__.__setitem ...
- AOP - C# Fody中的方法和属性拦截
很久很久以前用过postsharp来做AOP, 大家知道的,现在那东东需要付费,于是尝试了一下Fody,但是发现Fody跟新太快了,所以大家在安装fody的时候尽力安装老的版本:packages.co ...
- python7 静态方法、类方法、属性方法 ;反射;异常处理
#-*- coding:utf8 -*- # 静态方法@staticmethod # 静态方法(当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了.) clas ...
- 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理
委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...
- Touch 方法&属性 映射工具
Touch 方法&属性 映射工具(0.5 版本) 标签 : github 线上后门与接口调试: 原先需要测试一个接口(如Dubbo.DAO), 或为线上留后门, 需要写大量的Web层(Api. ...
- 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 ...
- (转)C# Aop简单扫盲及ORM实体类属性拦截示例
转自: http://www.cnblogs.com/cyq1162/archive/2012/05/30/2526573.html 先说下场景,C#中为什么要使用Aop,而我又是在哪里使用Aop? ...
- 【Spring开发】—— AOP之方法级拦截
前言: 前面介绍了Spring的核心模块以及相关的依赖注入等概念.这篇讲解一下spring的另一个重点,AOP面向切面编程. 说道AOP不得不提到几个概念: 切面:也就是我们自己的一些业务方法. 通知 ...
- jquery.validate.min.js 用法方法示例
页面html 代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...
随机推荐
- 图片按日期分类和查看程序(WPF开发)(附源码)
手机方便了我们的生活,可以随时随地拍摄.越来越多的图片堆砌在电脑里.看到杂乱无章的图片,实在感到头痛.手动整理太复杂.基于此,我写了一个小程序,可以将图片按日期整理和查看.按日期查看图片,回忆过去的点 ...
- linux解决病毒系列之一,删除十字符libudev.so病毒文件
前两天被服务器商通知服务器带宽流量增加,我想了想我们服务走的内网,没有什么大的带宽占用,于是我马上登录服务器. 用top命令查看运行情况,我擦,有一个进程吃了很高的cup,于是我赶紧用kill -9 ...
- CentOS7 下安装 iSCSI Target(tgt) ,使用 Ceph rbd
目录 一.iSCSI 介绍 1. iSCSI 定义 2. 几种常见的 iSCSI Target 3. 优缺点比较 二.安装步骤 1. 关闭防火墙 2. 关闭selinux 3. 通过 yum 安装 t ...
- MyBatis JavaType JdbcType
MyBatis 通过包含的jdbcType类型 BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED TINYINT REAL VARCHAR BINARY BLOB NV ...
- Log4j和Log4j2的区别
Log4j是Apache的一个开源项目,我们不去考究它的起源时间,但是据我了解,log4j 1已经不再更新了. 下面我就以列举的方式来浅谈log4j和log4j 2的不同之处. 一.配置文件类型 lo ...
- Unix/Linux系统管理技术手册学习笔记——shell
创建日期:2016/02/29 更新日期:2016/02/29 shell变量赋值时不能在等号两边留空白,否则shell会把变量名误认为是命令名 双引号括起来的变量可以进行替换(用*和?这样的文件名匹 ...
- 表格行mouse经过时高亮显示
昨天有解决网友一个问题<Repeater控件添加onmouseover和onmouseout事件>http://www.cnblogs.com/insus/p/3714013.html 这 ...
- 获取当前iframe动态加载文档的href
Insus.NET想实现一个功能,一个旧的站点A,它有两个网页logon.aspx和Default.aspx(登录成功能访问).由于某些原因,需另建一个新站点B,这个新站点B也有两个网页B_Index ...
- Spring基础(1) : 自动装配
1.自动装配 1.1 byType 1.1.1根据类型自动匹配,若当前没有类型可以注入或者存在多个类型可以注入,则失败.必须要有对于的setter方法 public class Person{ pub ...
- 虚方法virtual详解(转载)
从C#的程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而虚函数在编译期间是不被静态编译的,它的 ...