Aspect#的动态截入

代理对象是通过以下代码来进行动态戴入.

switch (handlerField.Name) {
 case mixinHandlerFieldName:
    {
        ilGenerator.Emit(OpCodes.Callvirt, typeof(IMixinInvocationHandler).GetMethod("Invoke") );
        break;
    }
    default: 
    {
        ilGenerator.Emit(OpCodes.Callvirt, typeof(IInvocationHandler).GetMethod("Invoke") );
        break;
    }
}

而IMixinInvocationHandler和IInvocationHandler接口的实现在代理对象的构造方法中中传入, 如下代码:

// class AspectSharpEngine
public static object Wrap(object target) {
     Type originType = target.GetType();
     string typeName = originType.FullName;

     IInvocationHandler handler = GetInvocationHandler(target);
     IMixinInvocationHandler mixinHandler = GetMixinInvocationHandler();
     IMixin[] mixins = GetMixins(typeName);

     // ...

     return ProxyGenerator.CreateInstance(  _typeCache[typeName], mixins, handler, mixinHandler );
}
同时传入代理对象构造方法的还有对象上的混合器接口.
这里IInvocationHandler的实现为DefaultInvocationHandler,
IMixinvocationHandler的实现为MixinInvocationHandler,
GetMixins从配置文件中获取加在对象上的所有混入器.

方法的截入过程:

1. 代理对象调用DefaultInvocationHandler.Invoke;
2. Invoke方法调用GetMethodInvocation通过配置文件来取得方法的拦截器;
   IMethodInvocation GetMethodInvocation(MethodInfo method, object[] arguments) {
       string typeName = _target.GetType().FullName;

       IAspect aspect = GetAspectForType(typeName);

       if(aspect != null && aspect.PointCuts != null) {
           IMatch match = _methodMatcher.Match(method, aspect.PointCuts);
           return new InterceptorMethodInvocation(_target, method, arguments, match.Interceptors);
           // match.Interceptors为方法的所有载入点.
       }
       else {
           return new DefaultMethodInvocation(_target, method, arguments);
       }
   }

这时有两种情况

a 方法没有定义截入点.
3. 建立一个DefaultMethodInvocation(默认的方法转发器);
4. 调用InvokeMethod执行真正的方法实现代码.

b. 方法有定义截入点.
3. 建立一个InterceptorMethodInvocation(拦截方法转发器);
4. 调用转发器的proceed方法;
     // class IntreceptorMethodInvocation
      public override object Proceed() {
           if ( _currentInterceptorIndex == (_interceptors.Length - 1) ) {
                 return InvokeMethod(_target, _method, _arguments);
           }

             _currentInterceptorIndex++ ;

             IInterceptor currentInterceptor = _interceptors[_currentInterceptorIndex];

             if(currentInterceptor is IMethodInterceptor) {
                    return ((IMethodInterceptor)currentInterceptor).Invoke(this);
             }
             else {
                   return InvokeMethod(_target, _method, _arguments);
             }
          }
          // 调用拦截器的Invoke方法, 然后执行真正方法的实现代码.
          // 拦截器必须实现IMethodInterceptor接口.

     此段代码只能调用_interceptors[0]的拦截器代码, 其它拦截器代码如何执行入?
    答案在我们实现的拦截器中,  在拦截器中, 典型的Invoke代码如下:
       public object Invoke(IMethodInvocation invocation)  {
          try  {
             // ...
             return invocation.Proceed();  这个是必须的, 这将使拦截过程继续下去.
          }
          catch(Exception e)  {
              // ...
          }
          return null;
      }

混合器的混入过程

1. 调用MixinInvocationHandler.Invoke方法;
2. 通过DefaultInvocationHandler的GetTargetMethod取得混合器的方法.
3. 调用方法的实现代码.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值