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("执行了方法本身!");
}
}

补充: .NET上下文(ContextBoundObject对象)
什么叫上下文,千万别和ASP.NET中的上下文搞混了,这个上下文是个形容词,在不同的场合有不同的意思。在ASP.NET中的上下文是指Context对象,这个对象基本上包容了HTTP协议的整个生命周期的信息,可以获取到客户端浏览器的一些基本信息,也可以获取到关于HTTP协议的一些信息,等等。
这里所讲的上下文是.NET程序执行的最小逻辑范围,ASP.NET上下文是站在B/S编程模型角度去看待的,而这里的上下文是站在.NET底层运行角度看来的,后者是代码的上下文,前者是整个生命周期的上下文。
在没有接触ContextBoundObject之前我一直以为.NET程序执行的最小逻辑范围是应用程序域(AppDomain),知道了之后才知道另有隐情,上下文是用来确定对象的逻辑归属,在多线程(Thread)、事物处理(Transaction)、企业服务(Enterprise)等方面都需要用上下文来对对象进行规划。
有了特性标签自然就要有特性标签对应的类,以及AOP的实现方法,这些东西可以单独独立到一个文件或程序集里。
首先是贴在方法上的标签,实现为空:
//贴在方法上的标签[MyInterceptorMethod]
[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);
}
}

补充: 这里继承了ContextAttribute, 在.net中怎么使用attribute,参考: http://blog.csdn.net/u013473447/article/details/41785823
这里定义了一个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介绍
首先看一段简单的代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); } //来自UI层的调用 ...
- C#利用Attribute实现简易AOP介绍 (转载)
地址:http://dotnet.9sssd.com/csbase/art/638 http://wayfarer.blog.51cto.com/1300239/279913 http://devel ...
- 利用.NET Core类库System.Reflection.DispatchProxy实现简易Aop
背景 Aop即是面向切面编程,众多Aop框架里Castle是最为人所知的,另外还有死去的Spring.NET,当然,.NET Core社区新秀AspectCore在性能与功能上都非常优秀,已经逐渐被社 ...
- C#利用Emit反射实现AOP,以及平台化框架封装思路
C#利用Emit反射实现AOP,以及平台化框架封装思路 这是前两天扒的一段动态代理AOP代码,用的Emit反射生成子类来实现代理模式,在这里做个小笔记,然后讨论一下AOP框架的实现思路. 首先是主函数 ...
- 利用基于@AspectJ的AOP实现权限控制
一. AOP与@AspectJ AOP 是 Aspect Oriented Programming 的缩写,意思是面向方面的编程.我们在系统开发中可以提取出很多共性的东西作为一个 Aspect,可以理 ...
- .Net core 2.0 利用Attribute获取MVC Action来生成菜单
最近在学习.net core的同时将老师的MVC5项目中的模块搬过来用,其中有一块就是利用Attribute来生成菜单. 一·首先定义Action实体 /// <summary> /// ...
- 利用Unity3D制作简易2D计算器
利用Unity3D制作简易2D计算器 标签(空格分隔): uiniy3D 1. 操作流程 在unity3DD中创建一个新项目 注意选择是2D的(因为默认3D) 在Assets框右键新建C#脚本 在新建 ...
- 利用Attribute实现Aop
Aop“面向切面编程”,与OOP“面向对象编程”一样是一种编程思路.个人理解:在不改变原有逻辑的基础上,注入其他行为. 基础代码(仿MVC拦截器实现) namespace HGL.Toolkit.Ao ...
- C# Unity依赖注入利用Attribute实现AOP功能
使用场景? 很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用OOP的思想, 在原有的功能上进行扩展. 那么有没有一种东西, 可以实现当我们需要扩展 ...
随机推荐
- 转:探索C++0x: 1. 静态断言(static_assert)
转自:http://www.cppblog.com/thesys/articles/116985.html 简介 C++0x中引入了static_assert这个关键字,用来做编译期间的断言,因此叫做 ...
- appium的初始化准备工作
文章出处http://blog.csdn.net/jiuzuidongpo/article/details/51790455 Appium在接收到客户端脚本的连接之后的初始化准备工作列表(细节部分详细 ...
- Java并发(2):Lock
在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方 ...
- 在Windows上以服务方式运行 Redis
ServiceStack.Redis 使用教程里提到Redis最好还是部署到Linux下去,Windows只是用来 做开发环境,现在这个命题发生改变了,在Windows上也可以部署生产环境的Redis ...
- java项目地址和服务器地址区分
项目地址String filePath = request.getSession().getServletContext().getRealPath("/") + "up ...
- MAC mysql install
# linux 查看是否安装mysql rpm -qa |grep mysql yum 安装mysql yum -y install mysql-server 1 download ...
- js防抖
那我们设置个 options 作为第三个参数,然后根据传的值判断到底哪种效果,我们约定: leading:false 表示禁用第一次执行trailing: false 表示禁用停止触发的回调 我们来改 ...
- git常用命令【转】
先上一个git常用命令图片 Git配置 1 2 3 4 5 6 7 8 9 git config --global user.name "robbin" git config ...
- iOS基于XMPP实现即时通讯之一、环境的搭建
移动端访问不佳,请访问我的个人博客 使用XMPP已经有一段时间了,但是一直都没深入研究过,只是使用SDK做一些简单的操作,看了许多大神的博客,自己总结一下,准备写一系列关于XMPP的使用博客,以便于自 ...
- Jquery 动态生成的元素绑定事件
使用 on方法 $("#id1").on("click","#id2",function(){}) 这里要注意的是#id1必须是原来就存在的 ...