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,可以理 ...
随机推荐
- Python基础学习篇章四
一. Python数据类型之字典 1. 键的排序:for循环 由于字典不是序列,因此没有可靠的从左至右的顺序.这就导致当建立一个字典,将它打印出来,它的键也许会以与我们输入时的不同的顺序出现.有时候我 ...
- linux搭建django项目基本步骤
一 linux下django基本项目搭建流程:M model 用于与数据库交互V view 接受前台请求 调用model获取结果,调用T获取页面,返回给前台T template 接受view的要求 生 ...
- CodeForces 1B-字符串,进制转换与数学
一个萌新的成长之路 Background 同学们都回家了,只有我和wjh还有邢神在机房敲代码,吃random口味的方便面-- Description Translated by @PC_DOS fro ...
- python基础——列表推导式
python基础--列表推导式 1 列表推导式定义 列表推导式能非常简洁的构造一个新列表:只用一条简洁的表达式即可对得到的元素进行转换变形 2 列表推导式语法 基本格式如下: [expr for va ...
- 通过java api统计hive库下的所有表的文件个数、文件大小
更新hadoop fs 命令实现: [ss@db csv]$ hadoop fs -count /my_rc/my_hive_db/* 18/01/14 15:40:19 INFO hdfs.Peer ...
- c# IPC实现本机进程之间的通信
IPC可以实现本地进程之间通信.这种用法不是太常见,常见的替代方案是使用wcf,remoting,web service,socket(tcp/pipe/...)等其他分布式部署方案来替代进程之间的通 ...
- 简单聊聊java中的final关键字
简单聊聊java中的final关键字 日常代码中,final关键字也算常用的.其主要应用在三个方面: 1)修饰类(暂时见过,但是还没用过); 2)修饰方法(见过,没写过); 3)修饰数据. 那么,我们 ...
- requests post一个json数据
# post一个json数据 import requests headers={ "Accept":"application/json, text/plain, */*& ...
- 调用Kubernetes API操作Kubernetes
准备工作 首先要准备一个1.5+版本的Kubernetes,并且开放了API Server的http访问端口8080.本文使用的是1.10的版本,没有环境的可以参考我上一篇文章<在CentOS ...
- java中匿名内部类的应用
如果某一个类实现了接口,而且仅仅在程序代码中使用了一次,那么就没必要单独定义该方法,可以通过接口来定义匿名内部类 interface Message{ public void print(); } p ...