动态织入的AOP实现

来源:互联网 发布:内核参数优化 编辑:程序博客网 时间:2024/05/17 04:07

转载自:http://www.cnblogs.com/luminji/archive/2012/01/10/2318211.html

动态织入的AOP实现,有两种方法:

第一类,借助于Remoting命名空间下的几个类,通过获取当前上下文及反射的机制来实现,这需要被AOP的类需要继承自arshalByRefObject或者ContextBoundObject;

第二类,原理是基于动态代理的思想,即在运行时动态构造一个原有类的子类,这样就可以在子类的重载方法中插入额外代码。

这两类方法,都有显著的不足,前者直接要求我们继承固定类,后者呢,除非父类方法被定义为virtual,或者方法定义于某个接口,否则就不能被重载,这就是得“拦截”并不是可以对任意的方法进行的。

动态织入局限于CLR的限制,不能实现对任何方法进行AOP,如果要突破这个限制,只能采用静态织入的方法,静态织入采用。静态织入突破OO设计模式,可以拦截所有的方法甚至构造函数或属性访问器,因为它是直接修改IL。还有,因为它在运行前修改原有程序集,也就基本不存在运行时的性能损失问题了。它的不足,一方面是框架较复杂,实现较麻烦,依赖于对底层的IL指令集的操纵;

一:继承自ContextBoundObject的实现

帮助类:

public class LogHandler : ICallHandler
{
    /// <summary>
    /// 执行顺序
    /// </summary>
    public int Order { get; set; }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("方法名: {0}", input.MethodBase.Name);
        Console.WriteLine("参数:");
        for (var i = 0; i < input.Arguments.Count; i++)
        {
            Console.WriteLine("{0}: {1}", input.Arguments.ParameterName(i), input.Arguments[i]);
        }
        Console.WriteLine("方法执行前的处理");
        var retvalue = getNext()(input, getNext);
        Console.WriteLine("方法执行后的处理");
        return retvalue;
    }
}
 
public class LogHandlerAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LogHandler();
    }
}
调用方:

public interface ISample{    [LogHandler]    void DoSomething();    void DoSomethingNoAop();} class Sample1 : ISample{    public void DoSomething()    {        Console.WriteLine("Sample1 do something");    }     public void DoSomethingNoAop()    {        Console.WriteLine("Sample1 do something no aop");    }} public class SampleClass{     [LogHandler]    public virtual void SampleVirtual()    {        Console.WriteLine("Virtual method");    }     public void Sample()    {        Console.WriteLine("Sampe method");    }} class Program {     static void Main() {        //针对接口        var container1 = new UnityContainer()            .AddNewExtension<Interception>()            .RegisterType<ISample, Sample1>();        container1            .Configure<Interception>()            .SetInterceptorFor<ISample>(new InterfaceInterceptor());        container1            .Configure<Interception>()            .SetInterceptorFor<SampleClass>(new VirtualMethodInterceptor());        var sample1 = container1.Resolve<ISample>();        sample1.DoSomething();        sample1.DoSomethingNoAop();         //针对虚拟方法        var sample2 = container1.Resolve<SampleClass>();        sample2.SampleVirtual();        sample2.Sample();         Console.ReadKey();    } }

可以看到,第二种方法是用Unity实现的,关于Unity,这里多说两句:

Unity的AOP可以从3种标记的情况拦截:
TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject;
VirtualMethod:直接在类的虚方法上进行标记,如上文代码;
InterfaceInterceptor:在接口的方法上进行标记,如上文代码;

代码下载:ConsoleApplication1.rar,ConsoleApplication2.rar