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,可以理 ...
随机推荐
- 启动mongodb遇到的错:warning: 32-bit servers don't have journaling enabled by deflity
执行修复:mongod --repair即可 正常关闭:killall mongod
- 基于JWT标准的用户认证接口实现
前面的话 实现用户登录认证的方式常见的有两种:一种是基于 cookie 的认证,另外一种是基于 token 的认证 .本文以基于cookie的认证为参照,详细介绍JWT标准,并实现基于该标签的用户认证 ...
- Properties文件读写问题
项目需要在Properties配置文件中设置一些配置属性,其中包含一些中文属性.经过一上午的奋斗终于圆满解决问题. 读取Properties文件所有属性 Map<String, String&g ...
- MyBatis(二):Select语句传递参数的集中方案
从别人说的方案中看出,传递参数方案还挺多,不如自己整理下,以便以后使用过程中有个笔记回忆录. 1.传递一个参数的用法: 配置文件 <select id="getById" r ...
- php实现记住密码自动登录的功能
$username=trim($_POST['username']); $password=md5(trim($_POST['password'])); $ref_url=$_GET['req_url ...
- C# 关键字替换
/// <summary> /// 关键字替换 /// </summary> /// <param name="body"></param ...
- tmux 终端复用详解
tmux是什么 我们在linux服务器上的工作一般都是通过一个远程的终端连接软件连接到远端系统进行操作,例如使用xshell或者SecureCRT工具通过ssh进行远程连接.在使用过程中,如果要做比较 ...
- [ZJOI2011]看电影(MOVIE)
题目描述 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院.但这家电影院分配座位的方式很特殊,具体方式如 ...
- C++Primer学习——未定义行为
定义: 主要是求值顺序的问题 int i = f1() + f2(); //我们无法知道是f1 还是 f2先被调用 而且求值顺序和优先级和结合律无关,比如: f() + g()*h( ...
- 17.10.28&29
28上午 骚猪选讲 28下午 BOZJ 1081 [SCOI2005]超级格雷码 感觉就是一个找规律,然后模拟输出.半天没找到一个比较简便的模拟方法,这份代码是学习网上一位大佬的,很巧妙. 代码: # ...