Unity 實現 AOP

前提
引用以下文件
Microsoft.Practices.ObjectBuilder2.dll
Microsoft.Practices.Unity.dll
Microsoft.Practices.Unity.Configuration.dll
Microsoft.Practices.Unity.Interception.dll
Microsoft.Practices.Unity.Interception.Configuration.dll
Microsoft.Practices.Unity.StaticFactory.dll
本文中的實現類繼承於IOutput接口
   1: public  interface IOutput {
   2:      void Output(int x);
   3: }
實現效果
我有兩個方法可以輸出字符串, 調用IOutput的實現類來輸出的,如:
   1: class OutputImplement2 : IOutput {
   2:     public void Output(int x) {
   3:         Console.WriteLine("output:{0}", x);
   4:     }
   5: }
調用它即在Main函數中
   1: var op2=new OutputImplement2();
   2: op2.Output(22);
即可,而AOP的作用是通過其它代碼,向op2.Output方法執行前或執行後注入其它執行過程即最後形成的結果可能是:
image
這裏除了箭頭所指的一句外其它的都是注入進去這個方法的。
 
 
 
定義處理代碼
這裏我們先定義一段處理方法的代碼,Unity規定它是ICallHandler的一個實現
   1: public class MyHandler : ICallHandler {
   2:     public int Order { get; set; }//這是ICallHandler的成員,表示執行順序
   3:     public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
   4:         Console.WriteLine("方法名: {0}", input.MethodBase.Name);
   5:         Console.WriteLine("參數:");
   6:         for (var i = 0; i < input.Arguments.Count; i++) {
   7:             Console.WriteLine("{0}: {1}", input.Arguments.ParameterName(i), input.Arguments[i]);
   8:         }
   9:         Console.WriteLine("執行");
  10:         //這之前插入方法執行前的處理
  11:         var retvalue = getNext()(input, getNext);//在這裏執行方法
  12:         //這之後插入方法執行後的處理
  13:         Console.WriteLine("完成");
  14:         return retvalue;
  15:     }
  16: }
好,下面我們來看看怎麼把MyHandler與IOutput關聯起來,大體有2種方法
1.通過代碼直接關聯
這種實現方式比較“硬”。
它是利用Atrribute來實現這種關聯的,首先,先建一個Attribute。
   1: public class MyHandlerAttribute : HandlerAttribute {
   2:     public override ICallHandler CreateHandler(IUnityContainer container) {
   3:         return new MyHandler();//返回MyHandler
   4:     }
   5: }
然後在IOutput的實現中使用如下代碼:
   1: [MyHandler]
   2:  class OutputImplement1 : IOutput {
   3:      public void Output(int x) {
   4:          Console.WriteLine("重典執行此方法輸出:{0}", x);
   5:      }
   6:  }
這裏靠此Attribute就將二者關聯了起來
現在執行處寫:
   1: var container1 = new UnityContainer()
   2:     .AddNewExtension<Interception>()
   3:     .RegisterType<IOutput, OutputImplement1>();//聲明UnityContainer並註冊IOutput
   4: container1
   5:     .Configure<Interception>()
   6:     .SetInterceptorFor<IOutput>(new InterfaceInterceptor());
   7: var op1 = container1.Resolve<IOutput>();
   8: op1.Output(11);//調用
That’s all OK.
2.用配置文件處理
如果用配置文件的話就不用Attribute了,所以實現的類如下
   1: class OutputImplement2 : IOutput {
   2:     public void Output(int x) {
   3:         Console.WriteLine("重典執行此方法輸出:{0}", x);
   4:     }
   5: }
這裏不使用屬性來標記了,而使用配置文件,我們建一個名爲Unity.xml的配置文件(配置文件長,可以後看):
   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <configSections>
   4:     <section name="unity"
   5:               type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
   6:                  Microsoft.Practices.Unity.Configuration, Version=1.2.0.0,
   7:                  Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
   8:   </configSections>
   9:   <unity>
  10:     <typeAliases>
  11:       <typeAlias alias="singleton"
  12:                  type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
  13:       <typeAlias alias="transparentProxy"
  14:                  type="Microsoft.Practices.Unity.InterceptionExtension.TransparentProxyInterceptor, Microsoft.Practices.Unity.Interception" />
  15:       <typeAlias alias="typeMatchingRule"
  16:                  type="Microsoft.Practices.Unity.InterceptionExtension.TypeMatchingRule, Microsoft.Practices.Unity.Interception"/>
  17:       <typeAlias alias="interception"
  18:                  type="Microsoft.Practices.Unity.InterceptionExtension.Interception, Microsoft.Practices.Unity.Interception"/>
  19:       <typeAlias alias="IOutput" type="ConsoleApplication1.IOutput, ConsoleApplication1" />
  20:       <typeAlias alias="MyHandler" type="ConsoleApplication1.MyHandler, ConsoleApplication1" />
  21:       <typeAlias alias="OutputImplement2" type="ConsoleApplication1.OutputImplement2, ConsoleApplication1" />
  22:     </typeAliases>
  23:     <containers>
  24:       <container name="DefContainer">
  25:         <types>
  26:           <type type="IOutput" mapTo="OutputImplement2" name="">
  27:             <lifetime type="singleton" />
  28:           </type>
  29:         </types>
  30:       </container>
  31:     </containers>
  32:   </unity>
  33: </configuration>
最後我們來執行,要比第一種方法複雜一點:
   1: var container2 = new UnityContainer().AddNewExtension<Interception>();//聲明UnityContainer
   2: var map = new ExeConfigurationFileMap {ExeConfigFilename = "Unity.xml"};//使用此配置文件
   3: var config
   4:    = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
   5: var section
   6:    = (UnityConfigurationSection)config.GetSection("unity");//讀取配置文件節點
   7: section.Containers["DefContainer"].Configure(container2);
   8: container2.Configure<Interception>()
   9:    .SetDefaultInterceptorFor<IOutput>(new TransparentProxyInterceptor())
  10:    .AddPolicy("LogMethod")
  11:    .AddMatchingRule(new TypeMatchingRule("IOutput"))
  12:    .AddCallHandler(typeof(MyHandler));
  13: var op2 = container2.Resolve<IOutput>();
  14: op2.Output(22);//調用
 
OK這時我們看到的結果就是:
image
代碼下載:
[url]http://cid-cbc2ddf168d9da0b.skydrive.live.com/self.aspx/.Public/%e5%85%b1%e4%ba%ab%e4%bb%a3%e7%a0%81/Unity%7C_AOP.rar[/url]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章