C#利用Attribute实现简易AOP介绍
首先看一段简单的代码:
| public partial class Form1 : Form |
| { |
| public Form1() |
| { |
| InitializeComponent(); |
| } |
| //来自UI层的调用 |
| private void button1_Click(object sender, EventArgs e) |
| { |
| BusinessHandler handler = new BusinessHandler(); |
| handler.DoSomething(); |
| } |
| } |
| //业务层的类和方法 |
| public class BusinessHandler |
| { |
| public void DoSomething() |
| { |
| MessageBox.Show("执行了方法本身!"); |
| } |
| } |
那么假设这是一个web程序,我们想在按钮点击时,先校验session,然后检验权限、起事务、写日志,然后再执行操作本身,最后再写日志。显然不能把对上面这些操作的方法调用都写在DoSomething()里,这样代码会变成一大坨屎,那我们该怎么办呢?
所谓AOP(面向切面编程)这个唬人的名词就是干这件事用的,其实现方式有很多种,比如利用Spring等框架,但是在实际项目中并不是想引一个框架进来就能随便引的,很多时候都需要我们自己手写一些机制。
这里想到了MVC当中的Filter,只要在Controller或者Action上打一个特性标签(Attribute),就能在方法执行前后做一些其他事情了。那么我们就来简单模拟一个Filter的实现吧。
首先给原先的方法改造一下,改成特性标签这种优雅的方式:
| //业务层的类和方法,让它继承自上下文绑定类的基类 |
| [MyInterceptor] |
| public class BusinessHandler : ContextBoundObject |
| { |
| [MyInterceptorMethod] |
| public void DoSomething() |
| { |
| MessageBox.Show("执行了方法本身!"); |
| } |
| } |
有了特性标签自然就要有特性标签对应的类,以及AOP的实现方法,这些东西可以单独独立到一个文件或程序集里。
首先是贴在方法上的标签,实现为空:
| //贴在方法上的标签 |
| [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] |
| public sealed class MyInterceptorMethodAttribute : Attribute { } |
之后定义贴在类上的标签:
| //贴在类上的标签 |
| [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] |
| public sealed class MyInterceptorAttribute : ContextAttribute, IContributeObjectSink |
| { |
| public MyInterceptorAttribute() |
| : base("MyInterceptor") |
| { } |
| //实现IContributeObjectSink接口当中的消息接收器接口 |
| public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next) |
| { |
| return new MyAopHandler(next); |
| } |
| } |
这里定义了一个MyAopHandler类,实现如下:
| //AOP方法处理类,实现了IMessageSink接口,以便返回给IContributeObjectSink接口的GetObjectSink方法 |
| public sealed class MyAopHandler : IMessageSink |
| { |
| //下一个接收器 |
| private IMessageSink nextSink; |
| public IMessageSink NextSink |
| { |
| get { return nextSink; } |
| } |
| public MyAopHandler(IMessageSink nextSink) |
| { |
| this.nextSink = nextSink; |
| } |
| //同步处理方法 |
| public IMessage SyncProcessMessage(IMessage msg) |
| { |
| IMessage retMsg = null; |
| //方法调用消息接口 |
| IMethodCallMessage call = msg as IMethodCallMessage; |
| //如果被调用的方法没打MyInterceptorMethodAttribute标签 |
| if (call == null || (Attribute.GetCustomAttribute(call.MethodBase, typeof(MyInterceptorMethodAttribute))) == null) |
| { |
| retMsg = nextSink.SyncProcessMessage(msg); |
| } |
| //如果打了MyInterceptorMethodAttribute标签 |
| else |
| { |
| MessageBox.Show("执行之前"); |
| retMsg = nextSink.SyncProcessMessage(msg); |
| MessageBox.Show("执行之后"); |
| } |
| return retMsg; |
| } |
| //异步处理方法(不需要) |
| public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) |
| { |
| return null; |
| } |
| } |
注意到上面的执行前后具体操作部分代码,相当于一个“代理类”,它实质上是改变了方法执行的上下文。可以用委托等面向对象程序结构把具体实现暴露给外部进行二次开发。
C#利用Attribute实现简易AOP介绍的更多相关文章
- C#利用Attribute实现简易AOP介绍 (转载)
地址:http://dotnet.9sssd.com/csbase/art/638 http://wayfarer.blog.51cto.com/1300239/279913 http://devel ...
- C#当中利用Attribute实现简易AOP
首先看一段简单的代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); } //来自UI层的调用 ...
- 利用.NET Core类库System.Reflection.DispatchProxy实现简易Aop
背景 Aop即是面向切面编程,众多Aop框架里Castle是最为人所知的,另外还有死去的Spring.NET,当然,.NET Core社区新秀AspectCore在性能与功能上都非常优秀,已经逐渐被社 ...
- Aop介绍及几种实现方式
Aop介绍 我们先看一下wiki百科的介绍 Traditional software development focuses on decomposing systems into ...
- Spring AOP介绍及源码分析
转自:http://www.uml.org.cn/j2ee/201301102.asp 软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程:前者是为了提高开发效率,而后者则使用了归纳法,把 ...
- Spring AOP编程(一)-AOP介绍
1. AOP介绍 l 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 ...
- Spring AOP介绍与使用
Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 面向切面 ...
- C#利用Emit反射实现AOP,以及平台化框架封装思路
C#利用Emit反射实现AOP,以及平台化框架封装思路 这是前两天扒的一段动态代理AOP代码,用的Emit反射生成子类来实现代理模式,在这里做个小笔记,然后讨论一下AOP框架的实现思路. 首先是主函数 ...
- 利用基于@AspectJ的AOP实现权限控制
一. AOP与@AspectJ AOP 是 Aspect Oriented Programming 的缩写,意思是面向方面的编程.我们在系统开发中可以提取出很多共性的东西作为一个 Aspect,可以理 ...
随机推荐
- nodejs(1-1)
http://www.runoob.com/nodejs/nodejs-tutorial.html
- linux系统命令学习系列-定时任务crontab命令
上节内容复习: at命令的使用 作业:创建一个任务10分钟后关机 at now+10 minutes at>shutdown at><EOT> 本节我们继续来说例行任务管理命令 ...
- CentOS7 安装eclipse
1. 首先将eclipse的压缩包文件解压到/opt目录下,要使用root权限.执行如下解压命令:tar -zxvf eclipse-jee-oxygen-1a-linux-gtk-x86_64.ta ...
- 服务器批量管理软件ansible安装以及配置
1.yum安装(管理主机以及被管理主机都需要安装) yum install epel-release yum install ansible 2.配置管理主机 vim /etc/ansible/hos ...
- Python/MySQL(三、pymysql使用)
Python/MySQL(三.pymysql使用) 所谓pymysql就是通过pycharm导入pymysql模块进行远程连接mysql服务端进行数据管理操作. 一.在pycharm中导入pymysq ...
- angular中使用echart遇到的获取容器高度异常的问题记录
问题 在使用echart去创建图表时,发现图表只占了容器的一个角落,如图,并没有充满容器. 第一反应是容器元素的样式有问题,于是我把容器的宽高都改为px指定的(之前是百分比设定的,查询资料发现说ech ...
- bootstrap——bootstrap-table(2)
先看问题现象: 问题描述: 点击"管理子账号"按钮,预期是按照传递的参数更新列表数据,但是最后才发现这个列表根本不会刷新,只会继承前一次的数据,意思也就是不会去请求第二次. 解决方 ...
- ES6 继续 变量的解构赋值
春节放假这几天,感觉跟梦一样,瞬间就过去了.现在上班的前几天,都感觉有点不真实,不过看到口袋里的钱,就知道,是真真实实的度过了这个假期. 现在得开始重新工作了: 变量的解构赋值 ES6 允许按照一定模 ...
- Java基础详解
从写Java系列的第一篇到现在已经三个月了,因为在网络上或书籍中没有见到一些很适合初学者的学习流程,所以下决心自己写一写,也当作回顾一下Java的知识.网上有许多Java教程之类的内容,都是从概念起步 ...
- hash解密小助手-python版
今天再看乌云大会的直播,最后一题用到了DEKHash解密,所以上github搜索了一个小工具,名字叫GeneralHashFunctions.py,出处忘记复制了,就复制了有用的代码,下次遇到出处在粘 ...