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 ...
随机推荐
- ES6快到碗里来---一个简单的爬虫指南
学习ES6的时候,没少看ES6入门,到现在也就明白了个大概(惭愧脸).这里不谈ES6,只谈怎么把ES6的页面爬下来放到一起成为一个离线文档. 之前居然没注意过作者把这本书开源了..瞎耽误功夫...地址 ...
- 有意思的App
掘金 javadoop 专业相机也羡慕奖 – Focos 说个睡前故事 so easy 奖 – 洪恩双语绘本 效率蹭蹭上升奖 – Sorted³ 时光隧道走一回奖 – NOMO 相机 设计师也爱用奖 ...
- gridvew使用技巧2
GridVew1_RowDataBindGridView1.DataKeys[e.Row.RowIndex].Values[].ToString(); foreach (GridViewRow t i ...
- JavaScript -- Window-Interval
-----031-Window-Interval.html----- <!DOCTYPE html> <html> <head> <meta http-equ ...
- Chrome 开发工具之Timeline/Performance
之前有说到Element,Console,Sources大多运用于debug,Network可用于debug和查看性能,今天的主角Timeline(现已更名Performance)更多的是用在性能优化 ...
- js便签笔记(14)——用nodejs搭建最简单、轻量化的http server
1. 引言 前端程序猿主要关注的是页面,你可能根本就用不到.net,java,php等后台语言. 但是你制作出来的网页总要运行.总要测试吧?——那就免不了用到http server.我先前都是用vis ...
- 扒一扒HTTPS网站的内幕
215年6月,维基媒体基金会发布公告,旗下所有网站将默认开启HTTPS,这些网站中最为人所知的当然是全球最大的在线百科-维基百科.而更早时候的3月,百度已经发布公告,百度全站默认开启HTTPS.淘宝也 ...
- 在Java的反射中,Class.forName和ClassLoader的区别
前言 最近在面试过程中有被问到,在Java反射中Class.forName()加载类和使用ClassLoader加载类的区别.当时没有想出来后来自己研究了一下就写下来记录一下. 解释 在java中Cl ...
- Linux 下面解压.tar.gz 和.gz文件解压的方式
Linux 下面解压.tar.gz 和.gz文件解压的方式 两种解压方式 1 .tar.gz 使用tar命令进行解压 tar -zxvf java.tar.gz 解压到指定的文件夹 tar -zxvf ...
- [转]Reporting Services 中的身份验证类型
本文转自:https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2008/cc281310%28v%3dsql.100%2 ...