AspectSharp例子分析

AspectSharp自带的例子提供了一个简单的logger拦截器和一个持久化混合器. 下面来看看它的工作原理.

1. 类和接口说明:

IMessage: Message对象接口, (要实现aspect的对象必须声明接口?)
MessageImpl: 实现IMessage接口;
IMessagePersistence: Message对象持久化接口;
LoggerInterceptor: 日志拦截器;
MessagePersistenceMixin: Message持久混合器, 实现IMessagePersistence接口;

2. 主程序代码:

//Creating the proxy
IMessage message = AspectSharpEngine.Wrap( new MessageImpl() ) as IMessage;
   
message.Message = “test“;  
// 注一: 显然这个message并不是真正实现IMessage的对象, 否则将无法拦截方法.

//Casting to the persistence service
IMessagePersistence persistence = (IMessagePersistence)message;
// 注二: message对象并没有实现IMessagePersistence接口!  

persistence.Save();

看到这段代码完全无法想像AOP是如何工作, 有点偷天换日的感觉;
关键就在这个proxy对象上, 先做一个这样假设:

message.Message = “test“;  
这个message肯定不是MessageImpl的实例, 那么这个Message是什么呢? 可能是个Aspect对象(aspect对象包含对象的所有拦截器和混合器). 它包装了MessageImpl对象. 不能解释的就是Aspect并没有从IMessage接口继承?

IMessagePersistence persistence = (IMessagePersistence)message;
这个比较容易理解, 虽然message并没有实现IMessagePersistence, 但只要重载as操作就可以得到我们想要的.

3. AspectSharpEngine

看名字就知道啦, AspectSharp核心对象, 负责封装对象.来看一下封装对象的代码:

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

  // 取得Invocation的处理对象, 默认为DefaultInvocationHandler
   IInvocationHandler handler = GetInvocationHandler(target);

  // 取得MixinInvocation的处理对象, 默认为MixinInvocationHandler
   IMixinInvocationHandler mixinHandler = GetMixinInvocationHandler();

  // 取得所有加在对象上的混合器, 混合器在配置文件中声明.
   IMixin[] mixins = GetMixins(typeName);

  // 检查cache
   if ( !_typeCache.Contains(typeName) )
   {
     // 取得对象实现的接口
    Type[] interfaces = GetInterfacesFrom(originType);

    // 取得代理的对象类型, 注意, 这时传入了对象实现的接口和所有混合器的接口,
    // 是否会建立一个实现所有这些接口的对象类型了?
    Type proxyType = ProxyGenerator.CreateProxyType(interfaces, mixins);

    _typeCache.Add( typeName, proxyType );
   }

   // 返回已封装对象的实例.
   return ProxyGenerator.CreateInstance(
    _typeCache[typeName], mixins, handler, mixinHandler );
  }

4. ProxyGenerator

负责创建代理对象的类型和实例.

  /// Generates a proxy transient Type implementing all the specified interfaces and mixins
  /// redirecting method invocations to the specifed handler.
上面这段是CreateProxyType方法的描述, 如我所想, 确实要建立一个实现所有接口的代理对象. Year! 有点佩服自己了. (有东西就扔过来吧, 呵呵.)   

  internal static Type CreateProxyType(Type[] interfaces, IMixin[] mixins)
  {
   //  ...
   // 新建一个程序集
   AssemblyName assemblyName = new AssemblyName();    
   assemblyName.Name = "DynamicAssemblyProxyGen";

   // 定义动态程序集  
 AssemblyBuilder assemblyBuilder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
    assemblyName,
    AssemblyBuilderAccess.Run);
   
   ModuleBuilder moduleBuilder =
    assemblyBuilder.DefineDynamicModule( assemblyName.Name, true );

   TypeBuilder typeBuilder = moduleBuilder.DefineType(
    "ProxyType", TypeAttributes.Public|TypeAttributes.Class, null, MergeTypes(interfaces, mixins) );

   FieldBuilder handlerField = GenerateField( typeBuilder, handlerFieldName, typeof(IInvocationHandler) );

   FieldBuilder mixinHandlerField = GenerateField( typeBuilder, mixinHandlerFieldName, typeof(IMixinInvocationHandler) );
   
   FieldBuilder mixinsField = GenerateField( typeBuilder, "mixins", typeof(IMixin[]) );

   ConstructorBuilder constr = GenerateConstructor( typeBuilder, handlerField, mixinsField, mixinHandlerField );

   GenerateInterfaceImplementation( typeBuilder, interfaces, handlerField );   GenerateMixinImplementation

  ( typeBuilder, mixins, mixinHandlerField, mixinsField);   

  return typeBuilder.CreateType();
  }
 以上代码看的头有点大, 请参考.net sdk,
只要知道此方法建立一个实现所有接口的对象类型就好了.

  public static object CreateInstance(Type type, IMixin[] mixins,
   IInvocationHandler handler, IMixinInvocationHandler mixinHandler)
  {
   return Activator.CreateInstance( type,  new object[]{ handler, mixinHandler, mixins} );
  }
直接建立一个实例, 这个对象的类型就是在CreateProxyType中动态加入的. 不是Aspect. 判断错误!.
看来头大也要把CreateProxyType的代码弄清楚了. 不过有个疑问, 动态建立的构造函数如何加入代码?

5 配置文件

配置文件内容比较简单.
  <advices>
    <interceptors>
      // 定义拦截器
      <interceptor type="AspectSharp.Sample.Interceptor.LoggerInterceptor, AspectSharp.Sample" name="Logger" />
    </interceptors>
    <mixins>
      // 定义混合器
      <mixin type="AspectSharp.Sample.Mixin.MessagePersistenceMixin, AspectSharp.Sample" name="Persistence" />
    </mixins>
  </advices>

  <aspects defaultNamespace="AspectSharp.Sample">
     // 声明要aspect的对象和混合器
     <aspect mixin="Persistence" namespace="Model" typeName="MessageImpl">
     // 要拦截的对象, 
        <pointcut interceptor="Logger" method="set" />
     </aspect>
  </aspects>

显然, AOP的关键就在那个动态建立的实现所有接口的代理对象上,
但是这个代理对象是如何与我们定义的拦截器和混合器交互的呢? 请关注后续文章.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值