好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

一个简单的AOP框架学习

一个简单的AOP框架学习

在.Net Unity2.0中的Interception,按三种方式实现:

1.TransparentProxy/RealProxy Interceptor 即Remoting代理机制。

2.Interface Interceptor  即动态代码 (Emit编程)实现

3.Virtual Method Interceptor 也是动态代码实现,Emit编程基本类似于IL编程了。

实例拦截与类型拦截

1.实例拦截



TransparentProxy 与 Interface Interceptor 属于实例拦截,所谓实例拦截就是被拦截对象完整而独立的在内参中存在。Client端通过代理类与被拦截对象发生通信(方法调用)。

2.类型拦截

Virtual Method 方式属于类型拦截,内参中不存在被拦截类型的实例,拦截框架通过动态代码生成被拦截类型的子类型程序集,该程序集被加载后对应的子类型被实例化于内存中与Client发生通信

 

下面针对TransparentProxy/RealProxy 与 Interface Interceptor帖出手头上dll实现的代码

1.TransparentProxy/RealProxy实现

view source print ?

using System.Reflection;

using System.Runtime.Remoting.Proxies;

using System.Runtime.Remoting.Messaging;

using System.Runtime.Remoting;

 

 

internal class TransparentProxy : RealProxy

{

     // Fields

     private readonly MarshalByRefObject m_Target;

 

     // Methods

     public TransparentProxy(MarshalByRefObject target)

         : base (target.GetType())

     {

         this .m_Target = target;

     }

 

     public static object GetProxy(MarshalByRefObject target)

     {

         TransparentProxy proxy = new TransparentProxy(target);

         return proxy.GetTransparentProxy();

     }

 

     public override IMessage Invoke(IMessage msg)

     {

         IMessage message = null ;

         IMethodCallMessage callMsg = msg as IMethodCallMessage;

         if (callMsg != null )

         {

             object [] customAttributes = callMsg.MethodBase.GetCustomAttributes( true );

             this .InvokeBeforeAttribute(customAttributes, callMsg);

             try

             {

                 message = RemotingServices.ExecuteMessage( this .m_Target, callMsg);

             }

             catch (Exception exception)

             {

                 this .InvokeExceptionAttribute(customAttributes, callMsg, exception);

                 throw ;

             }

             this .InvokeAfterAttribute(customAttributes, callMsg, ((ReturnMessage)message).ReturnValue);

         }

         return message;

     }

   //..........

   //............

}

类TransproxyProxy中维护着一个到target类实例的引用(必须是MarshalByRefObject类型的子类),最终的方法调用会通过消息机制到达target实例--语句RemotingServices.ExecuteMessage(this.m_Target, callMsg);,在调用目标对象的目标方法之前会调用InvokeBeforeAttribute,错误时会调用InvokeExceptionAttribute,而完成后调用 InvokeAfterAttribute .这里需要注意的是Unity2.0 Interception 中将要调用的InterceptionBehavior构建成管道模型,编程时会有Scop样的开闭结构,而这里的实现只是顺序的调用,这点需要加以区分 。InvokeBeforeAttribute等方法实现如下

view source print ?

private void InvokeAfterAttribute( object [] attributes, IMethodCallMessage callMsg, object result)

{

     foreach ( object obj2 in attributes)

     {

         AfterAttribute attribute = obj2 as AfterAttribute;

         if (attribute != null )

         {

             attribute.Invoke( this .m_Target, callMsg.MethodBase, callMsg.InArgs, result);

         }

     }

     List<IInterception> interceptionList = ProxyBuilder.GetInterceptionList( this .m_Target.GetType().FullName + "." + callMsg.MethodName, InterceptionType.After);

     if (interceptionList != null )

     {

         foreach (IInterception interception in interceptionList)

         {

             interception.Invoke( this .m_Target, callMsg.MethodBase, callMsg.InArgs, result);

         }

     }

}

2.Interface Interceptor 代码

view source print ?

