AspectSharp例子分析

來源:互聯網
上載者:User

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的關鍵就在那個動態建立的實現所有介面的代理對象上,
但是這個代理對象是如何與我們定義的攔截器和混合器互動的呢? 請關注後續文章.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.