首先看一段简单的代码:
public partial class Form1 : Form |
{ |
public Form1() |
{ |
InitializeComponent(); |
} |
|
|
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")
|
{ }
|
|
|
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next)
|
{
|
return new MyAopHandler(next);
|
}
|
} |
这里定义了一个MyAopHandler类,实现如下:
|
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;
|
|
|
if (call == null || (Attribute.GetCustomAttribute(call.MethodBase, typeof(MyInterceptorMethodAttribute))) == null)
|
{
|
retMsg = nextSink.SyncProcessMessage(msg);
|
}
|
|
else
|
{
|
MessageBox.Show("执行之前");
|
retMsg = nextSink.SyncProcessMessage(msg);
|
MessageBox.Show("执行之后");
|
}
|
|
return retMsg;
|
}
|
|
|
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
|
{
|
return null;
|
}
|
} |
注意到上面的执行前后具体操作部分代码,相当于一个“代理类”,它实质上是改变了方法执行的上下文。可以用委托等面向对象程序结构把具体实现暴露给外部进行二次开发。
|
请发表评论