在前面我們學習到的是Unity依賴注入(DI)與統一容器來松散耦合,這個設計已經對我們系統帶來了很多的好處。但是我們還會想嘗試和遵循單一職責,開放封閉原則。比如我們不應該在我們的Business層去實現日志、校驗、緩存、異常處理等工作,Unity的Interception可以幫助我們橫切關注點(Crosscutting concerns 即AOP),來獨立處理這些關注點。
什么是橫切關注點(AOP)?橫切關注點(AOP)是關注影響應用程序的許多區域。例如,你可能需要將信息寫入日志文件在應用程序許多不同的區域,橫切關注點(AOP)可以幫助你構建一致的應用程序方式與應用程序業務。
常見的LOB應用程序的橫切關注點包括:
1.日記(Log)
2.校驗(Validation)
3.異常處理(Exception handling)
4.瞬時故障處理(Transient fault handling)
5.權限處理(Authentication and authorization)
6.緩存(Caching)
7.性能監控(Performance monitoring)
8.加密(Encryption)
9.映射(Mapping)
10.壓縮(Compression)
在使用Unity.Interception以前我們先自己寫一個簡單的AOP:
1.業務接口
/// <summary> /// 接口 /// </summary> public interface ITalk { void talk(string msg); }
2.業務實現
public class PeopleTalk : ITalk { private string username; private int age; public string UserName { get { return username; } } public int Age { get { return age; } } public PeopleTalk(string userName, int age) { this.username = userName; this.age = age; } public virtual void talk(string msg) { Console.WriteLine(msg + "!你好,我是" + username + ",我的年齡" + age); } }
3.代理對象
public class TalkProxy : ITalk { private ITalk talker; public TalkProxy(ITalk talker) { this.talker = talker; } public void talk(string msg) { talker.talk(msg); } public void talk(string msg, string singName) { talker.talk(msg); sing(singName); } public void sing(string singName) { Console.WriteLine("唱歌:" + singName); } }
4.調用
class Program { static void Main(string[] args) { #region 靜態代理 ITalk people = new PeopleTalk("AOP", 18); people.talk("No ProXY Test!"); Console.WriteLine("---------------------------------"); TalkProxy talker = new TalkProxy(people); talker.talk("ProXY Test", "代理"); #endregion } }
代理模式是一種簡單的AOP,talk是一個切面,我們可以在代理類中添加日志、校驗、異常處理等等。這樣我們就實現了,核心關注點與橫切關注點的分離。正如Avanade公司的高級方案架構師Adam Magee所說,AOP的核心思想就是”將應用程序中的商業邏輯同對其提供支持的通用服務進行分離“。
下面我們來看看
Unity.Interception是如何現實AOP的
1.在Unity中實現IInterceptionBehavior接口
/// <summary> /// Unity為我們提供了一個IInterceptionBehavior接口需要實現這個接口 /// 接口為我們提供了三個方式(GetRequiredInterfaces、Invoke、WillExecute)實現 /// WillExecute表示是否執行該行為,如果是false這個方法被調用時,不會被捕捉。因為我們總是要執行的,所以為true /// GetRequiredInterfaces將你想要的接口類型和行為聯系起來,我們暫時不需要,所以返回Type.EmptyTypes /// Invoke執行方式接口 /// </summary> public class LoggingInterceptionBehavior : IInterceptionBehavior { public bool WillExecute { get { return true; } } public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("Method: {0}", input.MethodBase.Name); Console.WriteLine("參數:"); for (var i = 0; i < input.Arguments.Count; i++) { Console.WriteLine("{0}: {1}", input.Arguments.ParameterName(i), input.Arguments[i]); } Console.WriteLine("執行前"); var result = getNext()(input, getNext);//在這里執行方法 if (result.Exception != null) { //發生錯誤記錄日志 Console.WriteLine(String.Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString())); } Console.WriteLine("執行后"); return result; } }
2.調用
class Program { static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); container.RegisterType<ITalk, PeopleTalk>( new InjectionConstructor("AOP", 18), new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingInterceptionBehavior>()); ITalk talker = container.Resolve<ITalk>(); talker.talk("ProXY Test!"); } }
以上基本完成了簡單的Unity.Interception
當然在Unity中不只有InterfaceInterceptor一種攔截器,它還包含其它兩種攔截器:TransparentProxyInterceptor 與 VirtualMethodInterceptor
這里就不詳細介紹就提一下這三種:
InterfaceInterceptor只要是繼承接口的方法都會被攔截。
TransparentProxyInterceptor只要是繼承類使用的方法都會被攔截。
VirtualMethodInterceptor 意思是虛方法攔截器,繼承類的方法必須是Virtual的,和繼承類必須是公開的。滿足這兩個條件即可
----------------------------------------------------------------------------------------------------------------
同時在這里我還是沒有回答在我
Unity4.0的使用 中“一只老菜鳥”所提的問題,不過我會努力的
以上是本人比較初級的處理,主要用於本人學習Unity的一個記錄