public static object GetProxyInstance( object target, Type interfaceType)

    {

        return Activator.CreateInstance(GetProxyType(target.GetType(), interfaceType), new object [] { target, interfaceType });

    }

 

    private static Type GetProxyType(Type targetType, Type interfaceType)

    {

        AppDomain domain = Thread.GetDomain();

        AssemblyName name = new AssemblyName();

        name.Name = "TempAssemblyInjection" ;

        AssemblyName name2 = name;

        AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(name2, AssemblyBuilderAccess.Run);

        ModuleBuilder builder = assemblyBuilder.DefineDynamicModule( "TempClassInjection" );

        Type type = builder.GetType( "TempAssemblyInjection__Proxy" + interfaceType.Name + targetType.Name);

        if (type != null )

        {

            return type;

        }

        m_TypeBuilder = builder.DefineType( "TempAssemblyInjection__Proxy" + interfaceType.Name + targetType.Name, TypeAttributes.Public, targetType.BaseType, new Type[] { interfaceType });

        m_Target = m_TypeBuilder.DefineField( "target" , interfaceType, FieldAttributes.Private);

        m_Interface = m_TypeBuilder.DefineField( "iface" , typeof (Type), FieldAttributes.Private);

        CreateConstructor(m_TypeBuilder, m_Target, m_Interface);

        foreach (MethodInfo info in interfaceType.GetMethods())

        {

            CreateProxyMethod(info, m_TypeBuilder);

        }

          

        return m_TypeBuilder.CreateType();

          

    }

 上面代码通过Emit编程动态构建程序集,程序集中包括一个到目标类的代理类,针对给定接口中的方法签名逐个创建代理方法--语句CreateProxyMethod(info, m_TypeBuilder);
另外可以看到代理类型的程序集只在第一次访问时被创建
--语句 
 Type type = builder.GetType("TempAssemblyInjection__Proxy" + interfaceType.Name + targetType.Name);
   if (type != null)
    {
         return type;
     }

建立的代理类定义类似如下代码:

view source print ?

public class TempAssemblyInjection__ProxyIAnimalDog : IAnimal

{

     // Fields

     private Type iface;

     private IAnimal target;

   

     // Methods

     public TempAssemblyInjection__ProxyIAnimalDog( object obj1, Type type1)

     {

         this .target = (IAnimal) obj1;

         this .iface = type1;

     }

   

     public override int Run( int num1, int num2)

     {

         object [] parameters = new object [] { num1, num2 };

         return ( int ) DynamicProxy.InterceptHandler( this .target, <BR>           Helper.GetMethodFromType( this .target.GetType(), MethodBase.GetCurrentMethod()),<BR>           parameters, <BR>           Helper.AspectUnion(Helper.GetMethodFromType( this .iface, MethodBase.GetCurrentMethod()).GetCustomAttributes( typeof (AspectAttribute), true ))<BR>      );

     }

}


 DynamicProxy.InterceptHandler的代码

view source print ?

public static object InterceptHandlerMethod( object target, MethodBase method, object [] parameters, AspectAttribute[] attributes)

{

     object obj2;

     foreach (AspectAttribute attribute in attributes)

     {

         if (attribute is BeforeAttribute)

         {

             attribute.Invoke(target, method, parameters, null );

         }

     }

     foreach (IInterception interception in ProxyBuilder.GetInterceptionList(target.GetType().FullName + "." + method.Name, InterceptionType.Before))

     {

         interception.Invoke(target, method, parameters, null );

     }

     try

     {

         obj2 = target.GetType().GetMethod(method.Name).Invoke(target, parameters);

     }

     catch (Exception exception)

     {

         foreach (AspectAttribute attribute2 in attributes)

         {

             if (attribute2 is ExceptionAttribute)

             {

                 attribute2.Invoke(target, method, parameters, exception);

             }

         }

         foreach (IInterception interception2 in ProxyBuilder.GetInterceptionList(target.GetType().FullName + "." + method.Name, InterceptionType.Exception))

         {

             interception2.Invoke(target, method, parameters, exception);

         }

         throw ;

     }

     foreach (AspectAttribute attribute3 in attributes)

     {

         if (attribute3 is AfterAttribute)

         {

             attribute3.Invoke(target, method, parameters, obj2);

         }

     }

     foreach (IInterception interception3 in ProxyBuilder.GetInterceptionList(target.GetType().FullName + "." + method.Name, InterceptionType.After))

     {

         interception3.Invoke(target, method, parameters, obj2);

     }

     return obj2;

}

 

// Properties

public static Callback InterceptHandler

{

     get

     {

         return new Callback(DynamicProxy.InterceptHandlerMethod);

     }

}

完成代码与使用Demo请下载演示包

================================== 点这里下载 =========================

http://www.cnblogs.com/wdfrog/archive/2011/03/18/1988091.html

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于一个简单的AOP框架学习的详细内容...

  阅读:40次