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的思想, 在原有的功能上进行扩展. 那么有没有一种东西, 可以实现当我们需要扩展 ...
随机推荐
- Nhibernate工具Profiler配置
1.使用之前需要确认Framework的Version,如果是4.0那么使用如下程序集需要在 创建ISessionFactory的项目中引用NHProfiler安装目录下的 HibernatingRh ...
- springmvc get post put delete
web.xml <!-- 配置 org.springframework.web.filter.HiddenHttpMethodFilter: 可以把 POST 请求转为 DELETE 或 POS ...
- 【转】Linux 下取进程占用 cpu/内存 最高的前10个进程
# Linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...
- MiniGUI 显示中文
修改/usr/local/etc/MiniGUI.cfg # The first system font must be a logical font using RBF device font.[s ...
- 调试ASP.NET网站IIS环境问题解决方法汇总
调试网站时出现错误,错误如下: 1. 分析器错误消息: 创建 RewriterConfig 的配置节处理程序时出错: 无法生成临时类(result=1).error CS2001: 未能找到源文件“C ...
- Maven:如何在eclipse里新建一个Maven的java项目和web项目
如何在eclipse里新建一个Maven的java项目和web项目: 一:java项目 New-->Other-->Maven 右击项目-->properties,修改以下文件: ① ...
- Spark 实现自定义对象sequenceFile方式存储,读写示例(scala编写)
package com.fuge.bigdata.datahub.analysis import java.io.{DataInput, DataOutput} import com.fuge.big ...
- Qt查找孩子findChild
转载自[http://blog.csdn.net/liang19890820/article/details/52118210] 简述 在Qt编程过程中,通常会有多个部件嵌套,而大多数部件都有父子依赖 ...
- hydra简单使用示例
本内容为网上收集整理,仅作为备忘!! hydra简单使用示例: 破解https: # hydra -m /index.php -l muts -P pass.txt 10.36.16.18 https ...
- NSwag在asp.net web api中的使用,基于Global.asax
https://github.com/NSwag/NSwag/wiki/OwinGlobalAsax This page explains how to use the NSwag OWIN midd ...