C# Unity依賴註入利用Attribute實現AOP功能
使用場景?
很多時候, 我們定義一個功能, 當我們要對這個功能進行擴展的時候, 按照常規的思路, 我們一般都是利用OOP的思想, 在原有的功能上進行擴展。
那麽有沒有一種東西, 可以實現當我們需要擴展這個功能的時候, 在不修改原來的功能代碼的情況下實現, 這就是下面要說的到Unity。
1.準備工作
為項目添加NuGet包, 搜索Unity並且安裝。
在使用的項目中添加Unity的相關引用
using Microsoft.Practices.Unity.InterceptionExtension; using Microsoft.Practices.Unity;
2.假設場景
剛才上面說道, Unity可實現在不修改原功能的情況下, 添加額外的擴展功能。
當我們去做一個用戶註冊的功能, 最初的版本是完成了基本的註冊功能, 後來我們需要擴展了, 給他加上註冊校驗, 日誌處理, 和異常捕捉的幾個功能, 那麽接下來就演示, 如何用Unity給功能擴展。
3.如何使用
首先, 我們定義好一個最原始的註冊功能
public static void Show() { User user = new User() { Name = "Eleven", Password= "123123123123" };
IUserProcessor porcessor = new UserProcessor();
porcessor.RegUser(user); //簡單的用戶註冊
}
public interface IUserProcessor { void RegUser(User user); } public class UserProcessor : IUserProcessor//MarshalByRefObject,{ public void RegUser(User user) { Console.WriteLine("註冊。"); } }
接下來, 我們要對這個註冊進行擴展了, 添加註冊校驗, 日誌處理, 和異常捕捉的幾個功能。
1.先定義3個特性與對應的特性行為實現, 分別是註冊, 日誌, 和異常。
public class UserHandlerAttribute : HandlerAttribute //註冊校驗 { public override ICallHandler CreateHandler(IUnityContainer container) { ICallHandler handler = new UserHandler() { Order = this.Order }; return handler; } } public class LogHandlerAttribute : HandlerAttribute //日誌處理 { public override ICallHandler CreateHandler(IUnityContainer container) { return new LogHandler() { Order = this.Order }; } } public class ExceptionHandlerAttribute : HandlerAttribute //異常處理 { public override ICallHandler CreateHandler(IUnityContainer container) { return new ExceptionHandler() { Order = this.Order }; } }
對應的每個特性的實現行為, 分別實現 註冊校驗, 日誌記錄, 與 異常處理
public class UserHandler : ICallHandler //註冊校驗的行為 { public int Order { get; set; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { User user = input.Inputs[0] as User; if (user.Password.Length < 10) { return input.CreateExceptionMethodReturn(new Exception("密碼長度不能小於10位")); } Console.WriteLine("參數檢測無誤"); IMethodReturn methodReturn = getNext.Invoke().Invoke(input, getNext); return methodReturn; } } public class LogHandler : ICallHandler //日誌處理的行為 { public int Order { get; set; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { User user = input.Inputs[0] as User; string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password); Console.WriteLine("日誌已記錄,Message:{0},Ctime:{1}", message, DateTime.Now); return getNext()(input, getNext); } } public class ExceptionHandler : ICallHandler //異常處理的行為 { public int Order { get; set; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { IMethodReturn methodReturn = getNext()(input, getNext); if (methodReturn.Exception == null) { Console.WriteLine("無異常"); } else { Console.WriteLine("異常:{0}", methodReturn.Exception.Message); } return methodReturn; } }
按照現在思路, 我們要把這上面寫好的幾個功能添加在原來的註冊功能上, 首先, 我們回到最開始定義接口的地方, 給接口添加我們定義按的3個特性
[UserHandlerAttribute(Order = 1)] //註冊校驗 [LogHandlerAttribute(Order = 2)] //日誌處理 [ExceptionHandlerAttribute(Order = 3)] //遺產處理 public interface IUserProcessor { void RegUser(User user); }
//PS: 在上面的特性聲明中, 每個對應的Order 這個屬於排序, 相對於一個行為的執行順序, 這個內部是Unity的一個實現, 所以我們使用的過程中只需要聲明好標量即可。
然後, 我們在定義好的註冊方法中, 首先聲明一個Unity容器UnityContainer , 然後註冊其上面的接口 IUserProcessor, 最後調用其接口的註冊方法。
//聲明一個容器 IUnityContainer container = new UnityContainer(); //聲明UnityContainer並註冊IUserProcessor container.RegisterType<IUserProcessor, UserProcessor>(); container.AddNewExtension<Interception>().Configure<Interception>() .SetInterceptorFor<IUserProcessor>(new InterfaceInterceptor()); IUserProcessor userprocessor = container.Resolve<IUserProcessor>(); userprocessor.RegUser(user); //調用註冊方法。
最後, 我們看一下實際效果, 很輕松的實現了用於註冊時候擴展其他更多的行為
小結:
不難發現, Unity的實現 主要以在接口上定義的特性與實現行為 與其內部Unity容器的結合 實現的AOP功能。
因為上面是屬於靜態的寫法, 便於學習, 真正的實現AOP可動態配置, 在IOC裏會有詳細的介紹。
C# Unity依賴註入利用Attribute實現AOP功能