• 推荐
  • 评论
  • 收藏

一个简单的AOP框架学习

2022-11-06    8230次浏览

在.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实现

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等方法实现如下

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 代码

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;
     }

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

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的代码

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

原文地址:https://www.cnblogs.com/Leo_wl/p/1988544.html