以下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. Sharding-jdbc(一)分库分表理解

    1.什么是分库分表 所谓的分库分表就是数据的分片(Sharding). 2.为什么需要分库分表 因为随着公司的业务越来越大,对于现成单机单个应用瓶颈问题,对数据持久化硬盘如何进行扩容. 可以从4个方面 ...

  2. PLSQL Developer概念学习系列之登录连接Oracle时出现(没有登录) -PL / SQL Developer:ORA - 12541: TNS :无建听程序的错误解决办法(图文详解)

    不多说,直接上干货! 前期博客 PLSQL Developer概念学习系列之如何正确登录连接上Oracle(图文详解)   如用scott.scott_password进行登录,orcl是全局数据库 ...

  3. Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装

    组件封装 为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度. 组件结构 组件封装重构后,试图组件结构如下图所示 代码一览 Home组件被简化,包含导航.头部和主内容三个组 ...

  4. 29-hadoop-使用phtonenix工具&分页&数据导入

    因为rowkey一般有业务逻辑, 所以不可以直接使用rowkey进行分页, startkey, endkey 想要使用SQL语句对Hbase进行查询,需要使用Apache的开源框架Phoenix. 安 ...

  5. Java NIO系列教程(五) 通道之间的数据传输

    在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...

  6. KMP算法中next数组的理解与算法的实现(java语言)

    KMP 算法我们有写好的函数帮我们计算 Next 数组的值和 Nextval 数组的值,但是如果是考试,那就只能自己来手算这两个数组了,这里分享一下我的计算方法吧. 计算前缀 Next[i] 的值: ...

  7. Spring 注解方式引入配置文件

    配置文件,我以两种为例,一种是引入Spring的XML文件,另外一种是.properties的键值对文件: 一.引入Spring XML的注解是@ImportResource @Retention(R ...

  8. JavaScript回调函数及数组方法测试

    JavaScript回调函数及数组方法测试 具体代码如下: <!DOCTYPE html> <html lang="en"> <head> &l ...

  9. 4.3.6 对象的界定通过编写接口来访问带这类命名结构的表会出问题。如前所述,SQL Server的灵活性不应用作编写错误代码或创建问题对象的借口。 注意在使用Management Studio的脚本工具时,SQL Server会界定所有的对象。这不是因为这么做是必须的,也不是编写代码的最佳方式,而是因为在界定符中封装所有的对象,比编写脚本引擎来查找需要界定的对象更容易。

    如前所述,在创建对象时,最好避免使用内嵌的空格或保留字作为对象名,但设计人员可能并没有遵守这个最佳实践原则.例如,我当前使用的数据库中有一个审核表名为Transaction,但是Transaction ...

  10. WCF无法引入Model实体解决方案

    在重新引用服务的时候,或者是是更新引用服务的时候,点“高级”按钮,在服务引用设置对话框中,将“重新使用引用的程序集中的类型”这个勾取消,这样就能安全的重新引用服务.