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爬虫——分析天猫iphonX的销售数据
01.引言 这篇文章是我最近刚做的一个项目,会带领大家使用多种技术实现一个非常有趣的项目,该项目是关于苹果机(iphoneX)的销售数据分析,是网络爬虫和数据分析的综合应用项目.本项目会分别从天猫和京 ...
- ICC_lab总结——ICC_lab5:布线&&数字集成电路物理设计学习总结——布线
字丑,禁止转载! 这里将理论总结和实践放在一起了. 布线的理论总结如下所示: 下面是使用ICC进行实践的流程: 本次的布线实验主要达成的目标是: ·对具有时钟树布局后的设计进行可布线性检查 ·完成布线 ...
- Orm之中介模型
什么是中介模型 中介模型针对的是ManyToMany(多对多)的时候第三张表的问题, 中介模型其实指的就是我们不通过Django创建第三张表,如果自己不创建第三张表,而是由django给我们创建,那就 ...
- python Flask
python Flask Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请 ...
- 存图方式---邻接表&邻接矩阵&前向星
基于vector存图 struct Edge { int u, v, w; Edge(){} Edge(int u, int v, int w):u(u), v(v), w(w){} }; vecto ...
- LabelFrame
LabelFrame组件是Frame组件的变体. 默认情况下,LabelFrame会在其子组件的周围绘制一个边框以及一个标题. 何时使用LabelFrame组件?当你想要奖一些相关的组件分为一组的时候 ...
- java8接口定义增强
java1.7之前,接口中只允许有全局常量和抽象方法,而1.8之后允许在接口中扩充default修饰的普通方法和static修饰的静态方法 其目的是在修改接口中方法的时候,子类就不必去一一修改 pac ...
- [LeetCode] Next Greater Element I 下一个较大的元素之一
You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of n ...
- mysql5.5以上 用户的操作
mysql5.5以上 用户的操作(转) 1.创建用户 create user 'username'@'host' identified by 'password'; 参数说明: username: ...
- 原生JS面向对象方法实现万年历
###面向对象的方法实现万年历 实现思路: 1.创建构造函数constructor ``` function Calender(main){ this.current ...